Some JList actions not being executed when ActionE

2019-09-10 03:49发布

问题:

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

    }

回答1:

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 the addAuthor 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 a main 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"):

SwingUtilities.invokeAndWait(new Runnable() {
  @Override public void run() {
    addAuthor();
  }
});

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:

  1. Any code that is in your main method, or called by your main method (no matter how many levels deep), is run by the "main" thread.
    • For example, your main method calls foo(), which in turn calls bar(), which in turn calls foobar(). All of the code in all of these methods is run by the main thread.
  2. If you manually create a new Thread, for example with something like, new Thread(...).start(), that code, and the code in all methods called by it, are run from this thread.
  3. All Listener code invoked by the UI (for example your 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 your addAuthor 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.