[英]Why doesn't repaint() work when called by a method of an object of the same class?
In a program I'm building for my class I have the same class extending a Swing JPanel and implementing MouseListener, for which I use two instantiations - one to function as a JPanel, and the other as a mouse listener for that JPanel. 在为我的班级构建的程序中,我有一个相同的类扩展了Swing JPanel并实现了MouseListener,为此我使用了两个实例化-一个实例化为JPanel,另一个实例化为该JPanel的鼠标侦听器。
But when I click in the window, repaint() the MouseClicked method in the mouse listener fails to call the first object's paintComponent() method. 但是,当我单击窗口时,鼠标侦听器中的MouseClicked方法repaint()无法调用第一个对象的paintComponent()方法。 For example: 例如:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestPanel extends JPanel implements MouseListener{
static boolean black;
static TestPanel test = new TestPanel();
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseClicked(MouseEvent e){ //Expected behavior: the square turns black immediately
System.out.println("CLICK!");
black = true;
test.repaint(); //this fails
try{
Thread.sleep(3000);
}catch(Exception ex){}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
System.out.println("Painting...");
g2d.setColor(Color.white);
if(black){
g2d.setColor(Color.black);
}
g2d.fillRect(0, 0, 200, 200);
}
public static void main(String[] args) throws InterruptedException{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.addMouseListener(new TestPanel());
test.setPreferredSize(new Dimension(200, 200));
frame.add(test);
frame.pack();
frame.setVisible(true);
while (true){
black = false;
test.repaint();
Thread.sleep(100);
}
}
}
If you watch what happens on a click, the screen stays white for the 3 seconds after the click is registered, until the loop starts up again, ie, the repaint() call in the mouse listener didn't work. 如果您观察单击后发生的情况,则在单击记录后3秒钟内,屏幕将保持白色,直到循环再次启动,即鼠标侦听器中的repaint()调用无效。 Why does this happen? 为什么会这样?
I'm guessing it would work if I made different classes for the objects, but I'm mostly curious as to why it doesn't work this way. 我猜想如果为对象创建不同的类会起作用,但是我最好奇为什么它不能这样工作。
for which I use two instantiations - one to function as a JPanel, and the other as a mouse listener for that JPanel. 为此,我使用了两种实例化-一种用作JPanel,另一种用作该JPanel的鼠标侦听器。
There is no need to do that. 不需要这样做。 All you need is a single instance of the TestPanel
class. 您只需要一个TestPanel
类的实例TestPanel
。
In the constructor of your TestPanel
class you just add: 在您的TestPanel
类的构造函数中,只需添加:
addMouseListener( this);
The get rid of the static variable for the TestPanel class. 除去TestPanel类的静态变量。
Then the code in your main method should look something like: 然后,您的main方法中的代码应类似于:
//test.addMouseListener(new TestPanel());
//test.setPreferredSize(new Dimension(200, 200));
//frame.add(test);
frame.add( new TestPanel() );
Also, the TestPanel
class should override the getPreferredSize()
method to return the Dimension of your panel. 另外, TestPanel
类应重写getPreferredSize()
方法以返回面板的Dimension。
Read the section from the Swing tutorial on Custom Painting for a working example with a MouseListener
. 阅读有关定制绘画的Swing教程中的部分,以获取使用MouseListener
的工作示例。
The AWT thread is responsible for calling MouseListener and for repaint. AWT线程负责调用MouseListener并进行重新绘制。 Inside the repaint(); 在repaint()内部; method, the AWT thread is told to call the paint(); 方法,告诉AWT线程调用paint();。 Just call it using a different thread. 只需使用其他线程即可调用它。 In general, it is a bad idea to do anything intensive with the AWT thread. 通常,对AWT线程进行任何密集的工作都是一个坏主意。 It already does a lot, taking too much of its time will mess your GUI up. 它已经做了很多事情,花费太多时间会使您的GUI混乱。
Depending on your needs, this might work: 根据您的需求,这可能会起作用:
new Thread(()->{repaint();}).start();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.