Helo guys!
I am new to JavaFX. I am writing really small application which simulates working of printer. Simulation is running on special thread called PrintingProcess (this process is doing only one thing - waits given time and then increment counter). I need to send this value to window, where labels should show how many pages was "printed". Is any way to do it? So far I wrote small singleton class to hold value.
[edit] I solved it using tasks :) thanks for help
You should use the Task.updateProgress method. Call it to specify the current percentage of pages printed. Override Task.call to perform the action which needs to run in another thread. This method should never manipulate a JavaFX component. You can then oerride methods such as Task.succeeded to implement the behaviour of your UI when the print job is over. Look at the doc of this class to fully take advantage of it.
Platform.runLater(new Runnable() {
#Override public void run() {
textLabel.setText(yourValue);
}
});
The example above is quite simple. You ask JavaFX a runnable as soon as it can. I don't know how that works exactly but that's the way to change UI components from a non-JavaFX thread.
You could pass textLabel variable to any thread with a custom class or a new anonymous thread.
EDIT:
I find Dici's answer more appropriate for your application. I wouldn't recommend putting this code in any loop incase you may still use this.
Related
So im quite new to MVC structure.And im really confused on where/when to add my Gui part on EDT.
This is where im really confused:
public class ECPS_MVC {
//edt?
EcpsView view =new EcpsView();//shoud i put it on edt here?? SwingUtilities... etc
//edt?
EcpsModel model =new EcpsModel();
EcpsController controler=new EcpsController(view,model);
}
I have seen question on how to start gui on edt when using mvc
How to Start a Java MVC Application With a Swing GUI
And answer suprised me.Why shoud be Model on edt as well?Is that really correct??I dont think so.
So question1- When is the best time to put my Gui on edt.When i create View?
question 2- Do i have to do updates from my controller like this?Each time? -
public void setIconLabel(final Icon icon) {
SwingUtilities.invokeLater(new Runnable() {//with swingutil on each method where i work with gui?
#Override
public void run() {
myLabel.setIcon(icon);
}
});
}
If you understand please point me right direction and if needed provide short example code.Thank you.
Anything that interacts or can change the UI in anyway MUST do so from within the context of the Event Dispatching Thread.
Swing, by design, is not thread safe. That is, there are no checks in the default libraries to make determinations about what thread the various models and components are been executed on, it is assumed the developer will already have made these determinations.
So question1- When is the best time to put my Gui on edt.When i create View?
Immediately. You have no way of knowing when a component may become realised (displayed on the screen and/or attached to a native peer)
question 2- Do i have to do updates from my controller like this?Each time? -
No, in fact, I'd be very worried if I found myself coding like this all time. Make the determination that the models and components MUST be executed within the context of the EDT and make whatever is interacting with these models and components meet these requirements.
This would mean, if you are loading data from a separate Thread, you would need to ensure that any time they update the model, they are synchronizing these updates to the EDT to ensure that if the model notifies the UI, it all occurs within the context of the EDT.
Don't make assumptions about the state of the model, statements like "I know..." will come back to haunt you, especially when some one else makes use of your API.
Unless you physically create the model yourself (outside the EDT) and guarantee it's isolation while it's being loaded, don't assume anything that is given to you isn't attached to the UI in some way.
An easier solution is to use a SwingWorker when you want to perform operations off the EDT, as it provides this synchronisation via it's publish/process/done methods
I'm trying to teach myself JavaFX and stumbled over a problem I can't seem to fully understand even after reading anything remotely related I could find.
What I'm trying to do :
I basically want to run some quick processing in the background of my JavaFX application so to not block the UI for the user. While this is happening a UI element is put up which then should be removed as soon as the background process is finished.
So what I attempted to do was to just move those method calls into a Task which should then run without making the UI freeze.
Task task = new Task<Void>() {
#Override
protected Void call() {
step1();
step2();
step3();
}};
new Thread(task).start();
I want to call multiple methods of the class we're currently in, but what's happening instead is that only the first method gets invoked. It seems to me that after step1 has reached it's end it doesn't actually "return" to the Task. I've tried looking up how this works and what I could do but honestly didn't get any smarter. Basically all examples of threading and workers only included how to loop and do recurring things but I really just want a "single execution" but in background.
It's probably a really idiotic thing I'm trying to do and shows my little understanding of this but if anyone could point me into the right direction I'd be very thankful.
Thanks a lot!
Solution :
When working with JavaFX the use of "Platform.runLater(task)" is advisable since a normal Thread cannot interact with the UI. A IllegalStateException will be thrown and the thread is halted/canceled(?). The Task itself can remain unchanged but has to be handed to the Platform to execute it to prevent this issue. I changed that one line and everything was perfect afterwards.
I hope this might help someone, someday :-)
In my university, we are working with interfaces, using QT Jambi (Java) with the Eclipse Integration.
I would like to improve my design of my Elevator interface.
The main problem is that I would like to update the QLCDNumber with the floor in real-time.
What I do to simulate the elevator working, is to do a Thread.sleep(1000) between 2 floors, so that way, my QLCDNumber will display "an animation" saying "1...2...3...4". The problem is that the QLCDNumber only displays 1 and 4, no animation.
So, for example (resumed), the code I made is this one:
private void simulate(int floor){
while(actualFloor < floor){
try{
Thread.sleep(1000);
}catch(InterruptedException e){};
actualFloor++;
ui.LCDfloor.display(actualFloor);
}
}
Why this code only shows the 1st floor and the last one?
Sorry if you didn't understand what I wanted, my English is improving every day :)
Thank you in advance.
*Please note that LCDFloor is the name of the QLCDNumber widget
It looks like you have two problems:
(I assume) You're calling Thread.sleep() on the GUI thread. In other words, when you call simulate, you're doing so on the same thread as the rest of the gui operations. This causes the entire gui to pause.
You've never given Qt the chance to actually update the UI. When you call ui.LCDfloor.display(actualFloor), the a paint event is queued so that the UI can be updated, but rather than giving the UI a chance to actually execute the paint event, you continue with your loop which prevents the UI from ever being updated until after your simulation is finished.
You have two basic fixes:
Don't sleep, it's poor design. Instead, use timer's and signals to simulate the changes.
Force events to be processed using processEvents.
Also keep in mind that you can't update a GUI element from a non gui thread. And as this is homework, I'll leave the rest to you :).
I'm new to Java threads and after testing to see how they work, I can't figure out how to make them do calculations and return the result the way I want.
For example, in my current program, I want my thread to query a database by calling a method that returns the data in a Vector object when I click a JButton. Then, with that vector object, I want to add each index (an array) as a row in a JTable.
What would be the correct way to accomplish this? I know I could use a setter on my JTable in the calling class but I'm sure there has to be a more "correct" way.
Yes, use a SwingWorker. This mechanism is designed for situations where you need to have a long running task run in a background thread and provide updates to the UI either when done, or while processing. Since Swing is single-threaded, this allows the UI to remain responsive.
or basic workaround by impements Runnable where output to the GUI must be wrapped into invokeLater more about in Concurrency in Swing
As part of a larger application, I am writing a settings class, which collects and stores user-defined settings. This class is a singleton, and is instantiated during application startup.
In order to accept user input, two different GUI frames are insantiated from within ConfigSettings.java, from a public static method, selectSettings(). Both are subclasses of JFrame. Here is the code for the instantiation of the file selection dialog:
private void selectFile() {
SelectFileGUI fileSelector = new SelectFileGUI();
fileSelector.setVisible(true);
synchronized(this) {
try {
wait();
} catch(Exception e) {
e.printStackTrace();
}
}
fileSelector.dispose();
}
This works fine when the application is initially run. However, at a later point the user may alter their selected settings, including selecting a new source file. This is done by calling selectSettings() again.
The issue I'm having is that any subsequent attempt to instantiate and display these GUI components again results in a new JFrame being displayed, but with a grey background, and no buttons or other components shown. While debugging I was also failing to create new instances of SelectFileGUI directly.
What could be causing this sort of behaviour?
I would check to see if the second time you call it you are using the GUI thread or calling from one of your own threads.
At the top of that method you can test for it (The AWT thread is pretty easily identifiable by name) and have it throw an exception so developers know not to call it on the wrong thread--or you can block their thread and do it in a worker thread.
I don't know what is causing this behavior but in your code the following simply cannot possibly be the right way to manage dialogs (more below):
fileSelector.setVisible(true);
synchronized(this) {
try {
wait();
} catch(Exception e) {
e.printStackTrace();
}
}
fileSelector.dispose();
Do you want your dialogs to be modal or not?
If you want them to be modal, then you simply make a blocking call like when you're invoking JColorChooser.showDialog(...) method and your return "value" is your color/file/whatever.
If you want them non-modal, then you use a callback to get your color/file. In the JColorChooser dialog example, you'd call the createDialog(...) method and use the ok/cancel listeners as callbacks.
I suggest you take a look at sun's tutorial, for example the one on color chooser, to see how to correctly display a modal (or non-modal) dialog:
http://java.sun.com/docs/books/tutorial/uiswing/components/colorchooser.html
Once again, that synchronized(this) { try { wait() ... } to manage something as simple as a file selector/dialog frame just cannot be correct.
Agree with BillK: sounds like you're calling it from outside the EDT first time around (so your call to wait() doesn't block the EDT), then from the EDT the second time around. See SwingUtilities.invokeAndWait() and/or Dialog.setModal().
The consensus here is that you are breaking the rules governing the use of the AWT painting thread (the Event Dispatch Thread).
A couple things to note:
If your code attempts to paint your GUI components outside this painting thread, the gray dialog could be the result of a deadlock between the EDT and the thread your application is using to paint.
If you do get into this situation, you will experience the inability to create new dialogs as described.
However, as you mention that you are debugging while experiencing this problem, it might be that you have paused the EDT through your IDE.
Take a look at this tutorial for some guidelines on how use threads in a client application.
To fully appreciate the issue, it would be nice to see some more code - pertinent parts of selectSettings(), for example.