2010-07-29 55 views
1

请参阅下面的代码:JPanel组件绘制顺序

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。出于好奇 - 这个JPanel的Z顺序忽略行为是正常的吗?

+0

谢谢您的意见!其实,要解决这个问题,请阅读:[Swing Painting](http://java.sun.com/products/jfc/tsc/articles/painting/)(找到“Optimized”Drawing),也请阅读:[ isOptimizedDrawingEnabled()](http://download.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#isOptimizedDrawingEnabled()) – 2011-07-10 17:50:45

回答

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

如果我切换到使用替代的JPanel的JComponent ,它工作正常 和B不会画在A.

你的代码是告诉红色面板本身重绘所以确实。现在尝试更改JFrame的大小,并重新绘制面板。这是因为Z-Order仅在父面板重绘其所有子项时才适用。这就是为什么trashgod的解决方案适用于这种情况。

JComponent的行为方式是因为它是非透明的,所以无论何时需要重绘它的父级的背景都需要首先绘制,以便最终调用Z-Order中的绘画的父面板。

所以两者的区别在于组件的不透明性。

+0

优秀;更多讨论可以在“其他涂料属性”中找到:http://java.sun.com/products/jfc/tsc/articles/painting/#props – trashgod 2010-07-30 03:18:17