2014-01-06 81 views
2
public class ListExample { 
    public static void main(String[] args) { 
     final List l=new List(); 
     l.init(); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       l.list.updateUI(); 
       System.out.println("Asim"); 
      } 
     }); 
    } 
} 

public class List extends JFrame{ 
    public DefaultListModel DLM=new DefaultListModel(); 
    public JList list=new JList(DLM); 
    private JPanel jp=new JPanel(); 
    private JScrollPane sp=new JScrollPane(list); 
    public void init(){ 
     jp.add(sp); 
     super.add(jp); 
     super.setVisible(true); 
     super.setLayout(new FlowLayout()); 
     super.setSize(400,500); 
     UL p=new UL(); 
     p.UL_1(); 
    } 
    public void Update_list(String[] n){ 
     list.setListData(n); 
     list.updateUI(); 
    } 

} 
public class UL extends List{ 
    public void UL_1(){ 
     t.start(); 
    } 
    Thread t=new Thread(new Runnable() { 
     @Override 
     public void run() { 
      //To change body of implemented methods use File | Settings | File Templates. 
      String[] n={"Asim", "saif","Khan"}; 
      List l=new List(); 
      l.list.setListData(n); 
      list.updateUI(); 
     } 
    }); 
} 
+1

請做一些解釋有關面臨的問題!單獨發佈代碼不會給任何人任何想法,至於__什麼和如何解釋問題。它告訴所提供的,至於你有多少知識,你自己掌握的問題手頭:-) –

+0

對不起,我面臨的問題是從另一個線程更新我的Jlist 我正在製作一個程序,它將更新目前在GUI類中的JList另一個線程 堅果此代碼是一個例子是不適合我:( – user3164210

回答

3

你最好不要以糟糕的風格編寫你的java代碼。

不要讓xxxList擴展JFrame,這會引起誤解。 要使用一個線程更新的列表,可能是你可以開始一個新的線程,就像follwing:

前:不鼓勵使用其他非EDT線程,招致錯誤。

import java.awt.FlowLayout; 
import javax.swing.*; 
/* 
* This code is bad dealing with Swing component update 
* 
* Update a Swing component from A Non-EDT thread is not encouraged 
* may incur error like: 
* 
* Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
*/ 
public class ListExampleBad { 
    public static void main(String[] args) { 
     final ListFrame listFrame=new ListFrame(); 
     listFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       //use a thread to update list data 
       new Thread(new UpdateList(listFrame)).start(); 
       System.out.println("Asim"); 
      } 
     }); 
    } 
} 
//list fram with JList 
class ListFrame extends JFrame{ 
    public ListFrame(){ 
     jp.add(sp); 
     super.add(jp); 
     super.setVisible(true); 
     super.setLayout(new FlowLayout()); 
     super.setSize(400,500); 
    } 
    public synchronized void updateList(String[] n){ 
     list.setListData(n); 
     list.updateUI(); 
    } 
    private static final long serialVersionUID = 1L; 
    private DefaultListModel<String> DLM=new DefaultListModel<String>(); 
    private JList<String> list=new JList<String>(DLM); 
    private JPanel jp=new JPanel(); 
    private JScrollPane sp=new JScrollPane(list); 
} 
//runnable dealing with data update 
class UpdateList implements Runnable { 
    public UpdateList(ListFrame listFrame) { 
     this.ListFrame = listFrame; 
    } 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     if(SwingUtilities.isEventDispatchThread()) { 
      System.out.println("updating list from Event Dispatch Thread"); 
     }else { 
      System.out.println("updating list NOT from Event Dispatch Thread"); 
     } 
     String[] n={"Asim", "saif","Khan"}; 
     ListFrame.updateList(n); 
    } 
    private ListFrame ListFrame; 
} 

謝謝誰提出意見,我更新代碼:

「核心Java」引導我們拖原則:

1)不要在做一個費時的工作EDT線程,使用SwingWorker。

2)除EDT外,不要在其他線程中運行Swing組件。

此外,您可以使用SwingUtilities.isEventDispatchThread()檢查作業是否在EDT線程中執行。

一種方法:使用SwingUtilities.invokeLater

public class ListExampleBetter { 
    public static void main(String[] args) { 
     final ListFrameBad listFrame=new ListFrameBad(); 
     listFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     //use SwingUtilities.invokeLater,it's ok 
     SwingUtilities.invokeLater(new UpdateList(listFrame)); 
    } 
} 

另一種方法:使用SwingWoker

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.List; 

import javax.swing.*; 
/** 
* This example illustrate updating JList from thread 
*/ 
public class ListExample { 
    public static void main(String[] args) { 

     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       ListFrame listFrame = new ListFrame(); 
      listFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       listFrame.setLocationRelativeTo(null); 
       listFrame.setVisible(true); 
      } 
     }); 
    } 
} 
//frame with JList 
class ListFrame extends JFrame{ 
    public ListFrame(){ 
     super("Update JList Demo"); 

     //initalize data field 
     dataToUpdate =new String[]{"Asim", "saif","Khan"}; 
     DefaultListModel<String> DLM =new DefaultListModel<String>(); 
     DLM.addElement("wait for update...");; 
     list =new JList<String>(DLM); 

     //build gui 
     JPanel btnPanel = new JPanel(); 
     JButton btnUpdate = new JButton("Update"); 
     btnPanel.add(btnUpdate); 
     JScrollPane sp=new JScrollPane(list); 
     this.add(btnPanel,BorderLayout.NORTH); 
     this.add(sp,BorderLayout.CENTER); 
     this.setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT); 

     //deal with action 
     btnUpdate.addActionListener(new ActionListener(){ 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       // TODO Auto-generated method stub 
       ListUpdater updater = new ListUpdater(); 
       updater.execute(); 
      } 
     }); 
    } 
    public synchronized void updateList(String[] n){ 
     list.setListData(n); 
     list.updateUI(); 
    } 
    //using Swingworker to update list 
    private class ListUpdater extends SwingWorker<Void,String>{ 
     @Override 
     public Void doInBackground() { 
      for(String str :dataToUpdate) { 
       publish(str); 
      } 
      return null; 
     } 
     @Override 
     public void process (List<String> datas) { 
      for(String str : datas) { 
       model.addElement(str); 
      } 
     } 
     @Override 
     public void done() { 
      if(SwingUtilities.isEventDispatchThread()) { 
       System.out.println("updating list from Event Dispatch Thread"); 
      }else { 
       System.out.println("updating list NOT from Event Dispatch Thread"); 
      } 
      list.setModel(model); 
     } 
     private DefaultListModel<String> model =new DefaultListModel<String>(); 
    } 
    public String[] getDataToUpdate() { 
     return dataToUpdate; 
    } 
    public void setDataToUpdate(String[] dataToUpdate) { 
     this.dataToUpdate = dataToUpdate; 
    } 

    private static final long serialVersionUID = 1L; 
    private final int DEFAULT_WIDTH = 300,DEFAULT_HEIGHT = 300; 
    private JList<String> list ; 
    private String[] dataToUpdate ; 
} 
+0

嘿,兄弟thanx的答案 而我會按照你的意見:) – user3164210

+1

這仍然是錯誤的。你應該從事件線程更新'JList',而不是使用事件線程產生_another_線程,然後更新'JList'。只需在'main'中對正確的線程進行更新:'SwingUtilities.invokeLater(new UpdateList(listFrame));' – DaoWen

+0

或者使用SwingWorker – MadProgrammer

4

Swing是單線程架構,這意味着你的預計只修改來自事件調度線程的上下文中的UI元素。同樣,任何長期運行任務或其他阻塞流程都會阻止EDT處理新事件。

雖然有許多的方法你可能做到這一點,可能是最簡單的辦法是使用一個SwingWorker的

例如...

看看在Concurrency in Swing欲瞭解更多詳情