Search code examples
javaswinggraphics2drepaintjlayeredpane

Line not appearing on JDesktopPane


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;
       }                    


       }

     });
     }    

}

Solution

  • 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();
          }
      }
      

      }