1

我一直在我的 Mac 上开发 JAVA Applications 。逻辑如下:

  1. 服务器向客户端应用程序发送一些命令以绘制基本形状
  2. 客户端应用程序将基本形状绘制到 Jpanel 中

每次 Shape 到达时,程序都会调用 repaint()

 public void paintShape(Shape p) 
{
    //this.paintComponent(this.getGraphics());
   arrayofShapes.add(p);
   this.repaint();
    //this.updateUI();
    //this.update(this.getGraphics());

}
public void paintComponent(Graphics g) 
{ 
    super.paintComponent(g);
    g2d = (Graphics2D) g.create();
    g2d.setStroke(new BasicStroke(2));
    g2d.setColor(pickedColor);
    for(final Shape p : arrayofShapes)
    {
        g2d.draw(p);
    }
    //g2d.dispose();

}

一切都很顺利(实时),所以我决定在 Windows 计算机上测试相同的应用程序。结果是一个滞后的应用程序。这些是我得出的结论。

  • RepaintManager 正在累积 repaint() 调用。我看到了形状如何到达目的地,但在某些情况下,超过 5 个重绘调用被累积为一个,这使得应用程序非常滞后/不是实时的。

我试过而不是每次形状到达时都调用重绘,每隔几毫秒用一个计时器来做,结果是一样的。代码 :

ActionListener listener = new ActionListener(){
          public void actionPerformed(ActionEvent event){
            repaint();
          }
        };

Timer displayTimer = new Timer(5, listener);
displayTimer.start();

此外,我还测试了一些允许您使用鼠标绘画的随机代码,与我使用paintComponent 的逻辑相同。在这种情况下,它工作顺利,没有滞后感......示例:http: //javagraphics.blogspot.com.es/2010/06/shapes-implementing-freehand-pencil.html

我不明白为什么我的 Windows 计算机(同一个 Jar)上的paintComponent 这么慢。什么可能会影响我的程序的性能?

我已经阅读了有关油漆组件的所有答案,但其中任何一个都解决了这个问题。

关于如何解决问题并实际存档实时的任何建议?

先感谢您

更新视频:

Mac 视频:https ://youtu.be/OhNXdGXoQpk实时处理重负载没问题

Windows 视频https://youtu.be/yol2miHudZc明显滞后

我为低质量道歉

更新缓冲图像:

引入 BufferedImage 后,结果仍然是一个缓慢的绘画应用程序。它产生了另一个问题,因为其中一个命令是删除所有形状,它增加了一些复杂性,因为我必须做一个:

 g2d.clearRect(0, 0, screenSize.width, screenSize.height);

硬件/操作系统/Java版本

视窗

  • 处理器 i5-4300u 2.5ghz
  • 内存 12GB
  • Java 版本 1.7.0_71

苹果电脑

  • 处理器 i7 2.9ghz
  • 内存 8GB
  • Java 版本 1.7.0_67

Java VisualVM

VisualVM 直播视频:https ://youtu.be/cRNX4b3rlZk

我没有看到任何奇怪的东西可以解释为什么会出现滞后,但我远不是专家(再次为低质量感到抱歉)

感谢您的所有回复

4

3 回答 3

2

create()每次都不需要新的图形上下文;只是投到g. Graphics2D这在所有具体实现上都是安全的。这也消除了dispose()创建上下文的需要。如此处所述,保留可能对以后的绘画至关重要的任何上下文变量。

public void paintComponent(Graphics g) { 
    super.paintComponent(g);
    g2d = (Graphics2D) g;
    Stroke oldStroke = g2d.getStroke();
    g2d.setStroke(new BasicStroke(2));
    g2d.setColor(pickedColor);
    for(final Shape p : arrayofShapes) {
        g2d.draw(p);
    }
    g2d.setStroke(oldStroke);
}

此外,比较两个平台上的配置文件以查找差异。作为参考,此处引用的示例可以轻松处理任一平台上包含数百个形状的选择。

于 2015-04-03T21:19:03.650 回答
1

I would recommend that you do static drawing to a BufferedImage, and then draw the BufferedImage in your paintComponent method.

e.g.,

private BufferedImage bufferedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_ARGB);

public void paintShape(Shape p) {
    Graphics2D g2 = bufferedImage.createGraphics();
    g2d.setStroke(MY_STROKE); // make this a constant
    g2d.setColor(pickedColor);
    g2d.draw(p);
    g2d.dispose();
    this.repaint();
}

public void paintComponent(Graphics g) { 
    super.paintComponent(g);
    if (bufferedImage != null) {
       g2.drawImage(bufferedImage, 0, 0, null);
    }
    // do dynamic drawing such as drawing of moving sprites here
}
于 2015-04-03T18:06:16.737 回答
1

经过两天多的调试发现问题与paintComponent()无关

使用相同的服务器生成随机形状

在 Windows 应用程序中,同时接收到一些形状,不可能的,因为我每 15 毫秒发送一次形状。这就是它积累形状的原因(结果=滞后)。

另一方面,在 Mac 应用程序中,每个形状都有不同的接收时间 (结果 = 实时)

感谢您的友好回复,很抱歉给您带来不便,我可能有原因

于 2015-04-04T14:04:04.560 回答