使用工作线程,Java运行我的方法,并在其中一个方法中填充JList
。问题是,当我运行程序时,JList没有得到更新,但通过Netbeans调试,列表得到了正确更新!!
如何证明这一点?
代码看起来像
public class TheFrame extends javax.swing.JFrame {
public TheFrame() {
theFile = new ExcelFile();
initComponents();
}
@SuppressWarnings("unchecked")
private void initComponents() {
model = new DefaultListModel();
effectList = new javax.swing.JList<>();
effectList.setModel(model);
pack();
}
/* worker threads is here */
private ExcelFile theFile;
private DefaultListModel<String> model;
private javax.swing.JList<String> effectList;
}
worker的实现是
private void Load(JFileChooser fc, int i)
{
/* i is an identifier which shows which button has been pressed */
/* stuffs for creating a please wait window */
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws InterruptedException {
if ( i == 1 ) {
List< String > ls = theFile.updateEffectList();
for (int i = 0; i < ls.size(); i++) {
// The following line works fine in the debug mode
// but By running the project, it will be empty
model.addElement(ls.get(i));
}
effectList.setVisible(true);
}
return null;
}
@Override
protected void done() {
loading.dispose(); // this is the please wait window
}
};
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
//System.out.println(evt.getPropertyName());
Object value = evt.getNewValue();
if (value instanceof SwingWorker.StateValue) {
SwingWorker.StateValue state = (SwingWorker.StateValue) value;
switch (state) {
case DONE: {
try {
worker.get();
} catch (InterruptedException | ExecutionException ex) {
JOptionPane.showMessageDialog(null, "Failed");
ex.printStackTrace();
}
}
break;
}
}
}
});
worker.execute();
loading.setVisible(true); // this is the please wait window
}
有一些讨论,但我没有得到答案。
答案 0 :(得分:0)
这里有一个Minimal, Complete, and Verifiable example(可能不是 最小)!
我还强烈建议您研究SwingWorker
's documentation并查看Swing's Threading Policy。
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class TheFrame {
public static void main(String[] args) {
new TheFrame();
}
private JFrame frame;
private JList<String> list;
private DefaultListModel<String> model;
private JButton load;
private TheFrame() {
SwingUtilities.invokeLater(this::initGUI);
}
private void initGUI() {
// runs on EDT
model = new DefaultListModel<>();
list = new JList<>(model);
// for testing
load = new JButton("Load");
load.addActionListener(ev -> load());
frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(list), BorderLayout.CENTER);
frame.add(load, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 300);
frame.validate();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void load() {
// runs on EDT
frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
// runs on worker Thread
List<String> ls = updateList();
for (String string : ls) {
simulateDelay(200);
publish(string);
}
return null;
}
@Override
protected void process(List<String> chunks) {
// runs on EDT
for (String string : chunks) {
model.addElement(string);
}
}
@Override
protected void done() {
// runs on EDT
try {
get(); // check for Exceptions
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
} finally {
frame.setCursor(Cursor.getDefaultCursor());
}
}
};
worker.execute();
}
// generate some sample data
private List<String> updateList() {
simulateDelay(500);
List<String> data = Arrays.asList("a", "b", "c", "d", "e", "f", "g");
Collections.shuffle(data); // just fun.. erh, testing
return data;
}
// for testing only, do not use this in production/real code
private static void simulateDelay(long delay) {
try {
Thread.sleep(delay);
} catch (@SuppressWarnings("unused") InterruptedException ignored) {
}
}
}