DefaultTreeCellRenderer() execute periodically

一世执手 提交于 2019-12-12 04:54:06

问题


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();                 

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.


回答1:


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.

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:

  • 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.


来源:https://stackoverflow.com/questions/26524209/defaulttreecellrenderer-execute-periodically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!