你最好不要以那种不好的风格编写你的Java代码。
不要让xxxList继承JFrame,这会引起误解。
如果要使用线程更新列表,可以启动一个新线程,如下所示:
之前:不鼓励使用另一个非EDT线程,会导致错误。
import java.awt.FlowLayout;
import javax.swing.*;
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() {
new Thread(new UpdateList(listFrame)).start();
System.out.println("Asim");
}
});
}
}
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);
}
class UpdateList implements Runnable {
public UpdateList(ListFrame listFrame) {
this.ListFrame = listFrame;
}
@Override
public void run() {
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;
}
谢谢留言的朋友,我已经更新了代码:
《core 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);
SwingUtilities.invokeLater(new UpdateList(listFrame));
}
}
另一种方法:使用SwingWorker
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.*;
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);
}
});
}
}
class ListFrame extends JFrame{
public ListFrame(){
super("Update JList Demo");
dataToUpdate =new String[]{"Asim", "saif","Khan"};
DefaultListModel<String> DLM =new DefaultListModel<String>();
DLM.addElement("wait for update...");;
list =new JList<String>(DLM);
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);
btnUpdate.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
ListUpdater updater = new ListUpdater();
updater.execute();
}
});
}
public synchronized void updateList(String[] n){
list.setListData(n);
list.updateUI();
}
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 ;
}