Win a copy of Secure Financial Transactions with Ansible, Terraform, and OpenSCAP this week in the Cloud/Virtualization forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Rob Spoor
  • Henry Wong
  • Liutauras Vilda
Saloon Keepers:
  • Tim Moores
  • Carey Brown
  • Stephan van Hulst
  • Tim Holloway
  • Piet Souris
Bartenders:
  • Frits Walraven
  • Himai Minh
  • Jj Roberts

How to measure of a writer progress for JProgressBar value

 
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a java program which can download data from MySQL and write them in a chosen file format e.g. TXT. Here is the txt writer:



This writer is called in a JCombobox actionperformed as in an other java file:



I would like to show the progress of the writer with JprogrssBar, but I do not know how should
I measure the writer progress (i.e. the integer value for set the JprogressBar value). Could someone suggest me a solution?

 
Saloon Keeper
Posts: 23439
159
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's not a proper PreparedStatement. And, in fact, it's both a security risk and a risk for throwing an Exception.

The easiest way to show progress is to issue the same SQL selection twice: first "SELECT COUNT(*) FROM xxx WHERE ..." which will return you the expected number of records that you will be reading and writing.

The second SQL selection will select the actual data so that you can then process it.

The percentage value to display on the progressbar will then be the number of rows read so far divided by the total number of rows that you got from the first query (COUNT). Don't forget to invalidate the progress bar so that the GUI thread will re-draw it with the new value!

Also on an active database, the COUNT you get might not exactly match the number of records that the second query actually returns if other requests have inserted and/or deleted records. But then again, Windows file copy progress bars are infamous for their imprecision, so I wouldn't worry about minor aberrations.
 
Beata Szabo-Takacs
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Tim for your help! I tried your suggestion but unfortunately,
SQL connection blocks the JProgressBar or any GUI. According to
my best knowledge, swingworker should fix it. I do not have experience
in swingworker. Could someone help me how I should use it in the above-
mentioned code?
 
Marshal
Posts: 26493
81
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It sounds like you're using a Swing GUI. So, if the code you posted actually runs long enough that a JProgressBar is going to be useful, then it shouldn't run in the Swing thread.

That implies that the changes you make are nothing to do with that code. Or at least, very little to do with it. The posted code should be running in a different thread, for a start.

But in the code you posted, the vast majority of the elapsed time is going to be taken up by the SQL query. The remaining code, which writes to a file, isn't going to take very long at all unless the file is very large. So I don't quite see how a JProgressBar would be useful.
 
Ranch Hand
Posts: 65
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, this doesn't has to do anything with Swing itself in particular but rather with how GUIs work in more general: Most modern graphical desktops work on a "event queue -> redraw"-loop. That means, that there's at least one thread constantly running in a loop which only sole purpose is to listen for user input events and dispatch them to registered listeners - and also for listening to updates changing the gui and performing a re-draw of what has to be redrawn. If you lock up this very important loop you end up with most users know as "the program hangs and becomes un-responsive" - exactly what you experience: "my jprogressbar hangs". Other "famous" types of such issues (and re-occuring threads on this forum) are topics like "I made a counter - but it doesn't count and after a while it only shows the final value" and a-like.

They keyword here is "de-coupling" - to split of your long time task into it's own separate thread. But, care must be taken when updating the GUI - as Swing is not thread safe. This means, that only the EDT, the Event Dispatch Thread, should do the gui updates, no other thread. So, after you de-coupled your long time task from the edt you have to re-enqueue your updates into it. In the most basic form a quick example looks a bit like this:

So, it's basically nesting threads in eachother:

1. actionPerformed() is called from within the EDT - but you want to execute a task that takes way longer then just a few couple of milliseconds - so, in order to keep your gui responsive and give it a chance to redraw the updates you decouple your task into it's own thread
2. the outer run() is called from the newly created and separate running thread - so it can do what ever it wants to do - except from updating anything gui relatde
3. as you work with a gui you not just use it to take user inputs - but also to display result outputs - but care must be taken as gui updates has to be done from within the edt again - using something like SwingUtilities.invokeLater() grants you a way to (a-)synchronously enqueue your own update request events into the edt to have it executed by it - there's invokeLater() which just drops of the update request and goes along with your task - and then there's invokeAndWait() which blocks until the GUI has completely updated and your update request is done - there're several use cases for both of them

Yes, I know, that's the style of a very old book written for 1.4.2 - and today there are way more fancy ways to do such things in way cleaner way - but it illustrates the issue, its cause, and a way to solve it very clearly - I even missed out on lambdas for the sake of readability.

However you end up doing it - you have to keep in mind: all that gui stuff runs in the edt - and my stuff  has be de-couple from it. How you do it is up to you - there're several different ways today.
 
Beata Szabo-Takacs
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dear Matthew,
Thank you for your response. I could solve the issue based on
the second answer in https://stackoverflow.com/questions/768966/running-2-threads-simultaneously.

I changed my code from FileWriter to void and I set up a Swing Frame in one runnable thread
and I used another thread for file writing and run them simultaneously e.g.


 
Matthew Bendford
Ranch Hand
Posts: 65
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, I don't see any updates to the JProgressBar. Also: You're code is rather unnecessary as at least the first Thread is not required (in fact it's rather bad as it does fiddle with some Swing outside of EDT, which should be avoided as I mentioned).
I didn't look into the other thread linked, but from it's title I can guess its content.
 
Tim Holloway
Saloon Keeper
Posts: 23439
159
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Swing is operating in Model/View/Controller mode, so to update a ProgressBar, two things have to be done:

1. The model value in the JProgressBar has to be updated.

2. The Controller system has to be notified of the change.

While Swing does its rendering (painting) in a separate thread than the application logic runs under, it normally only runs a paint cycle when some event happens. For example, you have some other window overlapping the Swing window and you move it, uncoivering a previously-hidden area. In the case of the JProgressBar control, you have to "invalidate" the part of the display that renders the JProgressBar so that the rendeing thread will know to re-draw it.

You can iforce repainting of the entire window client area, but that tends to flicker badly, so usually you only want to mark the components that actually need updating.
 
Tim Holloway
Saloon Keeper
Posts: 23439
159
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I recommend this tutorial: https://docs.oracle.com/javase/tutorial/uiswing/components/progress.html

Note that since Java has PropertyChangeListeners actual marking of the progress geometry invalidation may be done by an automatic listener.
 
Sheriff
Posts: 22124
114
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That type threading is dangerous with Swing. You should read Concurrency in Swing.

In short: all UI access must be done on the Event Dispatcher Thread (EDT). The file writing should be done in a different thread, but updates to the UI (progress bar) should be done on the EDT. A SwingWorker is a good way to do this easily. Its doInBackground can do the writing; it can use publish to send updates to the EDT, which you can handle by overriding process. If needed you can override done to do any post-processing work on the EDT.
 
Matthew Bendford
Ranch Hand
Posts: 65
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To which do you refer to?
 
Fire me boy! Cool, soothing, shameless self promotion:
SKIP - a book about connecting industrious people with elderly land owners
https://coderanch.com/t/skip-book
reply
    Bookmark Topic Watch Topic
  • New Topic