DefaultTreeCellRenderer()定期执行 [英] DefaultTreeCellRenderer() execute periodically

查看:129
本文介绍了DefaultTreeCellRenderer()定期执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一些程序来监视UNIX服务器上的进程.我的代码的主要部分看起来像这样:

I write some program for monitoring processes on unix server. The main part of my code is looking like this:

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时,它始终会执行.请有人对此提供建议.预先感谢.

As you could see from code above I use two SwingWorkers. In one of them I make request to server to check which processes is running, in another worker I try to emulate envTree.setCellRenderer(new DefaultTreeCellRenderer() action by calling envTree.setSelectionRow(0), to mark running and downing processes by GREEN and RED colours in JTree. The main problem here that this action doesn't work properly for me, it could fire only one or two times, but when I manually clicked on JTree it always executed. Could please someone advise on this. Thanks in advance.

推荐答案

如果我正确理解了您的问题,则可以使用Shell获得某种进程列表.此列表存储在一个字段中,并用于创建TreeModel.您想使用对TreeModel的新可用信息来定期重新粉刷JTree.

If I understood your question correctly, you obtain some sort of process list using the shell. This list is stored in a field and used to create a TreeModel. You want to periodically repaint the JTree using the newly available info to the TreeModel.

JTree与所有Swing组件一样,具有内置的机制,可在基础数据发生更改时触发重新绘制.您更改模型,模型将触发一个change事件,并且该事件将被视图拾取.然后,视图便知道必须重新绘制.

The JTree, like all Swing components, has a built-in mechanism to trigger a repaint when the underlying data has changed. You alter the model, the model fires a change event and this event is picked up by the view. The view then knows that it has to repaint.

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

So, I would propose a solution like this:

  • SwingWorker(用于检索过程列表(并且当前在循环中更新字段))不再使用该字段.而是使用SwingWorker#publish方法发布中间结果.然后,您可以覆盖SwingWorker#process方法来处理这些结果.在EDT上调用此方法,并且可以使用新信息更新TreeModel.确保更改TreeModel时触发正确的事件.
  • TreeModel应包含与正确呈现数据有关的所有信息
  • 由于对TreeModel和相应事件所做的更改,JTree将安排重新绘制.不需要第二个SwingWorker.并且由于模型包含渲染器所需的所有信息,因此渲染器可以返回正确状态的Component.
  • The SwingWorker which retrieves the process list (and which currently updates a field in a loop) no longer uses the field. Instead, it uses the SwingWorker#publish method to publish the intermediate result. You then override the SwingWorker#process method to handle those results. This method is called on the EDT, and can update the TreeModel with the new information. Make sure that the correct events are fired when altering the TreeModel.
  • The TreeModel should contain all info which is relevant for the correct rendering of the data
  • Due to the changes made to the TreeModel and the corresponding event, the JTree will schedule a repaint. No need for the second SwingWorker. And since the model contains all info needed for the renderer, the renderer can return a Component in the correct state.

这篇关于DefaultTreeCellRenderer()定期执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆