So I have a button that is supposed to add a new user (whose name is taken from another class) to a list after being pressed. When I press the button by manually clicking on it after building and running, it works fine. The thing is that when I call the ActionEvent method through another method, it outputs my System.out.println text but doesnt add any new entries to the list.
Any suggestions?
Here's the code that is called in a button press (the line marked by an "<--" is the one that only seems to work if I manually press the button) :
public void actionPerformed(ActionEvent e) {
listModel.insertElementAt(name, index); // <--
System.out.println("finished running action");
}
Here's a more complete version of my code:
public void actionPerformed(ActionEvent e) {
System.out.println("ran action");
addAuthor();
System.out.println("authornamefinalfunc name: " + name);
//Reset the text field.
employeeName.requestFocusInWindow();
//employeeName.setText("");
//Select the new item and make it visible.
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
System.out.println("ran action final");
}
private void addAuthor()
{
String name = Global.s;
int index = list.getSelectedIndex(); //get selected index
if (index == -1) { //no selection, so insert at beginning
index = 0;
} else { //add after the selected item
index++;
}
listModel.insertElementAt(name, index);
}
Is the
addAuthor
method always being called on the event dispatch thread?JList
(and everything in Swing) is not synchronized or thread safe so any Swing related modifications/actions must take place on that thread. Since theaddAuthor
method interacts with Swing components, it must never be called from any thread other than that one. This goes for any other method you have in that class (except possibly amain
method if it's well written).If you need to call
addAuthor
, or any other method that directly interacts with Swing components, from a thread that's not the event dispatch thread, use something like this to call the method (this assumes your Swing form is named "myUI"):You can also use
invokeLater
if you want to run the code and not wait for it to finish.If you're not sure what threads code is running from, use these rules of thumb:
main
method, or called by yourmain
method (no matter how many levels deep), is run by the "main" thread.main
method callsfoo()
, which in turn callsbar()
, which in turn callsfoobar()
. All of the code in all of these methods is run by themain
thread.new Thread(...).start()
, that code, and the code in all methods called by it, are run from this thread.ActionListener
above when you press the button) is called by code on the Event Dispatch Thread.Code run on the Event Dispatch Thread is the only code that can safely interact with Swing components. Methods with code that interacts with Swing components (like your
ActionListener
and youraddAuthor
methods) therefore must only be called from code running in the EDT.If you want invoke the methods from any other thread (1 and 2 above), you need to use the method I've shown you above, since you can't do it directly.