当前位置: 首页 > 知识库问答 >
问题:

使循环迭代等待repaint()方法完成

常甫
2023-03-14

在搜索了很多类似问题的答案后,我仍然没有找到适合我需要的解决方案。

基本上,我有一个while循环,我想等待repaint()方法完成,然后再开始该循环的另一次迭代。

更详细地说,我有一些片段是在扩展JComponent的MapPanel类的paintComponent方法中绘制的。然后,当用户单击按钮时,算法开始搜索从“上部”线段开始的交点(使用endpoint作为事件点)。这个算法基本上就是我所说的while循环,它调用这个while循环中的另一个算法,在每次迭代时发送一个事件点(这些事件点按顺序从上到下发送)。

我想做的是通过在当前事件点画一条线来显示算法的当前“位置”。当算法找到新的交叉点时,我也想显示它们。我确实绘制了画组件()方法中需要的东西。

问题是,当我在循环中为MapPanel调用repaint()方法时,它会等待整个循环结束,然后再更新UI(我发现了很多关于它为什么这样做的原因,但没有发现在我的特定情况下如何修复这一问题)。

好的,我已经解释完了,下面是实际的算法:

private void findIntersection(ArrayList<Segment> segments){
    QTree Q=new QTree();
    for (Segment s : segments){
        Q.initialise(s);
    }
    TreeT T=new TreeT();
    while (Q.getRoot()!=null){
        Point p = Q.maxEventPoint(Q.getRoot());
        Q.delete(p.getX(), p.getY());
        mapPanel.setSweeplinePosition(p.getY());
        handleEventPoint(p, T, Q);
        mapPanel.repaint()
        //should wait here for repaint() to complete
    }
        System.out.println("all intersections found, found " + mapPanel.getIntersections().size());
}

共有2个答案

公孙志
2023-03-14

您是否尝试了方法线程。睡眠(毫秒)???例如,我习惯在代码中执行以下操作:

     btnNewButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        pca.setIcon(new ImageIcon("icon.png"));
                        for(int i=0; i<4; i++) {
                        try{Thread.sleep(700);} catch(InterruptedException er){} 
                        x+=20;
                        p.repaint();
                    }}
                }).start();
            }
        });
姜华翰
2023-03-14

问题是您的长时间运行的代码可能会在Swing事件线程上调用,这是一个阻止事件线程执行其操作(包括绘制GUI)的操作。

该解决方案可能与您在搜索中找到的类似,但我们不知道您为什么不能将其用于程序,也就是在SwingWorker后台线程中执行while循环,使用SwingWorker的发布/处理方法对发布临时结果,然后使用临时数据绘制图形。

有关这方面的更多信息,请阅读Swing中的并发

比如说

private void findIntersection(final ArrayList<Segment> segments) {
  final SwingWorker<Void, Double> myWorker = new SwingWorker<Void, Double>() {

     @Override
     protected Void doInBackground() throws Exception {
        QTree Q = new QTree();
        for (Segment s : segments) {
           Q.initialise(s);
        }
        TreeT T = new TreeT();
        while (Q.getRoot() != null) {
           Point p = Q.maxEventPoint(Q.getRoot());
           Q.delete(p.getX(), p.getY());
           publish(p.getY()); // push data to process method

           // take care that this method below does not
           // make Swing calls
           handleEventPoint(p, T, Q);
        }
        return null;
     }

     @Override
     protected void process(List<Double> chunks) {
        for (Double yValue : chunks) {
           // this is called on the EDT (Swing event dispatch thread)
           mapPanel.setSweeplinePosition(yValue);
           mapPanel.repaint();
        }
     }
  };
  myWorker.addPropertyChangeListener(new PropertyChangeListener() {

     @Override
     public void propertyChange(PropertyChangeEvent evt) {
        // get notified when Worker is done
        if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
           // TODO: any clean up code for when worker is done goes here
           try {
              myWorker.get(); // must call to trap exceptions that occur inside worker
           } catch (InterruptedException e) {
              e.printStackTrace();
           } catch (ExecutionException e) {
              e.printStackTrace();
           }
        }
     }
  });
  myWorker.execute(); // execute worker
}
 类似资料:
  • 问题内容: 为什么每当我将ajax放入for循环中时,它都无法很好地同步? 例如,我的代码是: 为什么它先调用Ajax查询?是否有可能让ajax查询在继续之前完成?因为它在完成填充之前就清除了数组。:/ 问题答案: 首先,您确实需要了解Ajax调用是如何异步的(这就是Ajax中的“ A”所代表的意思)。这意味着调用仅启动ajax调用(它将请求发送到服务器),其余代码愉快地继续运行。有时,在其余代码

  • 问题内容: 我想编写一个后台作业(EJB 3.1),该作业每分钟执行一次。为此,我使用以下注释: 工作正常。 但是,有时该工作可能需要一分钟以上。在这种情况下,计时器仍会触发,从而导致线程问题。 如果当前执行未完成,是否可以终止调度程序? 问题答案: 如果可能只有一个计时器同时处于活动状态,则有两种解决方案。 首先,应该在。在Singleton中,方法默认情况下是写锁定的,因此,当容器中仍有活动时

  • 问题内容: 我正在使用bluebird,方法 getAll 和 update return promises。我如何说“等到两个承诺返回,然后更新currentProduct值”?我对JS很陌生… 问题答案: 如果可以使用/,这将很简单。 或者,如果您只能使用简单的承诺,则可以遍历所有产品,并将每个承诺置于最后一个循环中。这样,仅当前一个问题解决时,它才会前进到下一个问题(即使它将首先迭代整个循环

  • 我有一个递归算法,我用它来迭代分层数据结构,但不幸的是,对于一些数据,分层结构太深,以至于我得到了一个StackOverflow错误。我见过这种情况发生在大约150个节点的深度上,而数据可能会增长到更远的程度。对于上下文,这段代码将在有限的环境中运行,改变JVM堆栈大小不是一个选项,数据结构是给定的,代表不同的文件系统和目录和文件。 为了解决堆栈溢出问题,我尝试将算法转换为迭代算法。这不是我以前必

  • 本节我们探索的主题是迭代与循环。循环通常在计算机编程用用于自动执行重复性任务。 在Python中最常用的迭代形式就是for循环了。for循环允许你迭代出列表中所有的项,迭代出来后你可以做任何你想做的事情。 比如,我们创建了一个列表,并打印出其中所有元素的平方。 >>> for value in [0, 1, 2, 3, 4, 5]: ... print(value * value) ... 0 1