【问题标题】:Periodic calls to repaint over time随着时间的推移定期调用重新绘制
【发布时间】:2020-07-24 08:12:22
【问题描述】:

所以,我有一个扩展 JPanel 并通过paintComponent 在矩阵中显示点的对象。在特定条件下,矩阵的点可以移动、消失或成倍增加,我想像这样自动显示它们随时间的演变:

for(int i = 0; i < 100; ++i){

    matrix = calculateNextMatrix();    //Calculate possible movements, deaths or births of dots
    myGraphic.updateMatrix(matrix);    //Pass new dots to the JPanel object
    myGraphic.repaint();               //Draw new dots
    Thread.sleep(100);                 //Wait 0.1 seconds for next iteration (yes, this should be in a 
                                       //try-catch)
}

但是,我只在循环完成后的最后一次迭代中绘制,并且之前对 repaint() 的所有调用基本上都被忽略了。如果我一次只进行一次迭代(例如,通过手动按钮按下),我没有问题。

有没有办法自动获得多个定期重绘调用?

【问题讨论】:

  • 是的,因为重绘意味着,用那个新东西重绘它,意味着删除以前存在的所有东西
  • 有没有办法自动获得多个定期重绘调用? - 您使用Swing Timer 来安排动画。这意味着您的代码需要重组以将参数传递给您的代码以指示当前的“状态”。阅读 How to Use Timers 上的 Swing 教程中的部分以获取更多信息。查看:stackoverflow.com/a/33907282/131872 为例。在您的情况下,您将在您的类上调用一个方法以将状态设置为下一次迭代,然后调用 repaint()。
  • 你是如何开始你的循环的?如果你在 EDT 上启动它,比如按下按钮时,那么你会占用 EDT,直到你的循环完成,然后 EDT 可以更新,但你会在最后。

标签: java swing repaint


【解决方案1】:

我在我的库中遇到了一个 JComponent 的类比问题,我找到了一个使用 swing timer 的解决方案,我报告了 timer 的 java 描述

一般来说,对于 GUI 相关的任务,我们建议使用 Swing 计时器而不是通用计时器,因为 Swing 计时器都共享相同的、预先存在的计时器线程,并且与 GUI 相关的任务会自动在事件调度线程上执行。但是,如果您不打算从计时器触摸 GUI,或者需要执行冗长的处理,则可以使用通用计时器。

您可以通过两种方式使用 Swing 计时器:

  • 在延迟后执行一次任务。 例如,工具提示管理器使用 Swing 计时器来确定何时显示工具提示以及何时隐藏它。
  • 重复执行一项任务。 例如,您可以执行动画或更新显示目标进度的组件。

我认为你属于这种情况之一。

如果没有可重现的最小示例,我可以使用我的代码。

你应该像这样创建 Swing 动作监听器:

public class UpdateComponentListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            count += 10;
            timeLabel.setText(count + "");
            //The label call repaint
            //in your app you should be call the repaint

            //In your cases
            /*
                matrix = calculateNextMatrix();    //Calculate possible movements, deaths or births of dots
                myGraphic.updateMatrix(matrix);    //Pass new dots to the JPanel object
                myGraphic.repaint(); 
             */
        }
}

计时器构造函数输入 延迟 和动作监听器,因此您可以使用以下代码构建计时器:

Timer timer = new Timer(1000, new UpdateComponentListener());
timer.start();

您可以停止、重新启动计时器,因此您应该设置计时器的适当性。

图形用户界面示例:

我在看到@camickr 评论后写了这篇文章。我发布答案是因为我的工作已经完成,但是评论回答了你的问题。

我希望必须建立一个食物的例子

【讨论】:

  • +1。我认为您也可以将repaint 替换为paintImmediately,因为根据文档如果在调度当前事件时需要更新显示,它很有用repaint 将合并快速的后续事件,我们不希望这里出现这种行为。但是只有JComponents 支持它。不普通Components.
  • 感谢您的支持,我不会插入有关重绘组件的详细信息,因为这取决于应用程序的结构。一个例子:如果 JPanel 在 JSplitPane 内,您应该在 JPanel 上的 updateUI() 上调用 repaint 并在 SplitPane 上重新绘制。我认为这取决于代码的结构。不过是的,您也可以拨打paintImmediately,谢谢您的建议。
  • 这正是我所需要的,并且解释得很好。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 2018-06-17
相关资源
最近更新 更多