JProgressBar Indeterminate

JensMander

Bekanntes Mitglied
Hallo Forum,
ich hoffe ihr könnt mir Helfen. Aktuell ändere ich den Zustand meiner JProgressBar mit:

Java:
progressBar.setValue(x);

Das gefällt mir eigentlich ziemlich gut, nun möchte ich aber gerne das der Balken der bereits fortgeschritten ist, genauso blinkt wie bei Indeterminate(true). Ist das irgendwie möglich?

Sinn besteht darin, dass ziwschen einigen Fortschrittsanzeigen einige Stunden(Bearbeitung von ca.1mio Geodaten) vergehen und einige Anwender die geduld verlieren und abbrechen, weil ja nichts mehr passiert....

vielen Dank für eure Hilfe.
mit freundlichem Gruß
Jens
 
Zuletzt bearbeitet von einem Moderator:
du könntest im progressbar neben ladebalken auch Progressfortschritt in Prozent angeben, dann sieht man ja dass der Prozess noch läuft.

Code:
progressBar.setStringPainted(true)
 
ja, das ist alles richtig, aber der ottonormal Nutzer, der hätte eben gerne, dass sich etwas bewegt, solange gearbeitet wird, ähnlich der Sanduhr bei windows. Und deshalb hätte ich eben gerne den Ladenbalken blinkend*G*
 
Mach doch sowas:
Java:
/* (@)JProgressBarTest.java */

/* Copyright 2011 Sebastian Haufe

 * Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       [url]http://www.apache.org/licenses/LICENSE-2.0[/url]

 * Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

package com.ebenius;

import java.awt.GridLayout;
import java.awt.event.*;

import javax.swing.*;

/**
 * JProgressBar test GUI.
 * 
 * @author Sebastian Haufe
 */
public class JProgressBarTest {

  private static Timer timer;

  /** Creates the GUI. Call on EDT, only! */
  static void createAndShowGui() {
    final String[] actionTexts =
          { "Initializing\u2026", "Fetching Data\u2026", "Calculating\u2026",
            "Done.", };

    final int[] actionDuration = { 1900, 1200, 10 * 1000, 0 };

    final JPanel contentPane = new JPanel(new GridLayout(2, 1, 6, 6));
    final JProgressBar actionPrgBar = new JProgressBar(0, 100);
    actionPrgBar.setValue(0);
    actionPrgBar.setString(actionTexts[0]);
    actionPrgBar.setStringPainted(true);
    contentPane.add(actionPrgBar);

    final JProgressBar busyPrgBar = new JProgressBar();
    busyPrgBar.setStringPainted(false);
    busyPrgBar.setIndeterminate(false);
    contentPane.add(busyPrgBar);

    timer = new Timer(actionDuration[0], new ActionListener() {

      private int actionIndex = 0;

      public void actionPerformed(ActionEvent e) {
        actionIndex++;
        timer.stop();
        if (actionIndex >= actionTexts.length) {
          return;
        }
        actionPrgBar.setValue(actionIndex * 100 / (actionTexts.length - 1));
        actionPrgBar.setString(actionTexts[actionIndex]);
        busyPrgBar.setIndeterminate(actionIndex == 2);
        timer.setInitialDelay(actionDuration[actionIndex]);
        timer.start();
      }
    });
    timer.setRepeats(false);
    timer.setInitialDelay(actionDuration[0]);

    final JFrame f = new JFrame("Test Frame: JProgressBarTest"); //$NON-NLS-1$
    f.addWindowListener(new WindowAdapter() {

      @Override
      public void windowOpened(WindowEvent e) {
        timer.start();
      }
    });
    f.setContentPane(contentPane);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }

  /** @param args ignored */
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

      public void run() {
        createAndShowGui();
      }
    });
  }
}
Oder ändere mit einem javax.swing.Timer den String; zum Beispiel indem Du immer die 0, 1, 2, 3 Punkte durchrotierst:
[c]Calculating[/c], [c]Calculating.[/c], [c]Calculating..[/c], [c]Calculating...[/c], [c]Calculating[/c], usw.

Ebenius
 
Ich wollte etwas ähnliches wie ebenius vorschlagen, allerdings dabei eine JProgressBar für den Gesamtfortschritt und eine für den Fortschritt beim aktuellen Datensatz einsetzen.
So oder so: die Verwendung von zwei JProgressBars dürfte für dein Problem am sinnvollsten sein (oder du schreibst in deine einzelne JProgressBar einen String wie "Verarbeite Datensatz 238.256 von 1.373.643" und setzt bei jedem DS die Zahl auf den aktuellen Wert, sofern möglich).
 
Oder zeichne es selber. Hier mal was auf die schnelle:
Java:
package de.sample.components;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JComponent;

public class TProgress extends JComponent implements Runnable
{
	private static final long serialVersionUID = 1L;

	private double percent=0.0;
	
	private int greenValue=255;
	private Color progColor=new Color(0,greenValue,0);
	
	private boolean ANIMATION=false;

	public void startAnimation()
	{
		ANIMATION=true;
		Thread anim=new Thread(this, "Animated Progressbar");
		anim.setDaemon(true);
		anim.start();
	}
	
	public void stopAnimation()
	{
		ANIMATION=false;
		greenValue=255;
		progColor=new Color(0,greenValue,0);
	}
	
	@Override
	public void run() 
	{
		while(ANIMATION) {
			for(int i=0;i<150 && ANIMATION;i++) {
				progColor=new Color(0, --greenValue, 0);
				repaint();
				try { Thread.sleep(5); } catch(InterruptedException e) {}
			}
			
			for(int i=0;i<150 && ANIMATION;i++) {
				progColor=new Color(0, ++greenValue, 0);
				repaint();
				try { Thread.sleep(5); } catch(InterruptedException e) {}
			}
		}
	}	
	
	public void setPercent(double percent) {
		this.percent=percent;
		repaint();
	}
	
	@Override
	protected void paintComponent(Graphics g) 
	{
		Graphics2D g2d=(Graphics2D) g;
		
		paintProgress(g2d);
		paintBorder(g2d);
		
		g2d.dispose();
	}		
	
	private void paintProgress(Graphics2D g)
	{
		GradientPaint gp=new GradientPaint(getWidth()/2, 0, progColor, getWidth()/2, getHeight()-1, progColor.darker());
		g.setPaint(gp);
		g.fillRoundRect(0, 0, (int)(getWidth()*percent), getHeight()-1, 5, 5);
	}	
	
	private void paintBorder(Graphics2D g) 
	{
		g.setColor(Color.BLACK);
		g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 5, 5);
	}
}
 
vielleicht wäre es besser, wenn du es einfach gestalltest und anzeigst wie lange der Prozess ungefähr dauern wird.
Wenn es wirklich um stunden handelt dann wird der benutzer ganz sicher nicht den Ladebalken anglotzen bis die Arbeit erledigt ist. 😀
Der ottonormal Nutzer ist bestimmt an die Ottonormale Windows oder Unix FortschrittAnzeigen gewöhnt und da blinkt jetzt nicht so viel 🙂

😳
 
Hi vielen Dank für eure zahlreichen Tipps.
Also "meine" ottonormal Nutzer werden alle Win nutzen und da blinkt der Fortschrittsbalken sogar beim Kopieren von Dateien (im Zweifel fliegen da die Blätter durch die Gegend)...Und ja ich hoffe die Nutzer werden nicht alle vorm Schirm sitzen und diesen anstarren. Aber Sie werden frustriert sein, wenn sie morgens im Büro auftauchen und der Balken steht an der selben Stelle wie am Vorabend und es bewegt sich nichts. Da werde ich dann angerufen und es heisst:"He dein Programm hat sich wieder aufgehängt, habs abgebrochen". Es gibt eben Nutzer die denken das 1Mio Geodatensätze genausoschnell durchgerechnet werden wie 1Mio Excelzahlen aufsummiert...."Da brauche ich doch auch nur Enter drücken".....
Aber genug ausgeweint...vielen Dank für eure Antworten.

Ich habe da jetzt folgendes gefunden und werde versuchen das so umzusetzen:

jbusycomponent - JBusyComponent 1.2.2 : Enhance any swing components with a "busy" state - Google Project Hosting
 
Zuletzt bearbeitet:
jetzt verstehe ich was du mit blinken meinst.. du meinst wohl das wachsen bzw das auffüllen des Ladebalkens oder ?

😳
 
Ich checks noch nicht so richtig... Warum sollte dein Ladebalken stehen bleiben. Du musst deine lange Berechnung in einem eigenen Thread/Job/Worker machen und natürlich deinen Ladebalken immer mal wieder aktualisieren sonst geht da nix 😉 .
 
Lol-okay, anfänglich dachte ich ihr habt mich problemlos verstanden, jedenfalls habe ich die Antworten als sinnvoll betrachtet.

Mein Balken macht Fortschritte wie es sein soll, wenn die Funktion fertig ist kommt er auch bei 100% an.
Weil ich aber nicht weiß, wie lange meine Funktion benötigt, aktualisiere ich den Balken "manuel", Sprich ich weiß dass es immer 10 Funktionsschritte gibt, also wird nach jedem Schritt der Balken um 10% erweitert. Zwischen Schritt 7 und 8 als der Sprung von 70 auf 80% dauert aber extrem lang, je nachdem wie die Geodaten aussehen (mal 20 mal 124 Stunden)... UNd deswegen hätte ich gerne den Balken graphisch halt blinkend dargestellt, aber ich habe jetzt schon andere Graupen im Kopf.

Und zwar ist, der "Start" - Button direkt nach dem Betätigen wieder verfügbar, diesen werde ich versuchen zu ersetzen (mit so einem Busy-GIF) solange wie die Funktion durchgerechnet wird.

Was meint ihr? Ist das Möglich?

vielen Dank
Jens
 
ich glaube die Aufteilung könnte anders sein.
Schritte 1 bis 6 : jeweils zb 2%.
Schritt 7 könnte dann 80 % sein.
Schritte 8 bis 10 die restlichen 8 %.

Ich meine bloß fair aufteilen...
 
Meine genannte Aufteilung war jetzt nur ein Beispiel(das hätte ich dazu schreiben müssen), es kann auch sein, das zwischen Schritt1 undSchritt2 diese Datenmengen auftretten, jenachdem was für gerade genutzt wird.
 
Ich halte einen Ladebalken so wie Du ihn hast, plus eine zweite Komponente die Aktivität vorgaukelt für eine gute Idee. Wie diese Komponente aussieht ist dabei auch zweitrangig. Den Start-Knopf durch ein bewegtes Icon auszutauschen halte ich für nicht so schön. Ich persönlich mag es nicht, wenn Buttons verschwinden. Aber Du könntest auch auf dem Button ein solches Icon darstellen und den Button deaktivieren.

Und: Ich hatte Dich anfänglich genau so verstanden. 🙂

Ebenius
 

Zurück
Oben