Aggiornamento occasionale di JLIST su Pulsante Premere
Domanda
Stavo cercando di aggiornare il contenuto di una JLIST quando è stato premuto un pulsante. Quindi, ho cancellato il modello dell'elenco, quindi ho cancellato l'elenco e quindi ho proceduto ad aggiungere nuovi valori all'elenco. Ecco il codice strippato:
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()
}
}
Il problema che sto affrontando è che quando l'elenco creato per la prima volta, aggiorna la JLIST. Quando il pulsante viene premuto di nuovo, la JLIST viene aggiornata solo a volte. E per ulteriori pressioni del pulsante non viene visualizzato nulla nella JLIST.
Qualcuno potrebbe aiutarmi a capire cosa sta causando questo problema? Grazie.
Soluzione
Il tuo problema principale è probabilmente correlato all'aggiornamento della GUI di swing da un thread che non è il AWT-EDT.
Potresti voler leggere e/o cercare di usare Sweworker (spedito con Java 6 e anche Disponibile per il download per l'uso con le versioni precedenti di Java.)
In alternativa, dai un'occhiata a questo approccio:
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
}
Altri suggerimenti
Una cosa che stai facendo è creare un nuovo thread e quindi apportare modifiche al tuo componente GUI al di fuori di EventDispatchThread. Questa non è generalmente una grande idea. Prova a correre il updateList()
In posizione, che sarà sull'EDT, poiché gli eventi del pulsante vengono gestiti in quel thread.