2013-07-14 3 views
1

У меня есть два класса, один из которых называется GUIFrame, который содержит все графические элементы и класс потоков, называемый squeak. В GUIFrame два графических элементов, первая кнопка, которая при нажатии запускает нить:Темы и обновления Java GUI

futures.put(1, pool.submit(new squeak("SqueakyThread",this.jTextArea1))); 

Второй является javax.swing.JTextArea с переменной под названием jTextArea1.

Второй класс, как упоминалось, является класс резьбы называется писк (реализует Runnable) и размещается при этом (истинный) петлю. Весь этот класс генерирует случайное число от 1 до 10, а затем выводит это число на jTextArea1 в класс GUIFrame.

Вопрос: Является ли это правильным формальным способом обновления элемента GUI в Java?

Я понимаю, что этот вопрос был задан очень много, но со всеми различными ответами там я надеюсь, что это может обеспечить простой шаблон для меня и для других.

GUIFrame.java

import java.util.HashMap; 
import java.util.Map; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 


public class GUIFrame extends javax.swing.JFrame { 

    public GUIFrame() { 
     this.pool = Executors.newCachedThreadPool(); 
     initComponents(); 
    } 

    private ExecutorService pool; 
    private Map<Integer, Future<?>> futures = new HashMap<>(); 
    /** 
    * This method is called from within the constructor to initialize the form. 
    * WARNING: Do NOT modify this code. The content of this method is always 
    * regenerated by the Form Editor. 
    */ 
    @SuppressWarnings("unchecked") 
    // <editor-fold defaultstate="collapsed" desc="Generated Code">       
    private void initComponents() { 

     jButton1 = new javax.swing.JButton(); 
     jScrollPane2 = new javax.swing.JScrollPane(); 
     jTextArea1 = new javax.swing.JTextArea(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

     jButton1.setText("Start"); 
     jButton1.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       jButton1ActionPerformed(evt); 
      } 
     }); 

     jTextArea1.setEditable(false); 
     jTextArea1.setColumns(20); 
     jTextArea1.setRows(5); 
     jScrollPane2.setViewportView(jTextArea1); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addContainerGap() 
       .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 468, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addGap(18, 18, 18) 
       .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 188, Short.MAX_VALUE) 
       .addContainerGap()) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addContainerGap() 
       .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 
         .addGap(0, 0, Short.MAX_VALUE) 
         .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE)) 
        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 444, Short.MAX_VALUE)) 
       .addContainerGap()) 
     ); 

     pack(); 
    }// </editor-fold>       

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     // TODO add your handling code here: 
     futures.put(1, pool.submit(new squeak("SqueakyThread",this.jTextArea1))); 
    }           

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String args[]) { 
     /* Set the Nimbus look and feel */ 
     //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> 
     /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */ 
     try { 
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
       if ("Nimbus".equals(info.getName())) { 
        javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (ClassNotFoundException ex) { 
      java.util.logging.Logger.getLogger(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (InstantiationException ex) { 
      java.util.logging.Logger.getLogger(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (IllegalAccessException ex) { 
      java.util.logging.Logger.getLogger(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
      java.util.logging.Logger.getLogger(GUIFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } 
     //</editor-fold> 

     /* Create and display the form */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new GUIFrame().setVisible(true); 
      } 
     }); 
    } 
    // Variables declaration - do not modify      
    private javax.swing.JButton jButton1; 
    private javax.swing.JScrollPane jScrollPane2; 
    private javax.swing.JTextArea jTextArea1; 
    // End of variables declaration     
} 

squeak.java

import java.util.Random; 
import java.util.concurrent.TimeUnit; 
import javax.swing.SwingUtilities; 

public class squeak implements Runnable { 

    private String Type = ""; 
    private javax.swing.JTextArea MW; 

    squeak (String type, javax.swing.JTextArea MW) 
    { 
     this.Type = type; 
     this.MW = MW; 
    } 

    @Override 
    public void run() 
    { 

     while(true) 
     { 
      UpdateGUI(RandomNumber()+"\r\n"); 

      try { 
       TimeUnit.SECONDS.sleep(10); 
      } catch (InterruptedException e) 
      { 
       UpdateGUI("Thread is now Exiting!\r\n"); 
       //Return cause program to exit the while(true) loop and end 
       return; 
      } 
     } 
    } 

    private int RandomNumber(){ 
     Random r = new Random(); 
     int num = r.nextInt(10-1) + 1; 
     return num; 
    } 


    private void UpdateGUI(final String foo) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       // Here, we can safely update the GUI 
       // because we'll be called from the 
       // event dispatch thread 
       MW.append(foo); 
      } 
     }); 
    } 
}    
+0

1) Чтобы лучше помочь, опубликуйте [SSCCE] (http://sscce.org/). 2) Единственная пустая строка пробела в исходном коде * всегда * достаточно.3) Пожалуйста, ознакомьтесь с общепринятыми [соглашениями по именованию Java] (http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#73307) (в частности, для имен, используемых для имен) для класса , методы и имена атрибутов и использовать их последовательно. –

ответ

1

Что касается,

private void updateGUI(final String foo) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      // Here, we can safely update the GUI 
      // because we'll be called from the 
      // event dispatch thread 
      MW.append(foo); 
     } 
    }); 
} 

Да, это, безусловно, один из способов сделать код позволяет в событие без Swing t hread для обновления компонента Swing - путем очередности запуска в очередь потока событий Swing через SwingUtilities.invokeLater(new Runnable() {...}).

Другой способ, и мой предпочтительный способ - использовать SwingWorker, поскольку он имеет встроенные механизмы, позволяющие запускать код в фоновом потоке и все еще быть в состоянии безопасно совершать вызовы Swing в потоке событий Swing.

Моя первая критика (и я должен найти что-то, чтобы критиковать, правда?) Заключается в том, что ваш код должен следовать соглашениям об именах Swing. Например, имена переменных должны начинаться с буквы нижнего регистра, а не буквы верхнего регистра. Это не так важно, если вы просто создаете код для своего собственного удовольствия, но очень важны, если хотите, чтобы другие просмотрели или обновили или сохранили ваш код.

Моя вторая критика здесь:

jButton1.addMouseListener(new java.awt.event.MouseAdapter() { 
     public void mouseReleased(java.awt.event.MouseEvent evt) { 
      jButton1MouseReleased(evt); 
     } 
    }); 

Вы не должны использовать MouseListeners для JButtons, как это получает слишком низкий уровень. Используйте ActionListeners, так как это то, для чего они созданы, и намного безопаснее. Например, если ваш код отключает действие кнопки или ее модель, кнопка не должна отвечать, но ваш код будет вести себя неправильно и не будет корректно отключен.

+0

Согласитесь с vAriable naming =)) Также протестировали addMouseListener, и вы правы, если отключили кнопку, которая все еще работает. Я правильно говорю, что вы рекомендуете вместо этого: jButton1ActionPerformed (java.awt.event.ActionEvent evt) – DevilCode

+0

Вопрос теперь исправлен для ActionListeners. – DevilCode

+0

@DevilCode: Спасибо за это. Есть ли у вас какие-либо дополнительные вопросы по поводу вашего первоначального вопроса? Отвечал ли мой ответ на ваши проблемы, а если нет, то что еще неясно? –