Getting return values from SwingUtilities.InvokeLater calls?

Related searches

Within my java application I have a JTabbedPane on a main JFrame with many JPanel tabs. Within the tabs I have a function

public void newStatus(final String arg)
{
    Runnable sendMsg = new Runnable() 
    {
        @Override
        public void run() 
        {
           mainView.newStatusLine(arg);
        }
    };
    SwingUtilities.invokeLater(sendMsg);
}

this function calls the main JFrame mainView function to write some text to a JTextPane. My issue is that this doesn't allow me to get a return value from the main JFrame. I would like to do something like

public InfoObj getInfo()
{
    Runnable sendMsg = new Runnable() 
    {
        @Override
        public void run() 
        {
           return mainView.getInfo();
        }
    };
    SwingUtilities.invokeLater(sendMsg);
}

But I am not sure how to make this work. I have tried to and followed my IDE's messages to see if I can get it to maybe work, but I cannot override Runnable.Run to return something.

Are there any mechanisms to do something like this?

EDIT: For HoverCraftFullOfEels, The overall problem is talking between JPanels themselves and between the main JFrame and a JPanel. At some point a JPanel wants to tell the main JFrame to do something, or it might want to get some data from it. But from everything I know I cannot just pass a reference of this to either the JFrame or JPanel and use it to call a public function or read some public field in either.

Sometimes I want to do this not on the EDT via a spawned thread. Some of the JPanel spawn threads and I would like to pass the JPanels reference to the main JFrame so it can call functions within it to tell the user something about what the thread is doing.

It looks like your application data is all bound up inside your user interface objects. If everything you do can be done on the EDT, then you should be OK. You can make direct calls among the objects that need information from each other. Since all of this is on the EDT, it's effectively single-threaded, and there are no race conditions or deadlocks. This, however, can couple various parts of the UI code to each other rather too tightly. In that case you can use some kind of observer or listener pattern as the commenters have suggested. This works fine in a single-threaded, event-driven environment like with AWT/Swing.

But then you say you might want to do this from some thread other than the EDT. That changes everything.

(As an aside, this is the sort of thing that causes people to consider having all your application data bound up inside your UI objects to be an anti-pattern. It makes it quite difficult to get to this data from outside the UI subsystem.)

You could add an observer pattern, but there are restrictions. The UI owns the data, so only the EDT can change the data and fire events to observers. The observers lists need to maintained in a thread-safe fashion. Presumably the observers will want to update data structures in response to events. These data structures will have to be thread-safe, since they're accessed both from the EDT and from your other thread. This approach will work, but you have to do a lot of thinking about which thread is calling which methods, and which data structures have to be made thread-safe.

Assuming you don't want to go this route, let's return to your original question, which was about how to return something from invokeLater. Doing this would let you keep your data in the UI while allowing other threads to get data out of the UI when they need it. It is possible to do this, with a bit of indirection. It does have risks, though.

Here's the code. This can be called from the "other" (non-EDT) thread.

InfoObj getInfo() {
    RunnableFuture<InfoObj> rf = new FutureTask<>(() -> getInfoObjOnEDT());
    SwingUtilities.invokeLater(rf);
    try {
        return rf.get();
    } catch (InterruptedException|ExecutionException ex) {
        ex.printStackTrace(); // really, you can do better than this
    }
}

The trick here is that RunnableFuture is an interface that is both a Runnable and a Future. This is useful because invokeLater takes only a Runnable, but Future can return a value. More specifically, Future can capture a value returned in one thread and store it until another thread wants to get it. FutureTask is a convenient, ready-made implementation of RunnableFuture that takes a Callable argument, a function that can return a value.

Basically we create a FutureTask and hand it a bit of code (the Callable, a lambda expression in this example) that will run on the EDT. This will gather the information we want and return it. We then post this to the EDT using invokeLater. When the other thread wants the data, it can call get() immediately or it can hang onto the Future and call get() later. There is a small inconvenience in that Future.get() throws a couple checked exceptions that you have to deal with.

How does this work? If the EDT runs the Callable first, the return value is stored in the Future until the other thread calls get() on it. If the other thread calls get() first, it's blocked until the value becomes available.

And there's the rub. Astute readers will recognize that this has the same risk as invokeAndWait(), namely, if you're not careful, you can deadlock the system. This can occur because the thread that calls get() might block waiting for the EDT to process the event posted by invokeLater. If the EDT is blocked for some reason -- perhaps waiting for something held by the other thread -- the result is deadlock. The way to avoid this is to be extremely careful when calling something that might block waiting for the EDT. A good general rule is not to hold any locks while calling one of these blocking methods.

For an example of how you can get yourself into trouble with invokeAndWait or with invokeLater(FutureTask), see this question and my answer to it.

If your other thread is entirely decoupled from the UI data structures, this technique should be quite effective.

SwingUtilities.invokeAndWait with return value, It looks like your application data is all bound up inside your user interface objects. If everything you do can be done on the EDT, then you should be OK. Within my java application I have a JTabbedPane on a main JFrame with many JPanel tabs. Within the tabs I have a function public void newStatus(final String arg) { Runnable sendMsg = new Runnable() { @Override public void run() { mainView.newStatusLine(arg); } }; SwingUtilities.invokeLater(sendMs

This works for me JAVA7

 //Here the main thread invokes it
    final RunnableFuture<Data> task = new FutureTask<Data>( new Callable<Data>() {
        @Override
        public Data call() throws Exception {
                  //Here EDT thread
                return calculateData();
           }
        });
        SwingUtilities.invokeLater(task);
        try {
        return task.get();
        } catch (InterruptedException | ExecutionException e) {
            logger.log(Level.SEVERE, "Exception", e);
        }

kschaefe: Returns values from SwingUtilities.in, Method invokeAndWait could be used for calculation, but it does not have e) { // pass exception to original thread except.set(e); } }}); if(except.get()! call() throws Exception { //executed inside EDT return new JPanel(); }})� Compute and return the location of the icons origin, the location of origin of the text baseline, and a possibly clipped version of the compound labels string. Locations are computed relative to the viewR rectangle. The JComponents orientation (LEADING/TRAILING) will also be taken into account and translated into LEFT/RIGHT values accordingly.

I know this question is quite old, but the following should provide a handy workaround for the issue.

You'll need this class to be able to define a final object which encapsulates your return value:

public class Shell<T> {

    private T value;

    public T getValue() {
        return this.value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

Afterward, you can run the whole thing is a nested Runnable f.e. like this:

public InfoObj getInformation() {
    final Shell<InfoObj> returnObj = new Shell<InfoObj>();
    try {
        SwingUtilities.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                returnObj.setValue(mainView.getInfo());
            }
        });
    } catch (InvocationTargetException | InterruptedException e1) {
        e1.printStackTrace();
    }
    return returnVal.getValue();
}

Note that I changed the method name from the question because this method is not meant to be called from within the Runnable. You can call this method from any thread and it will return you a value. However, I've also changed the invokeLater() to invokeAndWait(), because it can happen that the return value is null if the operation you execute in the Runnable has not assigned a value to the Shell object yet. If you don't want your thread to be blocked and use invokeLater() you can also return the Shell object to read it when it has a value.

SwingUtilities (Java Platform SE 7 ), Returns values from SwingUtilities.invoke Blog This method will not block the calling thread and now you have //blocks until future returns return invokeLater( callable).get(); } catch (ExecutionException e) { Throwable t = e. Using SwingUtilities.invokeLater() is not merely advantageous, it's essential, but to understand why you need to understand Swing's threading model. Updates to the GUI, via Swing, must occur on the Event Dispatch Thread (EDT), and code that does anything else (e.g. accessing some resource such as a database) should use one or more other threads.

How can we call the invokeLater() method in Java?, Convenience returning an array of rect representing the regions within rectA Get the index of this object in its accessible parent. This layoutCompoundLabel () does not know how to handle LEADING/TRAILING values in horizontalTextPosition In the following example the invokeLater call queues the Runnable object� Best How To : This is really two questions rolled into one. SwingUtilities.invokeLater() makes sure that whatever you want to do happens on the Event Dispatcher Thread.Since Swing is strictly single threaded, this is required for everything that interacts with Swing and doesn't already run in the EDT (e.g. is called as a result of an event handler) The main() method of your application is one

invokeLater() method works like SwingUtilities.invokeAndWait() except that it puts the request on the event queue and returns immediately. The following are top voted examples for showing how to use javax.swing.SwingUtilities.These examples are extracted from open source projects. You can vote up the examples you like and your votes will be used in our system to generate more good examples.

They run their long-running task on a background thread, and then their Swing GUI is updated with this SwingUtilities.invokeLater code. You can read more about the SwingUtilities.invokeLater method, but here are the best lines of information from that Javadoc: Causes the Runnable to be executed asynchronously on the AWT event dispatching thread.

Comments
  • This smells of a possible XY Problem. Better for you to tell us more the overall issue you're trying to solve and not how you're trying to solve it with code. Also why even queue a Runnable on the EDT here? I presume that this code is already being called from the EDT, no?
  • What part of later don't you understand? That code didn't run yet.
  • Generally to return something you need Callable.
  • Basically, you can't...what you can do is set up some kind of observer pattern
  • @PM77-1: but that wouldn't work if it were queued on the event thread. Then it would behave as a Runnable.
  • I think the answer to my question is in here. But it is not applied to somethign real-world for me to review it properly. I have asked a similar question here stackoverflow.com/questions/25649950/… if you would review it for me?