2010-11-19 109 views
1

我試圖在按下按鈕時更新JList的內容。所以,我清除了列表模型,然後清除了列表,然後繼續向列表中添加新值。這裏是剝離代碼:按鈕上的JList的Occational更新按

testList.java

public class testList extends javax.swing.JFrame { 

    private Thread t; 
    public DefaultListModel model; 
    public boolean first = true; 

    public testList() { 
     model = new DefaultListModel(); 
     initComponents(); 
     this.centre(this); 
    } 

    public static void centre(javax.swing.JFrame f) { 
     Dimension us = f.getSize(), them = Toolkit.getDefaultToolkit().getScreenSize(); 
     int newX = (them.width - us.width)/2; 
     int newY = (them.height - us.height)/2; 
     f.setLocation(newX, newY); 
    } 

    class updateList implements Runnable { 

     public void run() { 
      tmp.getTheList(); 
      model.clear(); 
      ouputList.removeAll(); 

      for (int i = 0; i < tmp.returnList.size(); i++) { 
       model.addElement(tmp.returnList.get(i)); 

      } 
      if (first) { 
       chList.setModel(model); 
      } 

     } 
    } 

    private void initComponents() { 
    // generated by NetBeans 6.9 
    } 

    private void buttonActionPerformed(java.awt.event.ActionEvent evt) { 
     t = new Thread(new updateList(), "List Updater"); 
     t.start(); 
    } 

    public static void main(String args[]) { 

     tmp = new aC(); 

     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       new chapList().setVisible(true); 
      } 
     }); 
    } 

    static aC tmp; 

    private javax.swing.JButton button; 
    public static javax.swing.JList outputList; 
    private javax.swing.JScrollPane jScrollPane1; 
} 

ac.java

public class aC extends testList { 

    ArrayList returnList = new ArrayList(); 

    void getTheList() { 
     returnList.clear(); 
     generateList(); 
    } 

    void generateList() { 
    // populate returnList with random values of random size using returnlist.add() 
    } 
} 

我面臨的問題是,當列表中首次創建,它更新JList。當再次按下按鈕時,JList有時會被更新。爲了進一步按下按鈕,JList中不顯示任何內容。

有人可以幫我找出是什麼原因導致這個問題? 謝謝。

+0

如果你被允許,用大寫字母開始你的班名。這是大多數Java開發人員使用的慣例,因此它使得許多Java開發人員更容易閱讀您的代碼。 – 2010-11-19 01:18:48

+0

謝謝你讓我知道。我會改變類名。 – Monk 2010-11-19 01:34:43

回答

3

您的核心問題可能與更新不是AWT-EDT的線程的Swing GUI有關。 (隨Java 6中,也available for download與早期版本的Java使用)

您可能希望瞭解和/或考慮使用SwingWorker

或者,看看這個方法:

import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 
import javax.swing.*; 

public class BackgroundWorkerFrame extends javax.swing.JFrame { 
    public BackgroundWorkerFrame() { 
     initComponents(); 
     jList.setModel(new DefaultListModel()); 
    } 

    private void jButtonGoActionPerformed(ActionEvent evt) {           
     Thread t = new Thread(new WorkerRunnable()); 
     t.start(); 
    }           

    public class WorkerRunnable implements Runnable { 
     public void run() { 
      System.out.println("Working hard..."); 
      sleep(1000); 
      ArrayList<Integer> list = new ArrayList(); 
      for (int i = 0; i < 5; i++) { 
       list.add((int) (Math.random() * 100)); 
      } 
      System.out.println("Updating GUI..."); 
      SwingUtilities.invokeLater(new UpdateRunnable(list)); 
     } 
    } 

    public class UpdateRunnable implements Runnable { 
     private final ArrayList<Integer> list; 
     private UpdateRunnable(ArrayList<Integer> list) { 
      this.list = list; 
     } 
     public void run() { 
      DefaultListModel model = (DefaultListModel) jList.getModel(); 
      model.clear(); 
      for (Integer i : list) { 
       model.addElement(i); 
      } 
     } 
    } 

    @SuppressWarnings("unchecked") 
    // <editor-fold defaultstate="collapsed" desc="Generated Code"> 
    private void initComponents() { 

     jButtonGo = new JButton(); 
     jScrollPane = new JScrollPane(); 
     jList = new JList(); 

     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     jButtonGo.setText("Go"); 
     jButtonGo.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
       jButtonGoActionPerformed(evt); 
      } 
     }); 
     getContentPane().add(jButtonGo, BorderLayout.PAGE_START); 

     jScrollPane.setViewportView(jList); 

     getContentPane().add(jScrollPane, BorderLayout.CENTER); 

     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     setBounds((screenSize.width-309)/2, (screenSize.height-338)/2, 309, 338); 
    }// </editor-fold> 

    public static void sleep(long ms) { 
     try { 
      Thread.sleep(ms); 
     } catch (InterruptedException ex) { 
      ex.printStackTrace(); 
      Thread.currentThread().interrupt(); 
     } 
    } 

    public static void main(String args[]) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       new BackgroundWorkerFrame().setVisible(true); 
      } 
     }); 
    } 

    // Variables declaration - do not modify 
    JButton jButtonGo; 
    JList jList; 
    JScrollPane jScrollPane; 
    // End of variables declaration 
} 
+0

這非常接近我的意圖。但是,我想清除現有列表並顯示新生成的列表。我嘗試清除代碼中的列表,模型和數組列表,但無法成功清除它。但是,我真的很喜歡把另一個Swing Worker叫做UI更新的想法。 – Monk 2010-11-19 01:59:41

+0

@Monk我在填充新數據之前更新了應用程序以清除列表。 – 2010-11-19 02:08:30

+0

對不起。我只是將模型聲明移到循環上方,並將其清除。像黃油一樣工作。謝謝。我會嘗試在我的代碼中實現。 – Monk 2010-11-19 02:13:32

1

您正在做的一件事是創建一個新的線程,然後在EventDispatchThread之外更改您的GUI組件。這通常不是一個好主意。嘗試運行updateList(),因爲按鈕事件在該線程中處理,將在EDT上。

+0

從我注意到的,名單第一次更新。在此之後,線程「List Updater」實際上死亡。只有在按下按鈕後纔會重新啓動。所以,線程應該像第一次那樣工作。另外,如果我正確理解了你,你建議我在線程死後更新JList。如果是這樣,我應該在哪裏放置代碼,因爲線程將同時運行,我將調用一個空的數組列表。謝謝 – Monk 2010-11-19 01:41:15