1

我正在开发一个用 Java 编写的并发画布,这将使用户认为他们正在并行绘制画布。

为了实现用户感知的并行性,我让他们创建这些 Runnable 对象,我继续使用 SwingUtilities.invokeLater() 将这些对象放入 EventQueue。

为了测试它,我使用几个线程模拟了用户,并在每次调用 invokeLater() 之间添加了一点延迟(大约 50 毫秒),以便查看它是否真的看起来像并行发生的绘图。

问题是,虽然它可以很好地处理 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);
}

}
4

1 回答 1

4

AFAIK,您不应该保留对 Graphics 对象的引用并在需要时在其上绘图。相反,您应该等待paintComponent()Swing 调用该方法,然后在此方法中进行绘图。

因此,您的任务应该只更改组件的状态,并请求异步或同步重绘(使用repaint()or paintImmediately())。Swing 将paintComponent()使用 Graphics 对象调用该方法,您可以使用该对象根据组件的状态绘制适当的线条。

有关更多详细信息和说明,请参见http://java.sun.com/products/jfc/tsc/articles/painting/

于 2012-06-02T22:13:41.193 回答