JPanel перекрасить вопрос
У меня есть JFrame, который содержит 2 подкласса JPanel и 2 JLabel в BorderLayout. Один из JPanel содержит JButton, а другой используется для отображения графики. JLabels находятся на севере и юге, кнопка JPanel на западе и дисплей JPanel в центре.
Дисплей JPanel требует постоянного обновления, поэтому я вызываю его метод repaint() через событие action, генерируемое таймером поворота. Я также переопределяю его метод paintComponent(), чтобы сделать мои рисунки.
Вместо отображения того, что я нарисовал, "содержимое JFrame" рисуется на дисплее JPanel. Я знаю, что я могу просто "очистить" дисплей JPanel с помощью g.fillRect() или super.paintComponent() перед выполнением моих рисунков.
Мне просто любопытно, почему это происходит.
Я использую 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();
}
}
1 ответ
Без super.paintComponent(g)
результат зависит от значения по умолчанию вашей платформы для свойства opacity JPanel
Пользовательский интерфейс, PanelUI
, Мой случается true
, но вы можете экспериментировать на вашей платформе, как предложено ниже.
Приложение: "Если вы не соблюдаете непрозрачное свойство, вы, скорее всего, увидите визуальные артефакты". paintComponent()
, Артефакт, который вы наблюдаете, будет варьироваться в зависимости от платформы, но он не является нетипичным. По сути, вы нарушаете обещание рисовать каждый пиксель и видите все, что осталось в каком-то буфере.
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.NORTH);
this.add(control, BorderLayout.WEST);
this.add(display, BorderLayout.CENTER);
this.add(state, 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, yco, getWidth() / 2, getHeight() / 2);
}
}