简体   繁体   English

使用SwingWorker更新GUI

[英]Updating GUI with SwingWorker

I posted a question yesterday about preventing the UI from freezing when using a scheduledexecutorservice here What should I do in order to prevent the UI from freezing(scheduledexecutorservice) and most people suggested using SwingWorker instead of scheduledexecutorservice. 我昨天在这里发布了一个有关在使用Scheduledexecutorservice时防止UI冻结的问题,为了防止UI冻结(scheduledexecutorservice)我应该怎么做 ,大多数人建议使用SwingWorker而不是Scheduledexecutorservice。 However, I've been stuck since then trying to figure out how a SwingWorker thread would work in my case. 但是,从那时起,我一直在试图弄清楚SwingWorker线程在我的情况下如何工作。

I have the following pseudocode: 我有以下伪代码:

createGraph(){
  if(rule1)
    n = new Node()
    graph.add(n)
    animateGraph()
    createGraph()
  if(rule2)
    ...

I have a recursive algorithm which creates a graph based on certain rules and I want to update the UI when a rule is matched and a new vertex/edge is added to the graph. 我有一个基于某些规则创建图形的递归算法,并且我想在匹配规则并将新的顶点/边添加到图形时更新UI。 My question is how can I display the graph whenever a new node/edge is added to it? 我的问题是,每当向其添加新节点/边时如何显示图形? This should happen in the animateGraph() method and when it hits this method, it should update the actual UI, preferably wait for 1500ms and do that until the whole graph is built. 这应该在animateGraph()方法中发生,并且当它命中此方法时,它应该更新实际的UI,最好等待1500ms并这样做,直到构建整个图形。

I tried creating a SwingWorker thread. 我尝试创建一个SwingWorker线程。 In this case it doesn't show the intermediate steps of the graph creation but only the final graph. 在这种情况下,它不会显示图形创建的中间步骤,而只会显示最终图形。 First, it executes all calls to doInBackground() and then it goes to done(). 首先,它执行对doInBackground()的所有调用,然后转到done()。

NB: I create a new SwingWorker thread every time a new vertex/edge is created as I read that doInBackground() is only called once. 注意:每次读取新的顶点/边时,我都会创建一个新的SwingWorker线程,因为我看到doInBackground()仅被调用一次。

private void animateGraph() {
    swingWorker = createRunnable();
    swingWorker.execute();
}

private void displayGraph() {
    JPanel.add(graph);
}

private SwingWorker<Object, Object> createRunnable() {
    swingWorker = new SwingWorker<Object, Object>() {

        @Override
        protected Void doInBackground() throws Exception {
            System.out.println("Start sleeping.. " + new Date());
            Thread.sleep(1500);
            publish(new NodeTuple(new Node("A"), new Node("B")));
            return null;
        }

        protected void process(List<NodeTuple> chunks) {
            System.out.println("In process..     " + new Date());
            NodeTuple nodeTuple = chunks.get(chunks.size() - 1);
            graph.addVertex(nodeTuple.source);
            graph.addVertex(nodeTuple.target);
            checkIfToAddEdge(nodeTuple.source, nodeTuple.target);
            createDiagram();
        }

        }
    };
    return swingWorker;
}

Edit: I updated doInBackground() and process() methods. 编辑:我更新了doInBackground()和process()方法。 However, I still don't get what I really want. 但是,我仍然没有得到我真正想要的。 No intermediate steps are shown and only the final graph is displayed. 没有显示中间步骤,仅显示最终图形。

You should probably use the publish / process API of the SwingWorker (see the second example of the SwingWorker API doc for code). 您可能应该使用SwingWorkerpublish / process API(有关代码,请参见SwingWorker API文档的第二个示例)。

This will allow you create nodes recursively and off the EDT, then publish new nodes matching your rule, before finally process ing these nodes on the EDT for display or animation. 这将允许您创建节点递归和关闭EDT,然后publish符合规则的新节点,最后才process荷兰国际集团在EDT这些节点进行显示或动画。

Adding animation will need it's own thread, and I suggest you add that as a separate task, but at least you should be able to see new nodes showing up as they are added to the graph. 添加动画将需要它自己的线程,建议您将其添加为一个单独的任务,但是至少您应该能够看到将新节点添加到图形中时出现的情况。

To see the intermediate steps, you have to publish() each new Node as it's created and process() it on the event dispatch thread, like they show in Tasks that Have Interim Results . 要查看中间步骤,您必须在创建每个新Node对其进行publish() ,并在事件分配线程上对其进行process() ,就像它们在具有临时结果的任务中所示

class FlipTask extends SwingWorker<List<Node>, Node> {
    @Override
    protected List<Node> doInBackground() {
        …
        publish(new (Node);
        …
    }

    protected void process(List<Node> list) {
        // add each new Node to the view
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM