【问题标题】:DefaultTreeCellRenderer() execute periodicallyDefaultTreeCellRenderer() 定期执行
【发布时间】:2014-10-23 08:35:39
【问题描述】:

我写了一些程序来监控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();                 

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

【问题讨论】:

  • 为了尽快获得更好的帮助,请发布MCVE(最小完整可验证示例)。
  • worker2 不应从 doInBackground() 更新树。

标签: java swing jtree swingworker


【解决方案1】:

如果我正确理解了您的问题,您将使用 shell 获得某种进程列表。此列表存储在一个字段中并用于创建TreeModel。您希望使用TreeModel 的新可用信息定期重绘JTree

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

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

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

【讨论】:

  • 感谢您的回复,我原样离开,但没有第二个 SwingWorker 并在第一个 SwingWroker 的第一个 doInBackground() 方法中调用 envTree.repaint(),现在它工作正常。实际上你的想法很有趣,但是从你的回复中我可以看出我需要为此实现 TreeModel 类。
猜你喜欢
  • 2012-05-17
  • 1970-01-01
  • 2015-10-29
  • 2023-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-08
相关资源
最近更新 更多