Drawing a selection box using Swing - java

I have written an application with a panel and three buttons. I want to add selection this buttons using the mouse. I mean like we have in Windows on the Desktop. I press the left mouse button and with the movement of the mouse the area selection is growing.
Is there a specific interface in this or do I have it manually call the appropriate methods for event listeners and there draw transparent rectangle? Here is a picture:
So I have a problem when I paint rectangle using event mouse-dragged, button is repainting so user see blinking button. I want to this button don't disapear when I paint rectangle. I think that I need to use glassPane. This is my conception. I have a frame. In frame I add panel with button and I need another panel where I will paint transparent rectangle. I am thinking then my button will not be still repainting. What do you think about this conception. Or maybe someone have another idea. This is code:
#Override
public void mousePressed(MouseEvent e) {
startPoint=e.getPoint();
setOpaque(true);
Graphics2D g2 = (Graphics2D)getGraphics();
Rectangle2D prostokat = new Rectangle2D.Double();
prostokat.setFrameFromDiagonal(e.getPoint().x, e.getPoint().y,startPoint.x, startPoint.y);
g2.setComposite(AlphaComposite.getInstance(rule, alpha));
g2.draw(prostokat);
g2.setColor(Color.BLUE);
g2.fill(prostokat);
}
#Override
public void mouseDragged(MouseEvent e) {
setOpaque(true);
Graphics2D g2 = (Graphics2D)getGraphics();
Rectangle2D prostokat = new Rectangle2D.Double();
prostokat.setFrameFromDiagonal(e.getPoint().x, e.getPoint().y,startPoint.x, startPoint.y);
g2.setComposite(AlphaComposite.getInstance(rule, alpha));
g2.draw(prostokat);
g2.setColor(Color.BLUE);
g2.fill(prostokat);
paintComponent(g2);
}
int rule = AlphaComposite.SRC_OVER;
float alpha = 0.85F;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable()
{
public void run()
{
zaznacz rys = new zaznacz();
JFrame frame = new JFrame();
JButton Button = new JButton("1");
JPanel panel = new JPanel();
panel.add(Button);
rys.add(panel);
frame.setSize(400,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setOpaque(false);
frame.add(rys);
}
});
}
}
I know that code is no perfect but almost work. I have a little problem. When I press the mousebutton and dragging my button disapear.
I don't need advise like "your code is wrong". I know that and I want to somebody help me what I must correct. I know that I shouldn't use paintComponent() in mouseEvents but only that way I can paint transparent rectangle. Or maybe you can othet idea how I can draw transparent rectangle. I try and try and I think that i must change mouseDragged method. because when I delete code from this method and only draw rectangle over a button all is ok. But problem is when I need draw rectangle by dragging mouse. I should change paint but I don't have idea how. Anyone can help me or try help me?

I think that that code doesn't works in this forms(main), maybe someone will debug that for you, please follows with Joey's advices
hmmm very offensive words, anyway follows (Oracle Java tutorial) http://download.oracle.com/javase/tutorial/uiswing/misc/trans_shaped_windows.html

Related

GUI application that the shape changes on a radio button click

What my application is meant to do is change the background and foreground on a click of a radio button and change the shape of the item based on a radio button.I am trying to get my application to actively change shape based on the radio button that is selected.I have the background and foreground working just not the shape. I have seen another post kinda like this but it has a submit button and does not use the JSlider
Below is what I have been messing with and cannot seem to get the program to execute correctly. I have gotten the shape to change but then the slider breaks. Am i approaching this the wrong way?
public class OvalPanel extends JPanel
{
private int diameter = 10; // default diameter
// draw an oval of the specified diameter
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(rectFillRadioButton.isSelected()){
g.fillRect(10,10,10,10);
//repaint();
}
if(ovalFillRadioButton.isSelected()){
g.fillOval(10,10,10,10);
//repaint();
}
}
// validate and set diameter, then repaint
public void setDiameter(int newDiameter)
{
// if diameter invalid, default to 10
diameter = (newDiameter >= 0 ? newDiameter : 10);
repaint(); // repaint panel
}
// used by layout manager to determine preferred size
public Dimension getPreferredSize()
{
return new Dimension(200, 200);
}
// used by layout manager to determine minimum size
public Dimension getMinimumSize()
{
return getPreferredSize();
}
}
this is the class that i initially have that sets the paintComponent. I also have
private class TopRadioButtonHandler extends JFrame implements ItemListener {
private Graphics panel;
public TopRadioButtonHandler(Graphics p) {
panel = p;
}
#Override
public void itemStateChanged(ItemEvent event) {
if(rectFillRadioButton.isSelected()){
panel = myPanel.getGraphics();
panel.fillRect(10,10,10,10);
repaint();
}
if(ovalFillRadioButton.isSelected()){
panel = myPanel.getGraphics();
panel.fillOval(10,10,10,10);
repaint();
}
}
}
i dont think i need the repaint but when i use this method my JSlider stops working.
Am i approaching this the wrong way?
Yes, the paintComponent() method should not be referencing another Swing component.
When you do custom painting, the paintComponent() should only paint the current state of your component.
For example when you use a Jlabel you have methods like setText() and setIcon() to set the text and icon you want to paint.
You already have a method, setDiameter() which is a good start. However, your painting code just hard codes the size of the oval/rectangle. The painting methods should reference you diameter variable.
Now, you need another property to idicate whether to paint an oval or a rectangle. So maybe you need a property like setPaintOval(boolean paintOval).
Then your painting code could be:
If (paintOval)
g.fillOval(10, 10, diameter, diameter);
else
g.fillRect(10, 10, diameter, diameter);
Of course the problem with this approach is that you can only paint two objects.
Also, you should never invoke repaint() in a painting method. The repaint() should only be invoked from your setter methods when you change the state of the component.
but then the slider breaks
The code you posted has nothing to do with a slider.
I'm guessing you want the slider to change the diameter of the oval? Well you need to add a ChangeListener to the slider and then invoke your setDiameter() method with the slider value.
Read the section from the Swing tutorial on How to Use Sliders for a working example.

How can I remove all lines while Drawing in jPanel in java?

I'm trying to make a Paint program using java , I have three events in the jPanel to draw my line.
my problem is that when I am drawing the new line , the first one removed (I think the problem in the dragged event!) .. and so on.
Note that while the mouse is dragged the line will be stucked to the mouse
here is my events code:
private void jPanel1MousePressed(java.awt.event.MouseEvent evt) {
g1=(Graphics2D) jPanel1.getGraphics();
p1=jPanel1.getMousePosition();
}
JLayer lpane;
private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {
if(p1!=null){
lpane = new JLayer();
jPanel1.add(lpane, BorderLayout.CENTER);
lpane.setBounds(0, 0, 328, 257);
g2=(Graphics2D) lpane.getGraphics();
l=new Line(p1.x,p1.y,jPanel1.getMousePosition().x,jPanel1.getMousePosition().y);
l.draw(g2);
//lpane.repaint();
lpane.setVisible(false);
lpane.removeAll();
lpane.disable(); jPanel1.remove(lpane);
}
}
private void jPanel1MouseReleased(java.awt.event.MouseEvent evt) {
if(p1!=null)
{
g1=(Graphics2D) jPanel1.getGraphics();
p2=jPanel1.getMousePosition();
l=new Line(p1.x,p1.y,p2.x,p2.y);
g1.setColor(Color.red);
l.draw(g1);
p1=null;
}
}
Graphics2D g1,g2; Point p1=null,p2=null; Line l;
getGraphics is not how painting should be done in Swing, instead override the panels paintComponent and paint your components state there.
The paintComponent method needs to know what to paint whenever it is called, as it may be called any number of times, many times without your interaction or knowledge.
One approach is to build a List of shapes or Points, which can then be looped through and painted each time paintComponent is called. The benefit of this is you can remove these shapes/points should you wish.
See Pinting in AWT and Swing and Performing Custom Painting for more detals
Also take a look at this example for an idea
The usual way of doing this is to create a (Buffered)Image the size of your Component, fill the background color, and then draw each new line on the Image as well. In your paintComponent method, all you call is g.drawImage(...);
In your panel:
public void paintComponent(Graphics g) {
if (mSizeChanged) {
handleResize();
}
g.drawImage(mImg, 0, 0, null);
}
In your MouseMotionListener:
public void mouseDragged(MouseEvent me) {
Graphics g = mImg.getGraphics();
Point p = me.getPoint();
g.drawLine(mLastPoint.x, mLastPoint.y, p.x, p.y); }

Border affects components position java

So I have a JPanel that has an inner border (it's toggled based on MouseEnter/MouseExit, as a sort of a rollover effect). I also have a JLabel. The problem is that the JLabel seems to be positioned relative to the border - not the actual edge of the JPanel. So whenever I move my mouse over the panel, the label shifts over a couple of pixels. I would prefer it to stay stationary.
So I guess my question is, what's the best way to change the border of a panel without affecting the positions of the components inside the panel?
Here's the mouselisteners for the panel:
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
panel.setBorder(BorderFactory.createBevelBorder(1, Color.BLACK, Color.BLACK));
}
#Override
public void mouseExited(MouseEvent e) {
panel.setBorder(null);
}
});
The JLabel is added simply using borderlayout:
panel.setLayout(new BorderLayout());
JLabel label = new JLabel("testlabel");
panel.add(label,BorderLayout.PAGE_END);
You could try using an EmptyBorder when the bevel border is not in use. Give it the same width/height you would the bevel border.
I don't do a lot of messing around with layouts or their managers but that's what I would try.
Edit
Since it seems you may wish to have an overlay type effect instead of a border, you could create a custom JPanel class and include some code in the paintComponent(Graphics g) method to draw this overlay.
Something similar to:
public class OverlayBorderJPanel extends JPanel
{
boolean containsMouse = false; //set to true by mouseListener when contains
BufferedImage overlay = //you would need to load an image border here,
//rather than having a java created border
//You could have alpha so it is half see-through
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (containsMouse)
{
g.drawImage(//use 0,0 position with panel width/height)
}
}
}
I think it would work with something like that, but you may need to call the panel's repaint() method in the listener as well.

Creating a JToolTip-like Component

I'm writing a custom component that displays some bioinformatics data, and I'd like to be able to show additional information about the location the mouse is at when the user holds down a certain key. This seems like an obvious job for a tooltip, but there are a few problems that seem to be preventing this from working. First, I want to have the tooltip follow the mouse and change its text dynamically. This works somewhat by overriding getToolTipText and getToolTipLocation for the component, but the tooltip flickers as the mouse position is updated and doesn't display over the sub-components (it's a JPanel with some JTextPanes inside it). I also don't think there's any way to make it display immediately without a call to the ToolTipManager, which I believe would change the delay for all other components.
It looks like there are workarounds for some of these problems, but they're rather complicated and inelegant so I'm thinking a good solution would be to just create my own component, fill it with the relevant information and show it myself. However, this needs to be some kind of top-level component because it needs to be able to extend slightly beyond the borders of the parent component or even the containing JFrame and be drawn over everything else. The only objects I know of that have this functionality outside of JToolTip are JFrame and JDialog, which have borders with titles and close buttons which I don't want. Is there some way to accomplish this?
One option is to use a glass pane. In this case your tooltip won't be able to go outside of the frame, but you can easily position it relative to how near it is to a side of the frame. Some example code that draws a bubble (which you can fill with text in the paint method) that follows the mouse.
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(new Dimension(500, 500));
JPanel glassPane = new JPanel();
glassPane.setOpaque(false);
glassPane.setLayout(null);
frame.setGlassPane(glassPane);
frame.getGlassPane().setVisible(true);
final MyInfoBubble mib = new MyInfoBubble();
mib.setBounds(10, 30, 100, 50);
((JPanel)frame.getGlassPane()).add(mib);
frame.getContentPane().addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent me) {
mib.setBounds(me.getPoint().x, me.getPoint().y, 100, 50);
}
});
((JPanel)frame.getGlassPane()).validate();
((JPanel)frame.getGlassPane()).repaint();
frame.setVisible(true);
}
static class MyInfoBubble extends JPanel
{
public MyInfoBubble()
{
setVisible(true);
}
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 20, 20);
}
}

ActionListener doesn't work properly after drawing line in java

I have a problem with an action listener after I draw a line, basicly it works just one time, for example, my application is downloading an image, than u pick two points, first with left button mouse, second with right button, than u click "connect points" button, and it is drawing a line. And this works, I can do it with many lines etc. BUT when I close an window with image and reload it the "connect points" button stops working. Dk what to do with it. Here is the code:
the painting line part:
public void paint(Graphics g) {
super.paint(g);
myPaint(g);
}
private void myPaint(Graphics g) {
g.drawLine(lx1, ly1, px2, py2);
}
}
ActionListener part:
public void actionPerformed(ActionEvent e) {
if(e.getSource()==painterka){
Graphics g = imadzysko.getGraphics();
paint(g);
lx1=0;
ly1=0;
px2=0;
py2=0;
}
}
Panel with graphic part:
void diagramKY (JFrame windower, String tyt, String content) {
Listener listener = new Listener();
panelik.setLayout(null);
painterka = new JButton("Connect Points");
windower = new JFrame("");
windower.setTitle(tyt+" - diagram");
windower.setSize(800, 600);
windower.setVisible(true);
windower.setLocationRelativeTo(null);
URLdownloader.fileUrl("http://stooq.pl/c/?s="+content+"&c=1d&t=l&a=lg",
content+".png","");
imadzysko = new ImagePanel(new ImageIcon(content+".png").getImage());
panelik.add(imadzysko);
panelik.add(painterka);
imadzysko.addMouseListener(new MyMouseListener());
painterka.addActionListener(listener);
Insets insets = panelik.getInsets();
Dimension size = imadzysko.getPreferredSize();
imadzysko.setBounds(20 + insets.left, 20 + insets.top,
size.width, size.height);
size = painterka.getPreferredSize();
painterka.setBounds(630 + insets.left, 20 + insets.top,
size.width, size.height);
panelik.repaint();
imadzysko.repaint();
windower.add(panelik);
well, any suggestions? :)
1) create panel, put that to the GUI and last code lines would be
windower.setLocationRelativeTo(null);
windower.setVisible(true);
otherwiese your panel never will be visible on the screen
2) don't use setBounds() etc.., for that is there exists LayoutManagers
windower.add(panel);
then your panel fill whole JFrame area
3) never use paint(Graphics g) in the Swing Code, use only paintComponent(Graphics g) to avoids un-expected output to the GUI
4) don't create new Top-level Containers on Runtime, for popup window create only one JDialog or JWindow and re-use that for another Action
5) you have problems with Concurency in Swing, your GUI freeze, because waiting for hard and longtime code, implements SwingWorker, there is similair example about that
6) if you want to display some pictures or images look for Icon placed in the JLabel
7) really required to read 2D Graphics tutorial before posting question here
Graphics g = imadzysko.getGraphics();
Never do that. A Java GUI should paint when told to do so. When that time comes, the paint(Graphics) or paintComponent(Graphics) will be called. Do the painting then.

Categories