2014-10-23 2 views
0

Я пишу программу для мониторинга процессов на сервере unix. Основная часть моего кода выглядит так:DefaultTreeCellRenderer() периодически выполняет

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. Основная проблема здесь в том, что это действие не работает должным образом для меня, оно может срабатывать только один или два раза, но когда я вручную нажимал на JTree, он всегда выполнялся. Может, кто-нибудь посоветует об этом. Заранее спасибо.

+2

Для получения более подробной помощи отправьте сообщение [MCVE] (http://stackoverflow.com/help/mcve) (минимальный полный проверенный пример). –

+4

'worker2' не должен обновлять дерево из' doInBackground() '. – trashgod

ответ

1

Если я правильно понял ваш вопрос, вы получаете какой-то список процессов, используя оболочку. Этот список хранится в поле и используется для создания TreeModel. Вы хотите периодически перерисовывать JTree, используя новую информацию до TreeModel.

JTree, как и все компоненты Swing, имеет встроенный механизм для запуска перерисовки при изменении базовых данных. Вы изменяете модель, модель запускает событие изменения, и это событие подхвачено представлением. Затем представление знает, что оно должно перерисовываться.

Итак, я хотел бы предложить решение так:

  • SwingWorker, который извлекает список процессов (и который в настоящее время обновляет поле в цикле) больше не использует поле. Вместо этого он использует метод SwingWorker#publish для публикации промежуточного результата. Затем вы переопределяете метод SwingWorker#process для обработки этих результатов. Этот метод вызывается на EDT и может обновить TreeModel с новой информацией. Убедитесь, что при изменении TreeModel активируются правильные события.
  • TreeModel должен содержать всю информацию, которая имеет отношение к правильной визуализации данных
  • Из-за изменений, внесенных в TreeModel и соответствующее событие, JTree будет перерисовку. Нет необходимости во втором SwingWorker. А поскольку модель содержит всю информацию, необходимую для рендерера, рендер может вернуть Component в правильном состоянии.
+0

Спасибо за ответ, я оставил, как было, но без второго SwingWorker и вызовет envTree.repaint() в первом методе doInBackground() первого SwingWroker, теперь он работает нормально. На самом деле ваша идея очень интересная, но, как я мог видеть из вашего ответа, мне нужно реализовать для этого класс TreeModel. – Iurii

Смежные вопросы