我有一个JFrame,其中包含2个JPanel子类和BorderLayout中的2个JLabel.其中一个JPanel包含JButtons,另一个用于显示图形. JLabels位于北部和南部,西部是JPanel按钮,中间是JPanel.
显示JPanel需要不断刷新,所以我通过swing计时器生成的动作事件调用它的repaint()方法.我也覆盖它的paintComponent()方法来做我的绘图.
而不是显示我绘制的内容,“JFrame的内容”被绘制到显示JPanel上.我知道在完成绘图之前,我可以通过使用g.fillRect()或super.paintComponent()简单地“清除”显示JPanel.
我只是好奇为什么会这样.
我正在使用jdk 1.6u27.下面是我的代码:
package test;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Main {
public static void main(String[] args) {
Simulation sim = new Simulation();
}
}
class Simulation extends JFrame {
public JLabel state;
private JLabel id;
private ButtonPanel control;
private display display;
public Simulation() {
id = new JLabel("Test");
state = new JLabel("Test");
control = new ButtonPanel();
display = new display(this);
this.setLayout(new BorderLayout());
this.add(id,BorderLayout.norTH);
this.add(control,BorderLayout.WEST);
this.add(display,BorderLayout.CENTER);
this.add(state,BorderLayout.soUTH);
this.setSize(500,600);
this.setVisible(true);
this.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
}
public ButtonPanel getControl() {
return this.control;
}
}
class ButtonPanel extends JPanel implements ActionListener {
public JButton b[] = new JButton[8];
public boolean bp[] = new boolean[8];
public ButtonPanel() {
this.setLayout(new GridLayout(8,1));
for (int i = 0; i < b.length; i++) {
b[i] = new JButton(""+i);
b[i].addActionListener(this);
bp[i] = false;
this.add(b[i]);
}
}
public void actionPerformed(ActionEvent e) {
//do something
}
}
class display extends JPanel implements ActionListener {
private Timer tm;
private int yco;
private Simulation sim;
public display(Simulation sim) {
tm = new Timer(100,this);
tm.start();
yco = 0;
this.sim = sim;
}
@Override
public void paintComponent(Graphics g) {
//draw something
g.drawLine(0,yco,100,100);
}
public void actionPerformed(ActionEvent e) {
yco ++;
this.repaint();
}
}
解决方法
如果没有super.paintComponent(g),结果将取决于您的平台JPanel UI委托,PanelUI的
opacity属性的默认值.我的情况恰好如此,但您可以在您的平台上进行试验,如下所示.
附录:“如果你不尊重opaque property,你可能会看到视觉artifacts.” – paintComponent().您观察到的artifact会因平台而异,但并非典型.实际上,你违背了绘制每个像素的承诺,你会看到在某个缓冲区中遗留下来的东西.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
EventQueue.invokelater(new Runnable() {
@Override
public void run() {
Simulation sim = new Simulation();
}
});
}
}
class Simulation extends JFrame {
public JCheckBox state;
private JLabel id;
private ButtonPanel control;
private display display;
public Simulation() {
id = new JLabel("Test");
state = new JCheckBox("Opaque");
control = new ButtonPanel();
display = new display(this);
this.setLayout(new BorderLayout());
this.add(id,BorderLayout.soUTH);
state.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
display.setopaque(e.getStateChange() == ItemEvent.SELECTED);
}
});
state.setSelected(true);
this.pack();
this.setVisible(true);
this.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
}
public ButtonPanel getControl() {
return this.control;
}
}
class ButtonPanel extends JPanel {
private static final int N = 8;
private List<JToggleButton> list = new ArrayList<JToggleButton>(N);
public ButtonPanel() {
this.setLayout(new GridLayout(0,1));
for (int i = 0; i < N; i++) {
final JToggleButton b = new JToggleButton(String.valueOf(i));
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//System.out.println(b.isSelected());
}
});
list.add(b);
this.add(b);
}
}
}
class display extends JPanel {
private Simulation sim;
private Timer tm;
private int yco;
public display(Simulation sim) {
this.setPreferredSize(new Dimension(320,320));
this.setopaque(true);
this.sim = sim;
tm = new Timer(100,new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
yco++;
repaint();
}
});
tm.start();
}
@Override
public void paintComponent(Graphics g) {
//super.paintComponent(g);
g.drawLine(0,getWidth() / 2,getHeight() / 2);
}
}