【发布时间】:2017-08-08 01:47:23
【问题描述】:
我的目标是使用观察者模式绘制一个矩形并从左到右平滑移动。
我有一个 Model 类,它是 Observable,我在其中放置了矩形的坐标,还有一个 Display 类,它是 Observer,每次模型中的坐标发生变化时都会执行重绘。
Model 中的坐标更改是在 SwingWorker 内的 while 循环中进行的:在每次迭代中,我将 x 坐标加一,然后休眠 100 毫秒,然后通知观察者(显示器)唯一要执行的任务重绘。如您所见,在 EDT 上调用了 repaint() 方法,就像建议的那样。
问题是大约一秒钟后移动不顺畅,重绘频率发生变化,并且矩形似乎越来越少重绘。
这是模型类:
import java.util.Observable;
import java.awt.EventQueue;
import javax.swing.SwingWorker;
public class Model extends Observable{
int xCoordinate;
Model(Display d){
SwingWorker<Void,Void> sw = new SwingWorker<Void,Void>(){
@Override
protected Void doInBackground() {
while(xCoordinate<600){
xCoordinate ++;
try {
Thread.sleep(100);
} catch (InterruptedException ex) {}
setChanged();
notifyObservers(xCoordinate);
}
return null;
}
};
addObserver(d);
sw.execute();
}
public static void main(String[] a){
EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
Display d = new Display();
Model m = new Model(d);
d.model = m;
}
});
}
}
这里是显示类:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Display extends JFrame implements Observer{
Model model;
int xCoordinate;
Display(){
getContentPane().add(new JPanel(){
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(xCoordinate, 1, 50, 50);
}
});
setSize(600, 600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@Override
/* arg is the updated xCoordinate*/
public void update(Observable o, Object arg) {
xCoordinate = (Integer)arg;
EventQueue.invokeLater(new Runnable(){
@Override
public void run() {
repaint();
}
});
}
}
我尝试了其他方法,例如在 Display 中使用 Timer,但也没有用。 SwingWorker 在这里可能没用,因为在 SwingWorker 线程上进行的计算很容易(递增 1),但我需要它来处理我打算在我的项目(台球游戏)上进行的繁重计算。
我还尝试通过查看两次重绘之间的时间(在 Display 中)和两次增量之间的时间(在 Model 中)进行调试,结果与预期的一样,每次大约 100 毫秒。
提前致谢
【问题讨论】:
-
你能改变睡眠时间吗?试试 10 毫秒,它会移动得更顺畅。
-
它仍然不流畅(至少在我的电脑上)。我尝试了 10 和 500 毫秒。
-
我尝试了一个使用
javax.swing.Timer的示例,但是将延迟设置为 100 毫秒它不会顺利移动。示例如下:java2s.com/Tutorial/Java/0240__Swing/Timerbasedanimation.htm. -
请注意
Thread.sleep(long milis)受制于系统计时器和调度程序的精度和准确性。它可能并不总是在给定的睡眠时间完全入睡,可能需要更长的时间。 -
我会因工作人员/观察者和绘制程序之间的同步问题而受到保护
标签: java multithreading swing observer-pattern swingworker