title: Paint over all other components (Swing, Java)
body: <p>In my application I need to draw grid lines just like those like Photoshop has - e.g, an user can drag lines over the document to help him align layers. Now, the problem is that I am able to draw such lines (it's just plain simple Java2D painting using Line2D), but I am not being able to keep such lines on top of everything else, because when children components draw themselves, my grid line is erased. </p>
  
  <p>The program structure is something like this: JFrame -> JPanel -> JScrollPane -> JPanel -> [many others JPanels, which are like layers]</p>
  
  <p>As a test, I added the draw code to JFrame, which correctly shows my Line2D instance on top of everything else. However, when I do anything in an child component that requires that child to repaint itself, the line that was drawn in the JFrame is erased. </p>
  
  <p>I understand that this is the expected Swing behavior - that is, it will only repaint those areas that have changed. However, I am looking for some approach that continuously draws line grid lines on top of everything else. </p>
  
  <p>The only way I was able to get it working was to use a Swing Timer that calls repaint() on my root component every 10ms, but it consumes a lot of CPU. </p>
  
  <p><strong>UPDATE</strong><br>
  Working code of an example is below. Please mind that in my real application I have dozens of different components that could trigger a repaint(), and none of them have a reference to the component that does the grid line drawing (of course I can pass it to everyone, but that appears to be the latest option)</p>
  
  <pre><code>import java.awt.BasicStroke;
  import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.Graphics;
  import java.awt.Graphics2D;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.geom.Line2D;
  
  import javax.swing.JButton;
  import javax.swing.JFrame;
  import javax.swing.JPanel;
  
  public class GridTest extends JFrame {
      public static void main(String[] args) {
          new GridTest().run();
      }
  
      private void run() {
          setLayout(null);
          setPreferredSize(new Dimension(200, 200));
          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
          final JPanel p = new JPanel();
          p.setBounds(20, 20, 100, 100);
          p.setBackground(Color.white);
          add(p);
  
          JButton b = new JButton("Refresh");
          b.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  // When I call repaint() here, the paint() method of
                  // JFrame it's not called, thus resulting in part of the
                  // red line to be erased / overridden.
  
                  // In my real application application, I don't have
                  // easy access to the component that draws the lines
                  p.repaint();
              }
          });
          b.setBounds(0, 150, 100, 30);
          add(b);
  
          pack();
          setVisible(true);
      }
  
      @Override
      public void paint(Graphics g) {
          super.paint(g);
  
          Graphics2D gg = (Graphics2D)g.create();
          Line2D line = new Line2D.Double(0, 50, getWidth(), 50);
          gg.setStroke(new BasicStroke(3));
          gg.setColor(Color.red);
          gg.draw(line);
          gg.dispose();
      }
  }
  </code></pre>