请参阅以下代码:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
final JFrame f=new JFrame("foo");
final JPanel c=new JPanel(null);
f.setContentPane(c);
c.setPreferredSize(new Dimension(500,500));
final JPanel a=new JPanel(null){
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.red);
g.fillRect(0, 0, getWidth(), getHeight());
}
};
a.setBounds(0,0,300,300);
c.add(a);
final JPanel b=new JPanel(null){
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.green);
g.fillRect(0, 0, getWidth(), getHeight());
}
};
b.setBounds(200,200,500,500);
c.add(b);
c.setComponentZOrder(a, 0);
f.pack();
f.setVisible(true);
f.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
b.repaint();
}
});
}
}
它基本上只是在第三个面板上绘制两个面板:面板A(红色)和面板B(绿色)。红色面板A具有较低的z次序,因此涂在面板B上。 现在,如果我们强制面板B重新绘制自己(只需单击面板A和B之外的JFrame),面板B突然在面板A上绘制。
如果我切换到使用JComponent而不是JPanel,它可以正常工作,B不会在A上绘制。看起来JPanel只是忽略了Z顺序。所以,解决方案似乎是使用JComponent而不是JPanel。只是出于好奇 - 这种Z-order忽略行为对于JPanel来说是正常的吗?
答案 0 :(得分:6)
如果我切换到使用JComponent 而不是JPanel,它可以正常工作 和B不会在A上画画。
您的代码告诉红色面板重绘自己,这样做。现在尝试更改JFrame的大小,面板将重新绘制。这是因为Z-Order仅在父面板重新绘制其所有子节点时适用。这就是为什么trashgod的解决方案适用于这种情况。
JComponent的行为方式是因为它是非透明的,因此每当需要重新绘制时,需要首先绘制其父级的背景,以便最终调用Z-Order中的绘制。父母小组。
因此,两者之间的差异是组件的不透明性。
答案 1 :(得分:1)
在鼠标处理程序中尝试c.repaint()
。此外,您无需覆盖paintComponent()
即可更改背景颜色。
public static void main(String[] args) {
final JFrame f = new JFrame("foo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel c = new JPanel(null);
f.setContentPane(c);
c.setPreferredSize(new Dimension(500, 500));
final JPanel a = new JPanel();
a.setBounds(0, 0, 300, 300);
a.setBackground(Color.red);
c.add(a);
final JPanel b = new JPanel();
b.setBounds(200, 200, 300, 300);
b.setBackground(Color.green);
c.add(b);
c.setComponentZOrder(a, 0);
f.pack();
f.setVisible(true);
f.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
c.repaint();
}
});
}