JPanel组件绘制顺序

时间:2010-07-29 09:07:14

标签: java swing

请参阅以下代码:

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来说是正常的吗?

2 个答案:

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