0

I want to draw line between two JPanels but line is not appearing on layeredPane.

This is what i have done please go through it, compilable.Do try and correct this code. I have tried on drawing lines on Internal frames this way but it is not working for JPanels.

package build;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class LinkLayerPane1 {

    public static void main(String[] args) {
        new LinkLayerPane1();
    }

    public LinkLayerPane1() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JLayeredPane layer = new JLayeredPane();
                JPanel red = new JPanel();
                red.setBackground(Color.RED);
                JPanel blue = new JPanel();
                blue.setBackground(Color.BLUE);

                red.setBounds(50, 50, 50, 50);
                blue.setBounds(125, 125, 50, 50);

                layer.add(red);
                layer.add(blue);

                Point Red= new Point();
                Red.x=red.getX()+(red.getWidth()/2);
                Red.y=red.getY()-(red.getHeight()/2);

                Point Blue= new Point();
                Blue.x=blue.getX()+(blue.getWidth()/2);
                Blue.y=blue.getY()-(blue.getHeight()/2);




                handleDrag(red,Blue);
                handleDrag(blue,Red);
         layer.add(new LinkPane(red, blue), new Integer(JLayeredPane.DEFAULT_LAYER + 1));
         layer.setPreferredSize(new Dimension(250, 250));

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(layer);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class LinkPane extends JPanel {

        private Point startPoint;
        private Point endPoint;

        public LinkPane(JPanel panel1, JPanel panel2) {

            setOpaque(false);

            Point p1 = panel1.getLocation();
            Point p2 = panel2.getLocation();

            startPoint = new Point();
            endPoint = new Point();

            Point from = new Point();
            Point to = new Point();

            if (p1.x < p2.x) {
                from.x = p1.x + (panel1.getWidth() / 2);
                to.x = p2.x + (panel2.getWidth() / 2);
            } else {
                from.x = p2.x + (panel2.getWidth() / 2);
                to.x = p1.x + (panel1.getWidth() / 2);
                startPoint.x = p2.x;
            }
            if (p1.y < p2.y) {
                from.y = p1.y + (panel1.getHeight()/ 2);
                to.y = p2.y + (panel2.getHeight()/ 2);

            } else {
                from.y = p2.y + (panel2.getHeight()/ 2);
                to.y = p1.y + (panel1.getHeight()/ 2);
            }

            int width = Math.max(1, to.x - from.x);
            int height = Math.max(1, to.y - from.y);

            setLocation(from);
            setSize(width, height);

            System.out.println(getBounds());

            if (p1.x < p2.x) {
                startPoint.x = 0;
                endPoint.x = getWidth();
            } else {
                startPoint.x = getWidth();
                endPoint.x = 0;
            }
            if (p1.y < p2.y) {
                startPoint.y = 0;
                endPoint.y = getHeight();
            } else {
                startPoint.y = getHeight();
                endPoint.y = 0;
            }            
        }

  @Override
  protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
  g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
            g2d.dispose();


        }        
    }    

  //Dragging 
    public static void handleDrag(final JPanel Tpanel,final Point to)
     {
        final JPanel p = Tpanel;
            Tpanel.addMouseMotionListener(new MouseMotionAdapter() {

 @Override
 public void mouseDragged(MouseEvent me) {
 me.translatePoint(me.getComponent().getLocation().x, me.getComponent().getLocation().y);

                        //Handling Panel Dragging 
                        p.setLocation(me.getX(), me.getY());

              //Finding new point
                      Point p1 = Tpanel.getLocation();
                      Point p2=to;

                     Point startPoint = new Point();
                     Point endPoint = new Point();

                      Point from = new Point();


       if (p1.x < p2.x) {
         from.x = p1.x + (Tpanel.getWidth() / 2);
         to.x = p2.x + (Tpanel.getWidth() / 2);
             } else {
             from.x = p2.x + (Tpanel.getWidth() / 2);
             to.x = p1.x + (Tpanel.getWidth() / 2);
             startPoint.x = p2.x;
         }
           if (p1.y < p2.y) {
           from.y = p1.y + (Tpanel.getHeight()/ 2);
           to.y = p2.y + (Tpanel.getHeight()/ 2);

           } else {
               from.y = p2.y + (Tpanel.getHeight()/ 2);
               to.y = p1.y + (Tpanel.getHeight()/ 2);
           }
               int width = Math.max(1, to.x - from.x);
               int height = Math.max(1, to.y - from.y);



       if (p1.x < p2.x) {
    startPoint.x = 0;
    endPoint.x = Tpanel.getWidth();
    } else {
    startPoint.x = Tpanel.getWidth();
    endPoint.x = 0;
      }
     if (p1.y < p2.y) {
        startPoint.y = 0;
        endPoint.y = Tpanel.getHeight();
      } else {
               startPoint.y = Tpanel.getHeight();
           endPoint.y = 0;
       }                    


       }

     });
     }    

}
Asd
  • 103
  • 2
  • 12
  • 2
    Consider this [alternative](http://stackoverflow.com/a/3952082/230513). – trashgod May 18 '13 at 22:43
  • Remember, paintComponent will paint UNDER the child components. If you want to paint over the top of them, you should consider using the glass pane or even possibly JXLayer/JLayer. Take a look at [this](http://stackoverflow.com/questions/14804136/connect-jbuttons-visually-via-line/14804252#14804252) for an example of using the glass pane...+1 to trashgod – MadProgrammer May 18 '13 at 22:48

2 Answers2

3

I'm confused. You extend your class from JDesktop, but then proceed to add it to a JLayedPane...JDesktop extends.

Without a layout manger by default, the JDesktopPane will be added to the JLayeredPane with a size of 0x0..

I'm not sure what you hoped to achieve by this.

Update with example

The problem(s) you are facing is that paintComponent will always paint under the components, while paint in theory will paint over the components, it can be excluded from updates (as the RepaintManager can go direct the component that needs to be updated).

While I still think using the glass pane is the simplest solution, as demonstrated here, you could simply take advantage of the layer pane by adding a "connect" pane that draws a line from one point to another and simply add it to the LayeredPane...

enter image description here

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class LinkLayerPane {

    public static void main(String[] args) {
        new LinkLayerPane();
    }

    public LinkLayerPane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JLayeredPane layer = new JLayeredPane();
                JPanel red = new JPanel();
                red.setBackground(Color.RED);
                JPanel blue = new JPanel();
                blue.setBackground(Color.BLUE);

                red.setBounds(50, 50, 50, 50);
                blue.setBounds(125, 125, 50, 50);

                layer.add(red);
                layer.add(blue);

                layer.add(new LinkPane(red, blue), new Integer(JLayeredPane.DEFAULT_LAYER + 1));
                layer.setPreferredSize(new Dimension(250, 250));

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(layer);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class LinkPane extends JPanel {

        private Point startPoint;
        private Point endPoint;

        public LinkPane(JPanel panel1, JPanel panel2) {

            setOpaque(false);

            Point p1 = panel1.getLocation();
            Point p2 = panel2.getLocation();

            startPoint = new Point();
            endPoint = new Point();

            Point from = new Point();
            Point to = new Point();

            if (p1.x < p2.x) {
                from.x = p1.x + (panel1.getWidth() / 2);
                to.x = p2.x + (panel2.getWidth() / 2);
            } else {
                from.x = p2.x + (panel2.getWidth() / 2);
                to.x = p1.x + (panel1.getWidth() / 2);
                startPoint.x = p2.x;
            }
            if (p1.y < p2.y) {
                from.y = p1.y + (panel1.getHeight()/ 2);
                to.y = p2.y + (panel2.getHeight()/ 2);

            } else {
                from.y = p2.y + (panel2.getHeight()/ 2);
                to.y = p1.y + (panel1.getHeight()/ 2);
            }

            int width = Math.max(1, to.x - from.x);
            int height = Math.max(1, to.y - from.y);

            setLocation(from);
            setSize(width, height);

            System.out.println(getBounds());

            if (p1.x < p2.x) {
                startPoint.x = 0;
                endPoint.x = getWidth();
            } else {
                startPoint.x = getWidth();
                endPoint.x = 0;
            }
            if (p1.y < p2.y) {
                startPoint.y = 0;
                endPoint.y = getHeight();
            } else {
                startPoint.y = getHeight();
                endPoint.y = 0;
            }            
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
            g2d.dispose();
        }        
    }    
}

Now with dragging

Remember, mouse events a relative to the component that MouseListener is registered to. That is, if you register the MosueListener to any of the components within the JLayeredPane, the mouse events will be translated to be relative to there coordinate space. This can make life a little confusing.

This example makes two significant changes.

  1. It adds a Mouse/MotionListener to the JLayeredPane. This listener then deals with figuring out what was clicked and managing the process
  2. Moves the "setup" code for the LinkPane to a updateLinks method. The LinkPane then registers a ComponentListener to each of the panels it is linking to and updates the link when there position or size changes...

    import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException;

    public class LinkLayerPane {

    public static void main(String[] args) {
        new LinkLayerPane();
    }
    
    public LinkLayerPane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }
    
                JLayeredPane layer = new JLayeredPane();
                JPanel red = new JPanel();
                red.setBackground(Color.RED);
                JPanel blue = new JPanel();
                blue.setBackground(Color.BLUE);
    
                red.setBounds(50, 50, 50, 50);
                blue.setBounds(125, 125, 50, 50);
    
                layer.add(red);
                layer.add(blue);
    
                layer.add(new LinkPane(red, blue), new Integer(JLayeredPane.DEFAULT_LAYER + 1));
                layer.setPreferredSize(new Dimension(250, 250));
    
                MouseAdapter ma = new MouseAdapter() {
                    private Point offset;
                    private Component dragComponent;
    
                    @Override
                    public void mousePressed(MouseEvent e) {
                        JLayeredPane layer = (JLayeredPane) e.getComponent();
                        dragComponent = layer.getComponentAt(e.getPoint());
                        if (dragComponent != null && !dragComponent.equals(layer) && !(dragComponent instanceof LinkPane)) {
                            offset = e.getPoint();
                            offset.x = dragComponent.getX() - offset.x;
                            offset.y = dragComponent.getY() - offset.y;
                        } else {
                            dragComponent = null;
                        }
                    }
    
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        dragComponent = null;
                        offset = null;
                    }
    
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        if (dragComponent != null) {
                            Point dragTo = e.getPoint();
                            dragTo.x += offset.x;
                            dragTo.y += offset.y;
                            dragComponent.setLocation(dragTo);
                        }
                    }
                };
    
                layer.addMouseListener(ma);
                layer.addMouseMotionListener(ma);
    
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(layer);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
    
    public class LinkPane extends JPanel {
    
        private Point startPoint;
        private Point endPoint;
        private JPanel[] links;
    
        public LinkPane(JPanel panel1, JPanel panel2) {
    
            setOpaque(false);
    
            links = new JPanel[]{panel1, panel2};
    
            ComponentAdapter ca = new ComponentAdapter() {
                @Override
                public void componentMoved(ComponentEvent e) {
                    updateLinks();
                }
    
                @Override
                public void componentResized(ComponentEvent e) {
                    updateLinks();
                }
            };
    
            links[0].addComponentListener(ca);
            links[1].addComponentListener(ca);
    
            updateLinks();
    
        }
    
        protected void updateLinks() {
    
            Point p1 = links[0].getLocation();
            Point p2 = links[1].getLocation();
    
            startPoint = new Point();
            endPoint = new Point();
    
            Point from = new Point();
            Point to = new Point();
    
            if (p1.x < p2.x) {
                from.x = p1.x + (links[0].getWidth() / 2);
                to.x = p2.x + (links[1].getWidth() / 2);
            } else {
                from.x = p2.x + (links[1].getWidth() / 2);
                to.x = p1.x + (links[0].getWidth() / 2);
                startPoint.x = p2.x;
            }
            if (p1.y < p2.y) {
                from.y = p1.y + (links[0].getHeight() / 2);
                to.y = p2.y + (links[1].getHeight() / 2);
    
            } else {
                from.y = p2.y + (links[1].getHeight() / 2);
                to.y = p1.y + (links[0].getHeight() / 2);
            }
    
            int width = Math.max(1, to.x - from.x);
            int height = Math.max(1, to.y - from.y);
    
            setLocation(from);
            setSize(width, height);
    
            System.out.println(getBounds());
    
            if (p1.x < p2.x) {
                startPoint.x = 0;
                endPoint.x = getWidth();
            } else {
                startPoint.x = getWidth();
                endPoint.x = 0;
            }
            if (p1.y < p2.y) {
                startPoint.y = 0;
                endPoint.y = getHeight();
            } else {
                startPoint.y = getHeight();
                endPoint.y = 0;
            }
    
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
            g2d.dispose();
        }
    }
    

    }

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • i want to create a line between two points on a JLayeredPane ; a simple code might help me. – Asd May 19 '13 at 10:08
  • but my objects i.e. JPanels are on JLayeredPane !! and i want to draw line connecting 2 panels but i failed to provide layerings to panels and the line..............layeredPane.add(g2d.draw(new Line2D.Float(startPoint, endPoint)),new Integer(2))...............this is not working – Asd May 19 '13 at 10:20
  • I don't know where you got your reference to `g2d` from, but `draw` returns `void`, which means it can't be used by `JLayeredPane#add` as it expects a `Component` – MadProgrammer May 19 '13 at 11:02
  • is their other way to add it to JLayeredPane ? – Asd May 19 '13 at 11:22
  • By *"other way"*, what do you mean? What parts of the example aren't working for you? – MadProgrammer May 19 '13 at 11:31
  • You don't want much do you ;) – MadProgrammer May 20 '13 at 20:43
  • please have a look at what i have tried to create the drag function; I have Added that Function into the code. Do check and correct me as i was able to achieve JPanels to drag but the Line is not following the JPanel's movement – Asd May 20 '13 at 21:57
  • I'm not at a PC at the moment. I will look at it when I have time – MadProgrammer May 20 '13 at 21:58
  • i have tried to make a drag function panel dragging is achieved but i couldnot implement the repaint function do check the updated code – Asd May 22 '13 at 03:28
  • Sorry, 1 year old who doesn't want to sleep not make much to code :P – MadProgrammer May 22 '13 at 04:18
  • what ?! how to repaint ? i wrote repaint at the end after finding new start and end points but it didnt work! – Asd May 22 '13 at 04:22
  • `setLocation` should be triggering a `componentMoved` event which the container should be listening to and automatically calling `repaint`...as I understand it... – MadProgrammer May 22 '13 at 04:31
  • but line is not repainting itself – Asd May 22 '13 at 04:46
  • :: What if i want to draw this dashed line .........Line line1 = new Line(20, 40, 270, 40); line1.getStrokeDashArray().addAll(25d, 20d, 5d, 20d); What changes should i do ? just the tell me about change drawLine to this line – Asd May 31 '13 at 06:36
  • 1
    What is `Line`? Take a look at [Stroking and Filling Graphics Primitives](http://docs.oracle.com/javase/tutorial/2d/geometry/strokeandfill.html) – MadProgrammer May 31 '13 at 06:38
  • see this he has implemented dashed line .[example](http://stackoverflow.com/questions/12786363/javafx-2-x-how-to-draw-dashed-or-dotted-lines) – Asd May 31 '13 at 09:03
2

It looks to me like you saw trashgod's example and are trying to modify it.

If you want to use a desktop pane like the example does, then use the code from the example. Don't try to mix in a JLayeredPane.

If you want to use a JLayeredPane, then don't use a JDesktopPane to do your custom painting of the line joining two components. A desktop pane is a container used to hold other components. If you want to do custom painting then use a more appropriate component. You can override the paintComponent() method of any component so in this case you could do your custom painting in a JComponent.

Before attempting to play with a JLayeredPane read the Swing tutorial on How to Use Layered Panes. You don't just add components to a layered pane. You need to specify the component and an Integer value. The integer value is used to determine the order of the layering. So if you want to add 3 components to 3 different layers then you need to specify 3 different integers. Or maybe you create a panel with your two components and then a second panel to draw the line connection.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • this was the answer i was looking for !! – Asd May 19 '13 at 07:05
  • please help im trying to implement you idea but didnt achive anything ! how to draw line and i also couldnot assign layer's level to ..... g2d.draw(new Line2D.Float(startPoint, endPoint)).... by.................. layeredPane.add(g2d.draw(new Line2D.Float(startPoint, endPoint)),new Integer(2)) – Asd May 19 '13 at 09:55
  • just tell me how to draw a simple line on a JLayeredPane when 2 points are given ! – Asd May 19 '13 at 10:06
  • You don't draw anything on a JLayeredPane. A layered pane is just a container. As I suggested you can extend JComponent, override the paintComponent() method and add this component to the layered pane. The paintComponent() code will be the same as you already have. When you add a component to a layered pane you need to set the size of the component. The Swing tutorial shows you how to do all this. If you have a problem then post your SSCCE showing the code. – camickr May 19 '13 at 18:14
  • please have a look at what i have tried to create the drag function; I have Added that Function into the code. Do check and correct me as i was able to achieve JPanels to drag but the Line is not following the JPanel's movement – Asd May 20 '13 at 21:59
  • 1) code doesn't complie, 2) code looks nothing like the suggestions I made in the posting you deleteted, so I'm just wasting my time trying to give advice. – camickr May 21 '13 at 00:04
  • Compilable code :: have implemented dragging of JPanels but having confusions how to repaint the line. P.s. i also got the new starting and endpoint as well as startPoint and endPoint. Sorry i accidently pasted the wrong code – Asd May 21 '13 at 16:16