1

I have a JScrollPane that fills a JPanel (which is the content pane for my JFrame). The JPanel performs custom drawing - however, it doesn't appear over top of the JScrollPane. Should I override something other than paintComponent?

Here is a demo:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.LayoutManager;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class Test {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                // Create the frame.
                JFrame frame = new JFrame();
                frame.setPreferredSize(new Dimension(1024, 768));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                JPanel custom = new CustomPanel(new BorderLayout());
                // Add the scroll pane.
                JScrollPane scroll = new JScrollPane();
                scroll.setBorder(BorderFactory.createLineBorder(Color.blue));
                custom.add(scroll, BorderLayout.CENTER);

                // Display the frame.
                frame.setContentPane(custom);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }
}

@SuppressWarnings("serial")
class CustomPanel extends JPanel {

    public CustomPanel(LayoutManager lm) {
        super(lm);
    }

    @Override
    public void paintComponent(Graphics g) {
        g.setColor(Color.red);
        g.drawRect(200, 200, 200, 200);
    }

}
sdasdadas
  • 23,917
  • 20
  • 63
  • 148

4 Answers4

3

I'd like for the paint on the JPanel to go over top of the paint on the JScrollPane

you can to paint to the

  • JViewport as you can to see here and here

  • use JLayer(Java7) based on JXlayer(Java6)

  • very similair (as todays JLayer) is painting to GlassPane, notice GlassPane to consume()(by default) MouseEvent in the case there is(are) added some JComponent(s), GlassPane can to covers whole RootPane or only part of available Rectangle, depends of used LayoutManager and Dimension returns from layed JComponent(s)

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
0

Just a simple problem. You are adding the scrollpane to the custompanel which is hiding what your are drawing. Instead, consider intializing your scrollpane with the cutsompanel as its content.

Example:

JScrollPane scrlPane = new JScrollPane(customPanel);
Mitch Connor
  • 766
  • 10
  • 19
  • I'm not sure if this will present exactly the same solution. In the actual problem (that's too big for a demo), the scroll pane is third party and contains other components. I would like to overlay drawings on top - but I'm not sure that I can work inside of it. – sdasdadas May 24 '13 at 18:50
0

when you add a single component to a BorderLayout and specify BorderLayout.CENTER, the component will expand to completely fill its parent. If the component is opaque, you won't be able to see any custom painting you are doing in the parent.

Dan O
  • 6,022
  • 2
  • 32
  • 50
  • I understand that it will fill completely (that's desired), but why won't my panel paint over top? Does the order go 1. children, 2. yourself, or does it go 1. yourself 2. children? If the latter, is there a way to reverse that painting order? – sdasdadas May 24 '13 at 18:52
  • your panel isn't painting for two reasons: (1) your `JScrollPane`'s `JViewport` is opaque, which hides what's underneath, and (2) your `paintComponent` method draws an unfilled rectangle 0 pixels in size :) try calling `scroll.getViewport().setOpaque(false);` and fixing your `paintComponent` method and let me know if that works. – Dan O May 24 '13 at 19:02
  • and yes, a component gets painted before any of its children get painted. If you want the opposite behavior, I guess you can override `paintComponent` - have the first line of the method be `super.paintComponent();` and then below that do whatever else you want to. – Dan O May 24 '13 at 19:05
  • I don't think those suggestions are correct: the paintComponent method does draw a red rectangle underneath (just not filled in), and calling super.paintComponent() first doesn't work - although I understand it as you do... – sdasdadas May 24 '13 at 19:07
  • You were partially right about the viewport (see my comment up above). Thanks! – sdasdadas May 24 '13 at 19:10
0

The way that worked (as @mKorbel suggested) is to play with the JViewport:

scroll.setViewport(new CustomViewPort());

where CustomViewPort is a class extending JViewport that overrides the paintComponent method.

sdasdadas
  • 23,917
  • 20
  • 63
  • 148