I am building a JavaFX app and am using JOptionPane to display dialogs
One of the problems I've encountered is that creating a new dialog and not dismissing it within 5 or so seconds will cause the main JavaFX stage go into a 'Not Responding' state
Running the joptionpane code in a new thread works, but causes the dialog not to be modal, which is not suitable for the app i'm building
This is all running in Windows.
Any ways to fix the not responding problem would be greatly appreciated :)
EDIT: The code I use is (from the main JavaFX thread)
JOptionPane.showMessageDialog(null, "message here");
Perhaps null is causing the problem?
You can't just show a JoptionPane, which is a Swing component, from the FX thread. You have three options:
create a Swing application and place all the fx nodes in JFXPanels.
use FX nodes only, for example by using a modal stage or by using an external library such as ControlsFX (JavaFX 8 only but there are other libraries available that work with JavaFX 2)
place your JOptionPane in a SwingNode (JavaFX 8 only)
For 1 and 3 you need to be careful to create/modify the Swing components on the Swing EDT thread and the JavaFX nodes on the JavaFX thread (unless you merge the two with the new JVM option available in Java 8). And I'm not 100% sure how the modality week work if you mix Swing and JavaFX.
If you are creating a JavaFX application there is little reason not to choose 2.
Don't use JOptionPane in a JavaFX application, use a JavaFX Alert instead. Alert was introduced in Java 8u40.
Using JOptionPane in JavaFX may be problematic due to the reasons pointed out in assylias's answer.
See also:
No errors, but crashing - JOptionPane - JavaFX
Related
I am making use of JavaFX's built in Alert and Dialog classes which work great in Windows and when running from Eclipse within Windows, but appear behind the parent window when running on my target hardware which is running RedHat 6. I have tried tweaking various things including:
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setFullScreen(true);
alert.initOwner(primaryStage) and alert.initOwner(primaryStage.getOwner())
alert.initModality(Modality.WINDOW_MODAL) and alert.initModality(Modality.APPLICATION_MODAL)
alert.initStyle(StageStyle.***) with *** being all possible styles.
The only way I have been able to get the alerts and dialogs to remain on top is by calling alert.initStyle(StageStyle.UTILITY) however this creates a window with a cross button which I do not want. Ideally I would prefer a bordered window without additional buttons, or an undecorated window which I should then be able to style to achieve the bordered look.
I have read of similar issues in which using Windows doesn't work but Ubuntu does. I haven't been able to find any open issues or solutions in this case.
I am using Java 8 Update 77.
I have experienced a similar problem: Alerts would show perfectly well in front of the primary stage in Windows 10, yet behind the stage when running the program on Ubuntu. alert.initOwner(primaryStage) actually solved the problem for me.
I would like to create system modal dialog. I mean a dialog that blocks the entire system screen, not a particular application. So far I found Application modality and Toolkit modality that might be replaced even with manual disabling blocked frames, but still no function to lock the entire screen as in a native application. How can I do this?
Well, so far I found the answer:
There is a note on docs.oracle.com:
Note : The new modality model does not implement a system modality,
which blocks all applications (including Java applications) that are
displayed on the desktop while a modal dialog box is active.
As I can see, I just have to seek different way for my task.
FXML performance is an issue with JavaFX, if you have complex screens and have divided them into small components (for maintainability / reuse) that use FXML, then it can get really slow.
As FXML parsing is made in UI Thread (not sure of this, still it blocks the JavaFX Application Thread), you cannot show a glasspane / popup / etc in JavaFX when FXML is being processed.
The only workaround I found is to use a Swing popup (as it is in Swing UI Thread, you can still show something) to provide a feedback to the user (it is working / not a bug / wait a little more) when FXML is being loaded and to close it when no more FXML files are parsed.
I have built a facade above FXMLLoader to do so. Also this also works with OpenGL libraries as well (LWJGL for instance, instead of Swing, anything that is UI and is not in JavaFX Application Thread works).
I was wondering if a better solution exists (JavaFX only, not mixing UI frameworks) as this artificially adds complexity to the project and won't be ported well with OpenJFX ports.
Recommended Solution
Use JavaFX 8u40+, you can find an early access release.
For 8u40, the following bug was fixed:
RT-17716 Some controls can only be created on the FX application thread
This fix allows you to create all controls (except currently a WebView) off of the JavaFX application thread. That means you can load up your FXML asynchronously to the JavaFX application thread within a standard JavaFX Task. While the task is running you can have a please wait dialog or animated progress indicator displayed or whatever you like (in JavaFX, no need to use other frameworks like Swing/LWJGL).
My favorite way of handling this is to load the FXML elements up while the user is shown a login prompt or needs to create some input (but whether or not you use the "load stuff in the background while awaiting user input" trick is app dependent).
You can also load your FXML in the init function of your application, so that the FXML is loaded in parallel to the JavaFX system starting up (you need to take care around threading a bit for that to ensure that you don't actually try to show your scene until all the FXML is loaded and the operation to show the scene occurs on the JavaFX application thread).
Alternate Solution
You could also try this solution to Convert FXML to Java as part of the build, then perhaps there won't be any issue with slow loading of FXML (because there is no longer any FXML, it has been converted to Java). But I don't know if that solution is currently mature and stable enough for your purposes.
Multi-window applications often have a main-window, and all other windows are kind of 'parented' to it. Minimizing such a sub-window will hide its content and show the title-bar at the bottom-left of the screen. Also, these windows do not have their own Icon in the Task-bar, only the main-window does.
How can I make a window being attached this way to another window?
If that is possible, is it also possible without a referenfe to the actual main window?
#2: I'm embedding Java into such an application and I would like to be able to use awt or swing additionally to the native dialogs, which have this behavior by default.
See How to Use Internal Frames.
have look at JInternalFrames for MDI application
read Oracle tutorial, try code example
I have written a swing application in Java and want to display the logo of the application at program start-up for a couple of seconds before the actual program GUI appears. How do you think I can do this in swing?
A built-in Splash-Screen Functionality was added in Java SE 6, take a look here .
You can use SplashScreen: SplashScreen.getSplashScreen().setImageURL(imageURL)
If it does not meet your requirements for some reason you can either create instance of java.awt.Window or javax.swing.JWindow and put image at the middle of the window. Use Timer to disappear this window after specific timeout.
You can also use Frame or JFrame and call its f.setUndecorated(false)