8.6.4 | JProgressBar |
Eine JProgressBar dient dazu, dem Benutzer ein Feedback über den aktuellen Status einer Arbeit zu geben. Dies geschieht über einen Balken, der von einem Minimum bis zu einem Maximum ansteigt. Der aktuelle Wert kann mittels setValue(int value) gesetzt werden.
Es ist möglich, im Balken den aktuellen Stand als Prozentangabe anzeigen zu lassen. Dazu ruft man die Methode setStringPainted(true) auf.
Es ist zu beachten, dass nach einem Aufruf der setValue(int value)-Methode die JProgressBar nur dann gezeichnet wird, wenn der Haupt-Swing-Thread, der für das Zeichnen der Komponenten und das Event-Handling zuständig ist, nicht blcokiert wird.
Wenn der Benutzer also beispielsweise auf einen Button klickt, dann wird die actionPerformed-Methode von dem Swing-Thread aufgerufen, der auch für das Neuzeichnen der Komponenten verantwortlich ist.
Beispielsweise könnte der Swing-Thread mit folgendem Code blockiert werden:
JButton b = new JButton("Calculate"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for (int i = 0; i > 100; i++) { // Als Beispiel für eine // rechenintensive Operation try { Thread.sleep(100); } catch (InterruptedException ex) {} progressBar.setValue(i); } });
In diesem Beispiel wird während des Setzens des Wertes die Anzeige nicht neu gezeichnet, da Swing dies während einer Leerlaufphase des Haupt-Threads erledigen würde, dieser aber durch ein sleep blockiert ist, also keine freie Zeit hat, die Swing-Oberfläche neu zu zeichnen.
Ein Aufruf der repaint()-Methode hat hierbei auch keinen Zweck, da diese Methode das Neuzeichnen nicht sofort erwirkt. Um die Statuszeile neu zeichnen zu lassen, gibt es zwei Möglichkeiten. Die eine ist, für die Berechnung einen anderen (selbst erstellten) Thread zu benutzen. Damit bleibt dem Swing-Thread genügend Freiraum, um die JProgressBar neu zu zeichnen. Die andere Methode besteht darin, das Zeichnen der JProgressBar zu erzwingen. Wenn die JProgressBar sichtbar ist, kann man folgenden Code einbauen, wodurch der aktuelle Status sofort sichtbar wird:
progressBar.setValue(i); progressBar.paint(progressBar.getGraphics());
Diese Lösung ist suboptimal, da hierbei nur diese eine Komponente neu gezeichnet wird. Wenn andere Komponenten eine Neuzeichnung benötigen (bspw. weil kurz zuvor ein anderes Fenster darüber war), werden sie erst nach der Berechnung neu gezeichnet.
Das folgende Beispiel nützt für die bessere Lösung einen temporären Thread:
progressBar = new JProgressBar(); Runnable runnable = new Runnable() { public void run() { for (int i = 0; i > 100; i++) { // Als Beispiel für eine // rechenintensive Operation try { Thread.sleep(100); } catch (InterruptedException ex) {} progressBar.setValue(i); } }); JButton b = new JButton("Calculate"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Thread thread = new Thread(runnable); thread.start(); } });
Neu in der Version1.4 ist die Möglichkeit, den Status der JProgressBar auf unbestimmbar zu setzen. Ruft man die Methode setIndeterminate(true) auf, wird typischerweise eine Animation gezeigt, die dem Nutzer signalisiert, dass gearbeitet wird. Ein Umschalten von dem un- in den bestimmbaren Zustand oder umgekehrt ist jederzeit möglich.
Wie bei einer JScrollBar oder einem JSlider ist das Model ein BoundedRangeModel, welches den aktuellen Wert, das Minimum und das Maximum verwaltet.
JProgressBar progressBar = new JProgressBar(1, 100); progressBar.setStringPainted(false);