سؤال

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();
        }
    });
}
هل كانت مفيدة؟

المحلول 2

You'd better not to write your java code in that bad-style.

Don not make xxxList extends JFrame ,which will cause misunderstanding. To use a thread update a list,may be you can start a new thread,like follwing:

Before: not encouraged to use another non EDT thread,incur error.

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;
}

Thank you who make comments, I update the code:

《core java》 guides us tow principle:

1)don't do a time-consuming job in EDT thread,using a SwingWorker.

2)Except from EDT,don not operate Swing componnet in other thread.

Besides,you can use SwingUtilities.isEventDispatchThread() to check if the job is doing in a EDT thread.

one way: use 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));
    }
}

another way:using 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 ;
}

نصائح أخرى

Swing is a single threaded framework, this means that your are expected to only modify the UI elements from within the context of the Event Dispatching Thread. Equally, any long run task or other blocking process will prevent the EDT from processing new events.

While there are a number of ways you might achieve this, probably the simplest would be to use a SwingWorker

For example...

Take a look at Concurrency in Swing for more details

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top