DefaultTreeCellRenderer()定期执行

时间:2014-10-23 08:35:39

标签: java swing jtree swingworker

我在unix服务器上编写了一些监控进程的程序。我的代码的主要部分看起来像这样:

Class FeedMonitor {
    //.............
    private volatile boolean monitor = true;
    private volatile String feedShRez;
    private volatile DefaultMutableTreeNode envNode;
    //.............
    public void prepareGUI() {
       //..............
       //
       SwingWorker worker = new SwingWorker<Void, Void>() {
          @Override
          protected Void doInBackground() throws Exception {
            sh = new Shell(env);
            System.out.println("Swing worker for check feed statuses started...");
            while (monitor) {
              // get running feeds
              feedShRez = sh.getFeedsStatus(rez);
              System.out.println(feedShRez);
              Thread.sleep(15000);              
              System.out.println("Swing worker for check feed statuses is waking up...");                                    
            }
            return null;
          }            
          @Override
          protected void done() {
            System.out.println("Swing worker completed.");
            super.done();
            System.out.println("Set monitor object to false");
            feedShRez = "";
          }            
        };
        worker.execute();  
        //......
        // This action I would like to execute in thread periodically
        envTree.setCellRenderer(new DefaultTreeCellRenderer() {
            public Component getTreeCellRendererComponent(JTree pTree,
                    Object pValue, boolean pIsSelected, boolean pIsExpanded,
                    boolean pIsLeaf, int pRow, boolean pHasFocus) {

                    System.out.println("Node is " + pValue.toString());                
                    super.getTreeCellRendererComponent(
                            pTree, pValue, pIsSelected,
                            pIsExpanded, pIsLeaf, pRow,
                            hasFocus);

                    // we are under environment tree
                    if ( envNode !=null && ((DefaultMutableTreeNode)pValue).getParent() == envNode 
                        && feedShRez != null && !feedShRez.isEmpty()){
                          if (feedShRez.contains(pValue.toString())) {
                            System.out.println("Found feed " + pValue.toString() + " in strings");
                            setForeground(Color.GREEN);
                              } else {
                            setForeground(Color.RED);
                          }                                   
                    }

                    return (this);
                }
        });     

        // In this thread I would like to execute action above
        // but it works only one or two times
        SwingWorker worker2 = new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() throws Exception {
                    while (monitor) {
                            //System.out.println("enter to second swing worker");                    
                            //envTree.repaint();
                            //mainFrame.repaint();
                            // should fire DefaultTreeCellRenderer action
                            envTree.setSelectionRow(0);
                            //envTree.setFont(null);                    
                            Thread.sleep(3000);
                    }
                    return null;
                }
                @Override
                protected void done() {                
                    super.done();
                    monitor = false;
                    System.out.println("Done in second swing worker");
                    //progressBar.setVisible(false);                                
                }          
        };
        worker2.execute();                 

正如您从上面的代码中看到的,我使用了两个SwingWorkers。在其中一个中,我向服务器发出请求,以检查另一个工作程序中正在运行的进程 我尝试通过调用envTree.setCellRenderer(new DefaultTreeCellRenderer()来模拟envTree.setSelectionRow(0)动作,以通过JTree中的GREEN和RED颜色标记运行和向下过程。这个动作对我来说不能正常工作的主要问题是,它只能触发一两次,但是当我手动点击JTree时它总是被执行。可以请有人就此提出建议。提前谢谢。

1 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,您可以使用shell获取某种进程列表。此列表存储在字段中,用于创建TreeModel。您希望使用新提供的信息定期将JTree重新标记为TreeModel

JTree与所有Swing组件一样,具有内置机制,可在底层数据发生更改时触发重绘。您更改模型后,模型将触发更改事件,并且视图将拾取此事件。然后视图知道它必须重新绘制。

所以,我会提出这样的解决方案:

  • 检索进程列表的SwingWorker(当前更新循环中的字段)不再使用该字段。相反,它使用SwingWorker#publish方法发布中间结果。然后,您可以覆盖SwingWorker#process方法来处理这些结果。在EDT上调用此方法,并可以使用新信息更新TreeModel。更改TreeModel
  • 时,请确保触发了正确的事件
  • TreeModel应包含与正确呈现数据相关的所有信息
  • 由于对TreeModel和相应事件所做的更改,JTree将安排重新绘制。不需要第二个SwingWorker。由于模型包含渲染器所需的所有信息,因此渲染器可以返回正确状态的Component