当我在单个 JFrame 中有多个 JPanel 对象时,repaint() 如何工作?
How does repaint() work when I have multiple JPanel objects in a single JFrame?
我读到过,当 JPanel
对象(或扩展 JPanel
的 class 的任何实例)是 JFrame
的一部分时,每次 JVM认为 JFrame
需要刷新,调用 JPanel
实例的 paintComponent()
方法。
但是当我有两个这样的对象时会发生什么,它们是两个 不同 classes 的实例? 运行 我最后提供的代码,我发现两个 paintComponent()
方法都被调用,当我最小化、更改大小或按 colourButton
时。
但是,当我按下 labelButton
时,不是 的情况。它只调用 MyDrawPanel paintComponent()
。为什么会这样?
提前致谢!
class GUI {
JFrame frame;
JLabel label;
void go() {
JButton labelButton = new JButton("Click me to change that (<-) text");
labelButton.addActionListener(new LabelListener());
JButton colourButton = new JButton("Click me to change the colour");
colourButton.addActionListener(new ColourListener());
label = new JLabel("Don't change me!");
frame = new JFrame();
frame.setSize(600, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
MyDrawPanel Q = new MyDrawPanel();
DrawPanel P = new DrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, Q);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);
frame.getContentPane().add(BorderLayout.SOUTH, colourButton);
frame.getContentPane().add(BorderLayout.NORTH, P);
}
class LabelListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event){
label.setText("You've changed me!");
}
}
class ColourListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event){
MyDrawPanel.red = (int) (Math.random() * 255);
MyDrawPanel.green = (int) (Math.random() * 255);
MyDrawPanel.blue = (int) (Math.random() * 255);
frame.repaint();
}
}
}
class MyDrawPanel extends JPanel {
static int red = (int) (Math.random() * 255);
static int green = (int) (Math.random() * 255);
static int blue = (int) (Math.random() * 255);
@Override
public void paintComponent(Graphics g){
Color randomColour = new Color(red, green, blue);
g.setColor(randomColour);
g.fillOval(70, 70, 75, 75);
System.out.println("Q");
}
}
class DrawPanel extends JPanel {
@Override
public void paintComponent(Graphics g){
System.out.println("P");
}
}
frame.repaint();
这会告诉框架重新绘制自身及其所有子项。所以框架上的所有组件都重新粉刷了。
label.setText("You've changed me!");
setText()
方法将调用标签上的 revalidate()
和 repaint()
。 repaint()
告诉标签重新绘制自身及其所有子项。
如果任何组件的大小发生变化,revalidate()
将调用布局管理器。在这种情况下,标签看起来会变大。这意味着添加到中心的面板(您的 DrawPanel)会变小,因此也需要重新绘制。
NORTH/SOUTH中的组件不受标签大小变化的影响,因此不会重新绘制。
所以 Swing 只会重新绘制任何必要的东西,以尽量减少绘制。
我读到过,当 JPanel
对象(或扩展 JPanel
的 class 的任何实例)是 JFrame
的一部分时,每次 JVM认为 JFrame
需要刷新,调用 JPanel
实例的 paintComponent()
方法。
但是当我有两个这样的对象时会发生什么,它们是两个 不同 classes 的实例? 运行 我最后提供的代码,我发现两个 paintComponent()
方法都被调用,当我最小化、更改大小或按 colourButton
时。
但是,当我按下 labelButton
时,不是 的情况。它只调用 MyDrawPanel paintComponent()
。为什么会这样?
提前致谢!
class GUI {
JFrame frame;
JLabel label;
void go() {
JButton labelButton = new JButton("Click me to change that (<-) text");
labelButton.addActionListener(new LabelListener());
JButton colourButton = new JButton("Click me to change the colour");
colourButton.addActionListener(new ColourListener());
label = new JLabel("Don't change me!");
frame = new JFrame();
frame.setSize(600, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
MyDrawPanel Q = new MyDrawPanel();
DrawPanel P = new DrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, Q);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);
frame.getContentPane().add(BorderLayout.SOUTH, colourButton);
frame.getContentPane().add(BorderLayout.NORTH, P);
}
class LabelListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event){
label.setText("You've changed me!");
}
}
class ColourListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event){
MyDrawPanel.red = (int) (Math.random() * 255);
MyDrawPanel.green = (int) (Math.random() * 255);
MyDrawPanel.blue = (int) (Math.random() * 255);
frame.repaint();
}
}
}
class MyDrawPanel extends JPanel {
static int red = (int) (Math.random() * 255);
static int green = (int) (Math.random() * 255);
static int blue = (int) (Math.random() * 255);
@Override
public void paintComponent(Graphics g){
Color randomColour = new Color(red, green, blue);
g.setColor(randomColour);
g.fillOval(70, 70, 75, 75);
System.out.println("Q");
}
}
class DrawPanel extends JPanel {
@Override
public void paintComponent(Graphics g){
System.out.println("P");
}
}
frame.repaint();
这会告诉框架重新绘制自身及其所有子项。所以框架上的所有组件都重新粉刷了。
label.setText("You've changed me!");
setText()
方法将调用标签上的 revalidate()
和 repaint()
。 repaint()
告诉标签重新绘制自身及其所有子项。
如果任何组件的大小发生变化,revalidate()
将调用布局管理器。在这种情况下,标签看起来会变大。这意味着添加到中心的面板(您的 DrawPanel)会变小,因此也需要重新绘制。
NORTH/SOUTH中的组件不受标签大小变化的影响,因此不会重新绘制。
所以 Swing 只会重新绘制任何必要的东西,以尽量减少绘制。