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();
}
});
}
答案 0 :(得分:4)
Swing是一个单线程框架,这意味着您只需要在Event Dispatching Thread的上下文中修改UI元素。同样,任何长期任务或其他阻止过程都会阻止EDT处理新事件。
虽然有很多方法可以实现这一点,但最简单的方法可能是使用SwingWorker
例如......
请查看Concurrency in Swing了解详情
答案 1 :(得分:3)
你最好不要用那种糟糕的方式编写你的java代码。
不要让xxxList扩展JFrame,这会引起误解。 要使用线程更新列表,可以启动一个新线程,如下所示:
之前:不鼓励使用其他非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 ;
}