2016-03-05 87 views
1

当我尝试在调用Thread和sleep()的循环中更新它时,包含嵌入式单个图形(Graphstream)的我的JFrame冻结。我试图在独立图上使用相同的更新(显示在它自己的图上),并且按预期工作。Thread.sleep()冻结包含GraphStream的JFrame/GUI图

我有嵌入的JFrame单个图表如下(AppGraph.java):

public static ViewPanel init(){ 

    graph.addAttribute("ui.stylesheet", styleSheet); 
    graph.setAutoCreate(true); 
    graph.setStrict(false); 
    graph.addAttribute("ui.quality"); 
    graph.addAttribute("ui.antialias"); 

    initGraph(); 

    initNodes(graph); 

    return attachViewPanel(); 

} 

private static ViewPanel attachViewPanel() { 
    Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD); 
    viewer.enableAutoLayout(); 
    return viewer.addDefaultView(false); 
} 

private static void initGraph(){ 
    FileSource fs = new FileSourceDOT(); 
    String graph_filename = "graph.gv"; 
    String absolute_path = System.getProperty("user.home") + File.separator + graph_filename; 
    fs.addSink(graph); 
    try { 
     fs.readAll(absolute_path); 
    } catch (IOException | NullPointerException e) { 
     e.printStackTrace(); 
    } finally { 
     fs.removeSink(graph); 
    } 
} 

然后这被称为在JFrame类如下:

/*AppWindow.java 
    * Set up graph 
    */ 
    GridBagConstraints graphConstraints = new GridBagConstraints(); 
    graphConstraints.fill = GridBagConstraints.BOTH; 
    graphConstraints.gridx = 0; 
    graphConstraints.gridy = 1; 
    graphConstraints.weightx = 0.5; 
    graphConstraints.weighty = 0.5; 
    graphConstraints.gridwidth = 4; 
    graphConstraints.gridheight = GridBagConstraints.RELATIVE; 
    add(AppGraph.init(), graphConstraints);` 

JFrame是按钮针对不同的搜索算法,如BFS。这些算法的执行过程中,遍历边以固定的时间间隔被着色,以产生一种动画效果,如下所示:

//BFSAlgorithm.java 
    private void callBFS(Node startNode, Node goalNode) { 
      startNode.setAttribute("parent", "null"); 
      startNode.setAttribute("level", 0); 
      startNode.setAttribute("visited?"); 
      LinkedList<Node> queueFrontier = new LinkedList<>(); 
      int level = 1; 
      queueFrontier.addLast(startNode); 
      while (!queueFrontier.isEmpty()) { 
       System.out.println("Level: " + (level - 1)); 
       LinkedList<Node> next = new LinkedList<>(); 
       for (Node node : queueFrontier) { 
        if (node == goalNode) { 
         System.out.println(node.getId() + ": Found Found Found!!!"); 
         if (node != startNode) { 
          colorEdge(node); 
         } 
         return; 
        } 
        System.out.print(node.getId() + " visited \t"); 
        if (node != startNode) { 
         colorEdge(node); 
        } 
        for (Edge edge : node.getEdgeSet()) { 
         Node opposite = edge.getOpposite(node); 
         if (!opposite.hasAttribute("visited?")) { 
          System.out.print(opposite.getId() + " enqueued \t"); 
          opposite.setAttribute("level", level); 
          opposite.setAttribute("parent", node); 
          opposite.setAttribute("visited?"); 
          next.addLast(opposite); 
         } 
        } 
        System.out.print("\n"); 
       } 
       level++; 
       queueFrontier = next; 
       sleep(); 
     } 
    } 

    private void colorEdge(Node node) { 
     Edge visitedEdge = node.getEdgeBetween(node.getAttribute("parent", Node.class)); 
     visitedEdge.setAttribute("ui.color", 0.5); 
     sleep(); 
    } 

    private void sleep() { 
     try { 
      Thread.sleep(AppWindow.speed); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

BFSAlgorithm器具DynamicAlgorithm和延伸SinkAdapter。随着算法的运行,我已经扩展了SinkAdapter以使它与视图交互。当我调用BFSAlgorithm时,算法运行并且各种println语句被延迟sleep(),则GUI会冻结并且无响应,直到执行完所有访问边被着色为止。我试图在实施ViewerListenerAppGraph.java如记录在graphstream documentation但只造成了一个无限循环崩溃的应用程序:

/*...init() method from AppGraph.java*/ 
ProxyPipe fromViewer = viewer.newThreadProxyOnGraphicGraph(); 
     fromViewer.addSink(graph); 
     fromViewer.pump(); 

while(loop) { 
      fromViewer.pump(); // 

} 
+2

看一看[并发在Swing(http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)和[如何使用Swing定时器](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)和[Worker Threads and SwingWorker](http://docs.oracle.com/javase/) tutorial/uiswing/concurrency/worker.html) – MadProgrammer

+0

我没有足够的时间来回答,但你应该使用[Swing Timer](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer .html)而不是 – Frakcool

+0

尝试重新验证您的图形所在的JPanel – rert588

回答

0

像@Frakool和@MadProgrammer的意见建议,如果有人遇到类似问题, ,使用SwingWorkerSwing Timer将提供期望的结果。按照documentation

一般情况下,我们推荐使用Swing的计时器,而不是通用定时器用于GUI相关的任务,因为摇摆计时器全部自动共享相同的,预先存在的计时器线程和GUI相关任务在事件派发线程上执行。但是,如果您不打算从定时器中触摸GUI,或者需要执行冗长的处理,则可以使用通用定时器。

下面是我用它来阻止gui冻结的方法。我创建了一个私有内部SwingWorker类,如下使用Swing Timer

private class BFSTask extends SwingWorker<LinkedList<Node>, Node>{ 
    private ArrayList<Node> visitedList; 
    private int visitedIndex = 0; 
    private boolean traversalDone = false; 
    private Timer traversal = new Timer(AppWindow.speed, new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent actionEvent) { 
      Node lastVisited = visitedList.get(visitedIndex); 
      Edge visitedEdge = lastVisited.getEdgeBetween(lastVisited.getAttribute("parent", Node.class)); 
      visitedEdge.setAttribute("ui.color", 0.5); 
      visitedIndex++; 
      if(visitedIndex >= visitedList.size()){ 
       traversal.stop(); 
       traversalDone = true; 
       if(BFSAlgorithm.this.getPathToGoal() != null){ 
        startTimer(); 
       } 
      } 
     } 
    }); 

    @Override 
    protected LinkedList<Node> doInBackground() throws Exception { 
     Node found = publishNodeBreadthFirst(getStartNode(), getGoalNode()); 
     if (found != null) { 
      return getPathToGoal(found); 
     } else{ 
      return null; 
     } 
    } 

    @Override 
    protected void process(List<Node> list) { 
     visitedList = (ArrayList<Node>) list; 
     traversal.start(); 
    } 

    @Override 
    protected void done() { 
     try { 
      BFSAlgorithm.this.pathToGoal = get(); 
      if(traversalDone && BFSAlgorithm.this.getPathToGoal() != null){ 
       startTimer(); 
      } 
      if(BFSAlgorithm.this.getPathToGoal() == null){ 
       throw new NullPointerException("Goal Not Found."); 
      } 
     } catch (InterruptedException | ExecutionException e) { 
      e.printStackTrace(); 
     } catch (NullPointerException e){ 
      JOptionPane.showMessageDialog(getAppWindow(), "Goal Node Not Found!", "Error", JOptionPane.ERROR_MESSAGE); 
      getAppWindow().disableExceptClear(); 
      getAppWindow().changeStatus("Goal node not found"); 

     } 
    } 

    private LinkedList<Node> getPathToGoal(Node found) { 
     LinkedList<Node> path = new LinkedList<>(); 
     Node parent = found.getAttribute("parent"); 
     path.addLast(found); 
     while (parent != getStartNode()){ 
      path.addLast(parent); 
      parent = parent.getAttribute("parent"); 
     } 
     return path; 
    } 
} 
+0

我遇到类似问题了。当我调用包含图的类时,它不会呈现节点。所以我使用SwingWorker将图形放在另一个线程上。好吧,它呈现,但现在viewlistener不起作用,我没有从用户交互(单击节点)的答案。你可以在这里看到。 http://stackoverflow.com/questions/36899115/graphstream-view-not-loading/36900197 –