How to use the Progress Bar in Java (Netbeans GUI) - java

I am not too experienced with Java and am having trouble getting a progress bar to work. I am using Netbeans' built-in GUI maker. Currently my program reads in images from a directory into an image array. Obviously this takes a bit of time, thus I would like a simple progress bar to update the user to know how far the loading is. I have used one of those drag-and-drop progress bar components.
I currently can get the number of files in a directory and can calculate the percentage of files loaded
The files successfully load into the array, but the progress bar is only updated after all files are loaded. I have tried revalidating and repainting while I loop but this does not work
I have tried the various tutorials on docs.oracle but can't seem to get anything working.
I believe SwingWorker is the class I should be using, is this correct?
Any help with an example or some advice would be greatly appreciated!
Thanks!

Yes, you have run into the trap of all new Swing programers - the Event Dispatching Thread
Basically speaking, this Thread is the heart of any Swing system. Is is responsible for dispatching events to all the UI components, as well as making requests to the repaint manager to update the UI.
If you do any time consuming tasks while in the EDT, you will prevent the UI from been updated.
I'd suggest you start by having a read through Worker Threads and SwingWorker and Concurrency in Swing and, because I know you're going to ask, have a read of this answer, it has a number of examples of using SwingWorker, JTextArea appending problems

Related

What does this error mean JXBrowser should only be constructed on the EDT

I have some code and when it executes, it throws a RuntimeException, saying:
JXBrowser should only be constructed on the EDT
it is stemming from when I'm creating a JXbrowser component
browser = (JXBrowser) browserFactory.create(true, WebBrowserType.JX);
What should I look for in fixing this error?
JavaFX (OpenJFX) is not thread-safe.
Like Swing, Vaadin, and most any other user-interface framework, you must limit all access to, and manipulation of, the widgets and other UI-related objects only from within the one thread dedicated to that framework.
Apparently your app is starting other threads and then performing JavaFX work on them. Never do this.
There are ways for you to perform lengthy tasks on background threads, and then upon completion post a request to the UI thread to update the UI widgets with the results. But you must study to learn those techniques.
See this tutorial and this one.
JxBrowser dropped this requirement since version 7.
In JxBrowser 7, you can initialize Engine and Browser in any thread. These operations are heavy and it's better not to do them in EDT.
Once the browser is created, you will need to create BrowserView and add it to your interface inside of EDT, according to Swing rules.

How can I disable automatic background clearing in a Java graphical application?

I am a Java developer with some expertise in graphical programming but not very skilled with the most recent techniques.
I am developing a Java graphical application using Apache Netbeans IDE 11.2; the application includes many structured panels (split panels, tab controls) and executes 2D drawings on some of them, using Swing and AWT.
The application worked well until now. After the last modifications, I am facing the following problem:
The application properly performs all drawings (polylines, rectangles and so on) on the main panel, but abruptly the panel is cleared and the original background restored, deleting all drawings.
The debugging shows that the clearing is not performed by any statement of the program. So I suppose that it is managed behind the scenes by AWT or something like this.
I understood that Swing automatically implements double buffering (anyway I also inserted a setDoubleBuffered statement), so I made the drawings directly on the screen without using a buffer. On the other hand, this had worked perfectly until now.
My questions are:
How can I detect the event that causes the causes the restore of the background? And how can I prevent this restore?
A solution could be to disable Swing Double Buffering and code it explicitly. I am not sure of this. Any hint?
Thank you very much for any suggestion.

Busy popup in JavaFX when FXML parsing is too slow

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.

Creating multiple windows in SWT

I'm trying to create a Window class which I can use to open multiple windows, and which will automatically add an event handler to listen for the Swt.CLOSE event, and call the shell.dispose() method when it is called.
My questions are:
Do I need to listen for shell.dispose() in this case, or to only listen for display.dispose() in my main method?
Do I need to run each window in its own thread, or can all the windows share the same UI thread? I've read some reports of buggy behavior related to event handling in case of multiple windows being open.
I recommend you should always have a single UI thread, which the single Display object runs on. See SWT: single vs. multiple displays or even the Eclipse documentation on Display that strongly recommends using a single Display object:
Applications which are built with SWT will almost always require only a single display. In particular, some platforms which SWT supports will not allow more than one active display.
There are even several sample apps available (such as this one) that demonstrate multiple shells in SWT. Calling shell.dispose() when you want to close a window is the way to go.
You should only use display.dispose() when you are shutting down the entire app, basically as a 'last step' - see this example, or this one, or pretty much any snippet on the SWT Snippets page.
Edit
The Eclipse framework itself is an example of an application that can have multiple windows - it still uses a single Display, with a single UI Thread and shared event system. Eclipse documentation on Threading Issues has a basic explanation of this:
Underneath any GUI application, regardless of its language or UI toolkit, the OS platform detects GUI events and places them in application event queues. [...] It determines which window and application should receive each event and places it in the application's event queue.

Java - How to change cursor without Swing Component?

I have a Java application that run as a background service, i.e. no GUI. But when starting it, say through a batch script, I have some preparation works to be done at the very beginning of my program (something like communicate with server).
I want a busy cursor appear at this busy moment. Is it possible to do this without using any Swing component? Thanks for any suggestion or alternative approach.
I'd go for a console-based "progress bar". It's possible to use Swing but it would render your solution useless in a headless environment. Drawing progress bars with characters in terminal is quite a common practice.
You can either implement it yourself or use a ready class. Just take a look at github or bitbucket and you'll find something for sure.
A busy cursor could even be displayed as a caption with alternating last character (as simple as possible), with "frames" like these (rotating bar)
LOADING DATA /
LOADING DATA |
LOADING DATA \
LOADING DATA -
Implementing something like this wouldn't take much time. We're talking about minutes here.
If the only thing that prevents you from using Swing is an appearing window, you can change its appearance thanks to window translucency. This way you'd get an animated image overlaying your screen. It wouldn't work in a terminal though.
If you're able to use Java AWT (Abstract Window Toolkit) I beleive you can use the setCursor of Component class to change the cursor.
More on this : http://www.roseindia.net/java/example/java/awt/ChangeCursor.shtml

Categories