我正在使用Java编写的并发画布,这将使用户认为他们正在并行绘制画布。
为了实现用户感知的并行性,我让他们创建这些Runnable对象,然后使用SwingUtilities.invokeLater()将其放在EventQueue上。
为了测试它,我使用几个Threads模拟了用户,并在每次调用invokeLater()之间添加了一点延迟(大约50ms),以便查看它是否真的看起来正在进行绘图平行。
问题在于,虽然它在invokeLater()调用之间增加了延迟时工作正常,但是取消延迟会导致绘图有时正确绘制,有时会部分绘制和消失,而在其他时候不会绘制。
我对可能出现的问题感到非常难过,所以如果有人有任何想法,请告诉我。
以下是延迟注释掉的代码:
public void run(){
//add tasks on to the event queue of the EDT
for(int i = 0; i<numLines; i++){
DrawLineTask task = new DrawLineTask(g, x1, y1+i, x2, y2+i, lineColor);
SwingUtilities.invokeLater(task);
// try {
// Thread.sleep(new Double(Math.random()*50).longValue());//random sleeping times to make it appear more realistic
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
干杯
编辑:以下是DrawLineTask的代码。它非常简单,因为它只是Runnable类的扩展,它使用给定参数的标准Java函数绘制一条线。
public class DrawLineTask implements Runnable {
Graphics g;
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
Color color = Color.BLACK;
public DrawLineTask(Graphics g, int x1, int y1, int x2, int y2){
this.g = g;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public DrawLineTask(Graphics g, int x1, int y1, int x2, int y2, Color color){
this.g = g;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
}
@Override
public void run() {
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
}
}
答案 0 :(得分:4)
AFAIK,你不应该保留对Graphics对象的引用并在你想要的时候绘制它。相反,您应该等待Swing调用paintComponent()
方法,并在此方法中执行绘图。
因此,您的任务应该只是更改组件的状态,并要求进行异步或同步重绘(使用repaint()
或paintImmediately()
)。然后,Swing将使用Graphics对象调用paintComponent()
方法,您可以使用该对象根据组件的状态绘制相应的行。
有关详细信息和说明,请参阅http://java.sun.com/products/jfc/tsc/articles/painting/。