So as far as I understood, all the swing components should be created, modified and queried only from the EDT.
So if I happen to press a JButton "submit" let's say, that will pack up all the information from the text boxes, send that data to controller and then controller will send it to other controllers which will eventually send stuff to the server. What thread is the action for that button is running on? If it is running on EDT, how do I exit it to send the data to controller from the main thread? Should I even use main thread to send data to server from the controller?
So what I am saying is this
java.awt.EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
JButton button = new JButton("Submit");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
// WHAT THREAD DO ACTIONS HERE RUN ON?
// AND HOW DO I MAKE THEM RUN ON MAIN THREAD?
// AND WHAT THREAD SHOULD I RUN THING ON HERE?
}
});
}
});
Any action triggered from Swing will run on the EDT. So the code in your actionPerformed method will already be executed on the EDT, without any special handling by you.
To start a long-running task, like sending data to a server, use a SwingWorker or a Callable and an ExecutorService.
I prefer using a SwingWorker when implementing a Swing UI, as has it a useful API for publishing updates and makes the callbacks when the task is done automatically happen on the EDT.
Related
I have page with grid. I am loading data through service to grid. Loading and computing all data takes about 20-40 seconds. When I press button to get data, page start loading (classical in vaadin top loading indicator start loading).
My question is, how can I stop loading/waiting for data?
I can't stop searching process on that server I am getting data from, it dont have this functionality, I can only request for data, and wait for them.
Should I stop some thread? should i use something like this.getUI... and somewhere here stop it?
I am using vaadin 7.7.4
Thank you :)
You should use threads for this.
You will need to separate your logic, that the main thread does add all components to the UI.
This thread then also needs to spawn a new thread which does fetch the data and then updates the UI accordingly.
To update the UI once the data has been fetched from the backend you will need to activate push in your UI.
Don't forget to synchronise thread access to the UI with something like:
ui.access(new Runnable() {
#Override
public void run() {
...grid_update_with_new_data... ;
}
});
The fetching of the data should occur outside the ui.access method, otherwise your UI will freeze during backend data loading.
See this post for more technical details
Using Thread with Vaadin? and https://vaadin.com/docs/v7/framework/advanced/advanced-push.html
#André Schild This is simplified code. When I hit search button, app start searching, no problem with that. Problem is how to STOP searching, before its done. Enough for me is to stop waiting for response, and stop loading bar at top of the page, but I dont know how to achive this.
#SpringComponent
#UIScope
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DistraintSearchComponent extends CustomComponent {
#Autowired
private Service service
private Button searchButton = new Button("Search");
public void init(){
searchButton.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
List<Results> results = service.findByFilter(filter);
refreshGrid(results);
}
});
}
}
I want to append some log strings to a textArea in my vaadin app.
VaadinSqlApplication.logger.info("Export start");
logTextArea.setValue("Export Start");
...
logTextArea.setValue("Export done");
but the textArea only changed after the whole function ended.
Is there any function like in JavaFX :
Platform.runLater(new Runnable() {
#Override
public void run() {
//change text
});
or in swing :
EventQueue.invokeLater(changer);
You need to enable "push" on the Vaadin UI, as by default all updates to the UI will be grouped and sent as a single response (like you say: when the function returns).
Have a look at this page, it explains the whole setup very nicely:
https://vaadin.com/docs/v8/framework/advanced/advanced-push.html
BTW, once push is enabled, you will need a similar technique as the SwingUtilities.invokeLater that you mentioned:
Making changes to a UI object from another thread and pushing them to
the browser requires locking the user session when accessing the UI.
Otherwise, the UI update done from another thread could conflict with
a regular event-driven update and cause either data corruption or
deadlocks. Because of this, you may only access an UI using the
access() method, which locks the session to prevent conflicts. It
takes a Runnable which it executes as its parameter.
For example:
ui.access(new Runnable() {
#Override
public void run() {
...
}
});
I have a simple client-server program. In one thread GUI is running, when I click "connect" button on GUI, I connect to server in new thread, after some time I receive some data from server and I want to pass it to GUI - how can I do that?
Pass a reference to your GUI object to the reading thread, and have the reading thread invoke a method of the GUI instance when he has received the data.
If the GUI is a Swing GUI, you'll need to wrap the call into SwingUtilities.invokeLater():
Thread readingThread = new MyReadingThread(gui);
readingThread.start();
and in the reading thread:
String data = readData();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gui.dataHasBeenReceived(data);
}
});
Note that SwingWorker is designed specifically for this kind of use-case.
Generally - by passing a callback object to the new thread, and whenever you have results, invoke that callback, which in turn updates the GUI.
The "callback" can be an object implementing a custom interface of yours, that takes the result as argument.
BackgroundThread background = new BackgroundThread();
backgroundThread.setCallback(new Foo() {
public void updateGUI(Bar bar) {
//...
}
}
Than, when you have the information available in the background thread, you can just call:
getCallback().updateGUI(bar);
I a making a Java Messenger. I did a login dialog and when I click on the connect button, an animated GIF appears while it's loading.
The problem is that the animated GIF stops moving while my MySQL connection and Query are processing.
I throw the MySQL connection and query in a new thread but still the same :
Thread connectionThread = new Thread(new Runnable() {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Database conection
OlaDB.createConnection();
...
What can I do to avoid my GIF freezing ?
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads.
Have a look at SwingWorker and Using a Swing Worker Thread.
also Read up on on Concurrency in Swing for more information on why the GUI freezes and for a working example of using a Swing Worker. (via #camickr)
in my class I have an inline thread in the constructor that loads objects from a remote site:
Thread readSite = new Thread(new Runnable() {
public void run() {
site.loadStuff();
}
});
readSite.start();
I want to display a 'loading' message until the thread is finished. So before the above code I show a loading message.
After the above code I show the screen in which I would like to continue.
The code looks like this:
showLoadingView(); //tells the user it is waiting
Thread readSite = new Thread(new Runnable() {
public void run() {
site.loadStuff();
}
});
readSite.start();
showStuffView(); //works with the data retrieved from the site instance
Now, the main thread of course continues and the showStuffView() is directly executed.
I can now let the main thread wait for the readSite Thread, but then the user cannot accept the connection request ('is it ok to use airtime?') that is shown to the user (because the responsible thread is asleep I guess).
On the other side, I cannot execute the showStuffView() from the readSite Thread.
I hope you guys can explain how to wait for this thread. I looked into synchronized, but couldn't really find a nice solution.
I think this is a common problem with threads and this particular problem you can solver with boolean variable. but for general purpose i think observer pattern is good.