Профессиональное обновление JList по нажатию кнопки - PullRequest
1 голос
/ 19 ноября 2010

Я пытался обновить содержимое JList при нажатии кнопки. Итак, я очистил модель списка, затем очистил список и затем продолжил добавлять новые значения в список. Вот раздетый код:

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 ничего не отображается.

Может ли кто-нибудь помочь мне выяснить, что является причиной этой проблемы? Спасибо.

Ответы [ 2 ]

3 голосов
/ 19 ноября 2010

Ваша основная проблема, вероятно, связана с обновлением графического интерфейса Swing из потока, который не является AWT-EDT .

. Возможно, вы захотите прочитать ои / или изучите использование SwingWorker (поставляется с Java 6, а также доступен для загрузки для использования с более ранними версиями Java.)

Кроме того, взгляните на этот подход:

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
}
1 голос
/ 19 ноября 2010

Одна вещь, которую вы делаете, - это создание нового потока, а затем внесение изменений в компонент GUI вне EventDispatchThread. Это вообще не очень хорошая идея. Попробуйте запустить updateList() на месте, которое будет в EDT, так как события кнопки обрабатываются в этом потоке.

...