Swing repaint()在循环或线程中不起作用
我有以下代码:
import java.awt.Color;import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.text.View;
public class ex10 extends JPanel {
private int x=1;
int y=1;
//Constructor
public ex10() {
while(true) {
System.out.println("x ->"+ x);
System.out.println("y ->" + y);
x = randomposition(x);
y = randomposition(y);
this.repaint();
}
}
public int randomposition(int value) {
Random random = new Random();
if (random.nextBoolean() == true) {
if (value+1 != 500) {
value++;
}
}
else {
if (value-1 != 0) {
value--;
}
}
return value;
}
@Override
public void paintComponent(Graphics g) {
//super.paintComponent(g);
g.setColor(Color.green);
g.fillRect(x, y, 20, 20);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(new ex10());
}
}
不幸的是,当this.repaint()
被调用时,该点并没有显示,但是我仍然得到了System.out.println
。我尝试单独设置一个新线程,但无济于事。我尝试了其他解决方案(invokelater
和paintimmediately
),但也无济于事。
我的目标是在屏幕上设置一个绿点。你有什么解决办法吗?
回答:
您while (true)
正在阻止Swing事件线程使应用程序进入睡眠状态。
对于简单的动画和游戏循环,请使用Swing计时器。如果需要长时间运行的代码需要在后台运行,请使用后台线程(例如SwingWorker),但要确保所有更改Swing组件状态的调用都应在Swing事件线程上进行。
例如,您可以更改以下内容:
while(true) { System.out.println("x ->"+ x);
System.out.println("y ->" + y);
x = randomposition(x);
y = randomposition(y);
this.repaint();
}
使用Swing Timer(javax.swing.Timer)的代码:
int timerDelay = 20;new Timer(timerDelay, new ActionListener(){
public void actionPerformed(ActionEvent e) {
x = randomposition(x);
y = randomposition(y);
repaint();
}
}).start();
关于DSquare的评论:
- 确实,您不是应该在Swing事件线程上运行GUI的,但是您的while真正循环仍会冻结绘画,因为无限循环会阻止组件完全创建自身。
- 如上所述,您实际上应该在Swing事件线程上启动所有Swing GUI,您可以通过将Swing创建代码放入Runnable并通过SwingUtilities方法invokeLater对事件线程上的Runnable排队来完成。
- 您需要在paintComponent覆盖中调用上级的paintComponent方法,以便JPanel可以执行其内部管理图形工作,包括清除“脏”像素。
例如,更改此:
public static void main(String[] args) { JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(new ex10());
}
对此:
public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(new Ex10());
}
});
}
并更改此:
@Overridepublic void paintComponent(Graphics g) {
//super.paintComponent(g);
g.setColor(Color.green);
g.fillRect(x, y, 20, 20);
}
对此:
@Overridepublic void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.green);
g.fillRect(x, y, 20, 20);
}
以上是 Swing repaint()在循环或线程中不起作用 的全部内容, 来源链接: utcz.com/qa/414607.html