I got a problem with setting a value to a JProgressBar which i got from inside a type returning method. I know I have to do multi threading but I´m really new to this topic and really don´t know how to implement this.
I try to briefly explain my dilemma in code:
This is my data returning method to count lines in a String (e.g. from a JTextArea or whatsoever).
public static int countLines(String s) {
int count = 0;
String[] words = s.split("\n");
for(String i: words) {
count++;
}
return count;
}
What I want to add is a method inside this method that sets my JProgressBar that I created in my JFrame to the value count. E.g. setProgress(count);
Is this even possible? Because i tried several ways of doing this and no matter what, the progressbar only updates AFTER the return value has been sent out.
Do I have to run this method in an own Thread or just the progress setting method? or both?
Cheers!
Do I have to run this method in an own Thread or just the progress setting method? or both?
Both tasks should run in separate threads: business logic (in this case word's count) must be performed in a background thread while progress bar update must run in the Swing thread, also known as Event Dispatch Thread (EDT).
IMO the best way to accomplish this is by using a SwingWorker:
doInBackground()
implementation.PropertyChangeListener
to the swing worker to listen for progress
property and update the progress bar within this listener.doInBackground
to set the worker's progress and fire a property change event notifying your listener.There are a lot of examples here in SO, just take a look to swingworker tag. Also, consider this snippet:
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
// Following code is performed in a background thread
@Override
protected Void doInBackground() throws Exception {
String[] words = string.split(System.lineSeparator());
int totalWords = words.length;
for (int count = 0; count < totalWords; count++) {
int progress = (count + 1) * 100 / totalWords;
setProgress(progress);
}
return null;
}
};
worker.addPropertyChangeListener(new PropertyChangeListener() {
// Following code is performed in the EDT, as all event handling code is.
// Progress bar update must be done here, NOT within doInBackground()
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
Integer progress = (Integer)evt.getNewValue();
progressBar.setValue(progress);
}
}
});