So, what I "think" you have is a fundamental misunderstanding how, well, everything works in Swing.
You "seem" to be having an issue with how the layout management system works, how the painting system works and how the coordinate system works
Let's start with your Dr
component.
You seem to want to develop overlapping components, which can show the child components below them, but you use setOpaque(true);
, which means that the component won't be see through
This...
public void draw() {
if (buffer == null && width > 0 && height > 0) {
buffer = new BufferedImage(width, height, java.awt.image.BufferedImage.TYPE_INT_ARGB);
}
if (buffer == null) return;
Graphics g = buffer.getGraphics();
setBounds(0, 0, full_width, full_height);
Graphics2D g2d = (Graphics2D)g;
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, full_width, full_height);
g2d.setColor(new Color(255, 0, 80, 128));
g2d.fillRect(left, top, width, height);
System.out.println(left + ", " + top);
}
Seems odd to me. You define the BufferedImage
to be sized as width
by height
, but then use full_width
and full_height
to fill it...it seems, to me, to make more sense to do it the other way round
@Override
public void repaint() {
draw();
}
Okay, important lesson in Swing, you don't control the paint process, so don't try. Swing has a well documented and well established painting process that provides well defined hooks into which you can inject your custom painting (ie paintComponent
). If you need "control", then you need to look towards using a BufferStrategy
, which will give you complete control to define you're own painting process.
Okay, so what's the answer?
Well, that's not so straight forward, because I'm not 100% sure I understand what the problem is you're trying to solve is.
But, let's start with the Dr
panel...
public class Dr extends JPanel {
public Dr(int x, int y, int w, int h, int fw, int fh) {
left = x;
top = y;
width = w;
height = h;
full_width = fw;
full_height = fh;
setOpaque(false);
setBounds(x, y, fw, fh);
}
public void draw() {
if (buffer == null && width > 0 && height > 0) {
buffer = new BufferedImage(getWidth(), getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB);
}
Graphics g = buffer.getGraphics();
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(255, 0, 80, 128));
g2d.fillRect(0, 0, width, height);
g2d.dispose();
}
@Override
public void paintComponent(Graphics g) {
draw();
g.drawImage(buffer, 0, 0, this);
g.setColor(Color.RED);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
}
private BufferedImage buffer;
private int left;
private int top;
private int width;
private int height;
private int full_width;
private int full_height;
}
So, here, I've changed it so that the panel will be positioned at the x
, y
position you pass to the constructor and will be sized to the fw
and fh
properties.
In the draw
method, I then create a BufferedImage
sized to the component's current size and paint ... what ever ... based on the width
and height
properties ... questions are raised about why we have to sizes, but, there it is...
The buffer is then draw to the top/left position of the component, this is important, Swing's coordinate system is based around the component itself, so 0x0
is always the top/left corner of the component, the coordinate system has nothing to do with the parent container.
ps- The red rectangle is for debugging purposes, you don't need it.
I then use...
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new JLayeredPane());
frame.add(new Dr(10, 10, 180, 180, 200, 200));
frame.add(new Dr(100, 100, 180, 180, 200, 200));
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
And voila, overlapping components...
Now, I strongly recommend that you stop and go have a read through:
And, my gut feeling is, you probably really don't want separate components, what you want is one component which can paint many buffers