PaintComponent Java慢

时间:2015-04-03 17:53:35

标签: java swing paintcomponent repaint repaintmanager

我一直在Mac上开发JAVA应用程序。逻辑如下:

  1. 服务器向客户端应用程序发送一些订单以绘制基本形状
  2. 客户端应用程序将基本形状绘制为Jpanel
  3. 每次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个重绘调用累积到一个,这使得应用程序非常滞后/非实时。

    我已经尝试过每次使用Timer每隔几毫秒一次形状到达时调用重绘,结果是相同的。代码:

    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

    我不明白为什么paintComponent在我的Windows计算机上这么慢(同一个Jar)。什么可能影响我的计划的表现?

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

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

    提前谢谢

    更新视频

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

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

    我为低质量道歉

    更新BufferedImage:

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

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

    HW / OS / JavaVersion

    • 处理器i5-4300u 2.5ghz
    • Ram 12gb
    • Java版本1.7.0_71

    MAC

    • 处理器i7 2.9ghz
    • Ram 8gb
    • Java版本1.7.0_67

    Java VisualVM

    LiveVM视频:https://youtu.be/cRNX4b3rlZk

    我没有看到任何奇怪的东西可以解释为什么滞后发生但我远非专家(再次抱歉质量低劣)

    感谢您的所有回复

3 个答案:

答案 0 :(得分:2)

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

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);
}

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

答案 1 :(得分:1)

我建议您对BufferedImage进行静态绘制,然后在paintComponent方法中绘制BufferedImage。

如,

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
}

答案 2 :(得分:0)

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

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

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

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

感谢您的回复,对不起给我带来的不便表示遗憾