JPanel组件绘制顺序

Mar*_*sny 1 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();
        }
    });
    }
}
Run Code Online (Sandbox Code Playgroud)

它基本上只是在第三个面板上绘制两个面板:面板A(红色)和面板B(绿色).红色面板A具有较低的z顺序,因此涂在面板B上.现在,如果我们强制面板B重新绘制自己(只需点击JFrame,在面板A和B之外),面板B突然涂上了OVER小组A.

如果我切换到使用JComponent而不是JPanel,它可以正常工作,B不会在A上绘制.看起来JPanel只是忽略了Z顺序.所以,解决方案似乎是使用JComponent而不是JPanel.只是出于好奇 - 这种Z-order忽略的行为是否适用于JPanel?

cam*_*ckr 6

如果我切换到使用JComponent而不是JPanel,它可以正常工作,B不会在A上绘制.

你的代码告诉红色面板重新绘制它自己.现在尝试更改JFrame的大小,面板将重新绘制.这是因为Z-Order仅在父面板重新绘制其所有子节点时适用.这就是为什么trashgod的解决方案适用于这种情况.

JComponent的行为方式是因为它是非透明的,所以每当需要重新绘制时,需要首先绘制其父元素的背景,以便最终调用父元素的Z-Order中的绘制.

所以两者之间的区别在于组件的不透明性.