从paintComponent调用repaint是一个很好的做法

时间:2015-05-31 19:22:40

标签: java performance swing awt

对于我们应用程序中的某些UI组件,我们覆盖paintComponent,在某些条件下"递归地"通过调用repaint来调用自己。我们使用这种方法来实现组件中动画的高刷新率。

例如,我们使用的进度条看起来像:

public class SimpleProgressBar extends JPanel {
    private boolean inProgress;

    ....

    @Override
    protected void paintComponent(Graphics g) {
        if (inProgress) {
            paintBar(g);
            repaint();
        } else {
            doSomeOtherThings();
        }
    }
}

这是一个很好的做法(特别是在性能/效率/ CPU使用方面)? 使用Timer或后台线程来repaint我们的组件会更好吗?

2 个答案:

答案 0 :(得分:6)

  

这是一种很好的做法(特别是在性能/效率/ CPU使用方面)吗?

不,这不是好习惯。在paintComponent内调用重绘是不好的做法,因为:

  1. 这样的高帧率几乎不需要
  2. 无法保证帧速率(重绘不直接调用绘制方法,但会尽快调用此组件的绘制方法'(可能不是马上))
  3. 优先绘制单个组件,并且不仅可能导致该组件的绘制,还可能导致其他组件的绘制以及对其他EDT特定任务的响应(例如事件)
  4.   

    使用Timer或后台线程重新绘制组件会更好吗?

    是的,使用TimerThread可以更好地控制帧速率,而不会在执行此操作时阻碍EDT。根据上下文,Timer在EDT上运行(而不是线程),因此不需要调度到EDT。

答案 1 :(得分:0)

极少数情况下,覆盖paintComponent是件好事。你的情况似乎是其中之一;但是,重要的是要记住,调用paintComponent不是你的工作。我的意思是,它是系统的一个办公室,决定何时重新绘制某些组件。当您拖动屏幕或将另一个屏幕放在您的屏幕上时,这一点尤其明显。话虽如此,很难说你的方法会被调用多少次;其中,很难说什么时候值得使用该实现。
在旁注中,正如你所说的那样,后台线程很可能不会使它变得更好,而Swing很可能不是线程 - 安全。
我希望这对你有所帮助,祝你好运!