Progress Bar

TDO88

Bekanntes Mitglied
Hallo Zusammen,

wie der Titel ja schon sagt, geht es darum eine Progressbar zum laufen zu bekommen.
Ich habe schon einiges darüber gelesen, aber irgendwie bekomme ich es nicht zum laufen.
Ich habe auf meinem Frontpanel eine Progressbar (jProgressBar1) erstellt.
Ich durchlaufe eine while Schleife, in der Zufallspositionen für einen motorisierten Tisch erzeugt und vom Tisch angefahren werden. Das ganze soll eine bestimmte Zeit laufen. Den Fortschritt der Zeit würde ich gerne über eine Progressbar darstellen.
Die Schleife sieht folgendermaßen aus:
Java:
while(System.currentTimeMillis() < startTime + (Laufzeit * 1000))
{
     Xpos = r.nextInt((Math.abs(XCalPos.intValue()) + Math.abs(XRMPos.intValue()))) - Math.abs(XCalPos.intValue());
     Ypos = r.nextInt((Math.abs(YCalPos.intValue()) + Math.abs(YRMPos.intValue()))) - Math.abs(YCalPos.intValue());
     if((returnfunction = TANGOINST.LSX_MoveAbs(ILSID, Xpos, Ypos, 0, 0, true)) != 0)
             throw new Exception("MoveAbs failed");
}

Jetzt muss ja das füttern der Progressbar mit Werten in einen Extra Thread gepackt werden, damit die Progressbar auch wirklich aktualisiert wird.
Das habe ich so versucht:

Java:
try{
     new Thread(new Runnable(){
        public void run() {

           while(System.currentTimeMillis() < startTime + (Laufzeit * 1000))
           {
               Xpos = r.nextInt((Math.abs(XCalPos.intValue()) + Math.abs(XRMPos.intValue()))) - Math.abs(XCalPos.intValue());
               Ypos = r.nextInt((Math.abs(YCalPos.intValue()) + Math.abs(YRMPos.intValue()))) - Math.abs(YCalPos.intValue());
                if((returnfunction = TANGOINST.LSX_MoveAbs(ILSID, Xpos, Ypos, 0, 0, true)) != 0)
                     throw new Exception("MoveAbs failed");
                jProgressBar1.setValue((int) ((100 * (startTime + (Laufzeit *1000) ))/System.currentTimeMillis()));
           }
       }
    }).start();
}catch(Exception e){
     JOptionPane.showMessageDialog(this, e.getMessage(), "Send String failed", 0);
}

Funktioniert aber so leider auch nicht, weil ich z.B. nicht weiß, wie ich mit den Variablen umgehen soll.
Die Variablen XPos und YPos z.B. werden im Code vor der Schleife mit Werten gefüttert. Sollen dann aber hier in dem Thread als final deklariert werden, aber das kann ja irgendwie nicht gehen.
Ich komme so gerade echt nicht weiter.
Wäre super, wenn jemand eine Idee dazu hat
 

Flown

Administrator
Mitarbeiter
Dann nimmst du eben private Variablen in deinem Runnable und zusätzlich konvertierst du dein Xpos und Ypos - die in Java eigentlich xPos und yPos heißen sollten - zu Felder mit getter/setter:
Java:
public void run() {
  int x = getX();
  int y = getY();
  while(...) {
    x = ...;
    y = ...;
  }
}
 

TDO88

Bekanntes Mitglied
Dann nimmst du eben private Variablen in deinem Runnable und zusätzlich konvertierst du dein Xpos und Ypos zu Felder mit getter/setter:
Java:
public void run() {
  int x = getX();
  int y = getY();
  while(...) {
    x = ...;
    y = ...;
  }
}

Die Variablen Xpos und YPos kann ich so deklarieren, aber die Variablen XCalPos, YCalPos, XRMPos, YRMPos werden vor der Schleife von dem motorisierten Tisch ermittelt. Wie komme ich dann an diese Werte dran?

- die in Java eigentlich xPos und yPos heißen sollten -
Warum?

Würde das dann eigentlich generell funktionieren, wenn ich die Schleife mit den Move Kommandos zum Tisch, deren Berechnung und die ProgressBar zusammen in einen neuen Thread packe, oder muss ich das irgendwie umschreiben, dass nur die ProgressBar in einem neuen Thread läuft?
 

Flown

Administrator
Mitarbeiter
xPos und yPos sollten - per Javakonvention - in lowerCamelCase geschrieben werden.

Die ProgressBar sollte dir nur den Status deiner Berechnungen anzeigen und nicht deine Logik ausführen. Deshalb wurden SwingWorker geschaffen. Deine Berechnungen sollten laufen und ständig deine ProgressBar updaten, nicht umgekehrt.
 

TDO88

Bekanntes Mitglied
Für get() und set() Funktionen brauche ja eine Klasse Progressbar oder?
Ich habe ein Netbeans Projekt, auf dem ich mir eine Progressbar gezogen habe. Dadurch habe ich ja keine Klasse Progressbar! Ich könnte mir eine Schreiben, aber wie bekomme ich dann einen Bezug von meinem Frontpanelobjekt auf die Klasse?
Noch was: Wie könnte ich denn noch die Möglichkeit einbauen, das ganze abzubrechen? Also sowohl die Schleife mit den Move Befehlen, als auch die ProgressBar, wenn sie denn mal läuft?
 
Zuletzt bearbeitet:

VfL_Freak

Top Contributor
Moin,
Für get() und set() Funktionen brauche ja eine Klasse Progressbar oder?
warum sollte das so sein?
Wie flown schon schrieb ist es reine Optik !!

Ich habe ein Netbeans Projekt, auf dem ich mir eine Progressbar gezogen habe. Dadurch habe ich ja keine Klasse Progressbar! Ich könnte mir eine Schreiben, aber wie bekomme ich dann einen Bezug von meinem Frontpanelobjekt auf die Klasse?
Noch was: Wie könnte ich denn noch die Möglichkeit einbauen, das ganze abzubrechen? Also sowohl die Schleife mit den Move Befehlen, als auch die ProgressBar, wenn sie denn mal läuft?
Vielleicht hilft Dir dies zum verstehen weiter ?
http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html

Gruß Klaus
 

Flown

Administrator
Mitarbeiter
Du hast anscheinend meinen Link zu SwingWorker nicht angesehen oder? Da steht sogar was von einem Abbruch des Threads! HIER

Die Klasse Progressbar existiert schon in der Swing API und du musst sie nur noch verwenden, aber deine Aktionsloop, wo du deine Berechnungen steuerst musst du auslagern in einen Thread (SwingWorker) und der UI dann sagen, wenn sich was geändert hat.
 

TDO88

Bekanntes Mitglied
Danke für eure Antworten.
Ich fand diese Seite hier sehr hilfreich: http://www.javacreed.com/swing-worker-example/
Ich habe mir damit jetzt eine Klasse erstellt die so aussieht:
Java:
 public static class runDauerlaufWorker extends SwingWorker<Integer, String> {
        private static void failIfInterrupted() throws InterruptedException {
            if (Thread.currentThread().isInterrupted()) {
              throw new InterruptedException("Interrupted while Dauerlauf");
            }
        }
       
        private final Double xCalPos, yCalPos, xRMPos, yRMPos;
        private final int Laufzeit;
       
        private runDauerlaufWorker(final Double xCalPos, final Double yCalPos, final Double xRMPos, final Double yRMPos, int Laufzeit)
        {
            this.xCalPos = xCalPos;
            this.yCalPos = yCalPos;
            this.xRMPos = xRMPos;
            this.yRMPos = yRMPos;
            this.Laufzeit = Laufzeit;
        }
       
        protected Integer doInBackground() throws Exception {
            int returnfunction;
            int xPos, yPos;
            Random r = new Random();
            long startTime;
           
            startTime = System.currentTimeMillis();
            while(System.currentTimeMillis() < startTime + (Laufzeit * 1000))
            {
                runDauerlaufWorker.failIfInterrupted();
                xPos = r.nextInt((Math.abs(xCalPos.intValue()) + Math.abs(xRMPos.intValue()))) - Math.abs(xCalPos.intValue());
                yPos = r.nextInt((Math.abs(yCalPos.intValue()) + Math.abs(yRMPos.intValue()))) - Math.abs(yCalPos.intValue());
                if((returnfunction = TANGOINST.LSX_MoveAbs(ILSID, xPos, yPos, 0, 0, true)) != 0)
                    throw new Exception("MoveAbs failed");
                setProgress((int) ((100 * (startTime + (Laufzeit *1000) ))/System.currentTimeMillis()));
            }
            return 0;
        }
    }

Jetzt versuche ich ein Objekt der Klasse so zu erzeugen:

Code:
DauerlaufWorker = new runDauerlaufWorker(xCalPos, yCalPos, xRMPos, yRMPos, Laufzeit);

Aber bekomme ständig die Meldung:
cannot find symbol
symbol: variable DauerlaufWorker
location: class Dauerlauf
----

Jemand eine Idee, wie ein Objekt meiner Klasse erstellen kann?!
 

TDO88

Bekanntes Mitglied
Total blöd.... Antwort gerade selbst gefunden
Java:
runDauerlaufWorker DauerlaufWorker = new runDauerlaufWorker(xCalPos, yCalPos, xRMPos, yRMPos, Laufzeit);
 

VfL_Freak

Top Contributor
Moin,

klar, was soll denn "DauerlaufWorker" sein ??
Falls diese Variable nicht anderswo deklariert ist, wird der von Dir gepostete Aufruf logischerweise fehlschlagen, weil der Compiler diese Variable nicht kennt !

Gruß Klaus

EDIT:
Ah ok, warst ja doch schneller als ich :-D
 

TDO88

Bekanntes Mitglied
Hmm... jetzt versuche ich im EDT Thread danach einen PropertyChangeListener einzufügen
Java:
DauerlaufWorker.addPropertyChangeListener(new PropertyChangeListener(){
     @Override
     public void PropertyChange(final PropertyChangeEvent event){
        Switch(event.getPropertyName())
        {
             case "progress":
                      jProgressBar1.setValue((Integer) event.getNewValue);
                      break;
              default:
                      break;
         }
      }
});
DauerlaufWorker.execute();

Bekomme aber schon in der ersten Zeile die Fehlermeldung:
<anonymous Dauerlauf.Dauerlauf$14> is not abstract and does not override abstract method propertyChange(PropertyChangeEvent) in PropertyChangeListener

Da hab ich gerade gar keine Ahnung, was ich damit anfangen soll
 

TDO88

Bekanntes Mitglied
Ich werde daraus leider nicht schlau!
Habe jetzt ein @Override vor meine doInBackground() Methode gepackt, aber es bringt leider nichts...
Wäre wirklich dankbar, wenn mir jemand erklären könnte, woher der Fehler kommt
 

TDO88

Bekanntes Mitglied
Du musst propertyChange überschreiben, deine Methode heißt aber PropertyChange.
Außerdem solltest du https://de.wikipedia.org/wiki/Annotation_(Java) lesen.

Es kann manchmal so leicht sein... Danke!

Würdest du eine IDE wie z.B. Eclipse benutzen, hättest du solche Probleme nicht oder nur ganz selten ;-)

Kann ich mir leider nicht aussuchen ;)

Es funktioniert jedenfalls nun so:
Java Klasse mit doInBackground() Methode:
Java:
public static class runDauerlaufWorker extends SwingWorker<Integer, String> {
        private static void failIfInterrupted() throws InterruptedException {
            if (Thread.currentThread().isInterrupted()) {
              throw new InterruptedException("Interrupted while Dauerlauf");
            }
        }
     
        private final Double xCalPos, yCalPos, xRMPos, yRMPos;
        private final int Laufzeit;
     
        private runDauerlaufWorker(final Double xCalPos, final Double yCalPos, final Double xRMPos, final Double yRMPos, int Laufzeit)
        {
            this.xCalPos = xCalPos;
            this.yCalPos = yCalPos;
            this.xRMPos = xRMPos;
            this.yRMPos = yRMPos;
            this.Laufzeit = Laufzeit;
        }
     
        @Override
        protected Integer doInBackground() throws Exception {
            int returnfunction;
            int xPos, yPos;
            Random r = new Random();
            long startTime;
         
            startTime = System.currentTimeMillis();
            while(System.currentTimeMillis() < startTime + (Laufzeit * 1000))
            {
                runDauerlaufWorker.failIfInterrupted();
                xPos = r.nextInt((Math.abs(xCalPos.intValue()) + Math.abs(xRMPos.intValue()))) - Math.abs(xCalPos.intValue());
                yPos = r.nextInt((Math.abs(yCalPos.intValue()) + Math.abs(yRMPos.intValue()))) - Math.abs(yCalPos.intValue());
                if((returnfunction = TANGOINST.LSX_MoveAbs(ILSID, xPos, yPos, 0, 0, true)) != 0)
                    throw new Exception("MoveAbs failed");
                setProgress(100 - ((int) ((100 * (startTime + (Laufzeit * 1000) - System.currentTimeMillis())) / (Laufzeit * 1000))));
            }
            setProgress(100);
            return 0;
        }
    }

und Aufruf:
Java:
runDauerlaufWorker DauerlaufWorker = new runDauerlaufWorker(xCalPos, yCalPos, xRMPos, yRMPos, Laufzeit);
     DauerlaufWorker.addPropertyChangeListener(new PropertyChangeListener(){
        @Override
        public void propertyChange(final PropertyChangeEvent event){
        if(event.getPropertyName().equals("progress"))
        {
             jProgressBar1.setValue((Integer) event.getNewValue());
        }
        else if(event.getPropertyName().equals("state"))
        {
              switch((SwingWorker.StateValue) event.getNewValue()){
              case DONE:
                   jButtonRandom.setText("Zufallslauf");
                   jProgressBar1.setValue(100);
                   break;
               case STARTED:
               case PENDING:
               jButtonRandom.setText("Abbrechen");
               break;
               }
         }
     }
});
DauerlaufWorker.execute();

Mich würde jetzt nur noch eines Interessieren.
Den ganzen Prozess starte ich, wenn der Benutzer auf den Button "Zufallslauf" klickt.
Dem Quelltext kann entnommen werden, dass sich der Text auf dem Button während des Laufs auf "Abbrechen" ändert. Ich würde den ganzen Prozess dann gerne Abbrechen, wenn jemand während des Dauerlaufs auf den Button klickt.
Wie fange ich das dann aber in meiner Methode ab?
Muss ich das über ein if(Button.getText() == "Abbrechen") machen oder gibt es elegantere Möglichkeiten?

Vielen, vielen Dank bisher für eure Hilfe
 

VfL_Freak

Top Contributor
Moin,

Den ganzen Prozess starte ich, wenn der Benutzer auf den Button "Zufallslauf" klickt.
Dem Quelltext kann entnommen werden, dass sich der Text auf dem Button während des Laufs auf "Abbrechen" ändert. Ich würde den ganzen Prozess dann gerne Abbrechen, wenn jemand während des Dauerlaufs auf den Button klickt.
Wie fange ich das dann aber in meiner Methode ab?

Muss ich das über ein if(Button.getText() == "Abbrechen") machen oder gibt es elegantere Möglichkeiten?
Theoretisch ja, es gibt aber beim JButton auch die Methode "setActionCommand", das sich anschließend anfragen läßt.
Du könntest aber vlt. auch einen JToggleButton nehmen, der je nach Zustand dann die enstprechende Aktion ausführt!

mMn ist es aber von Aufbau her zumindest fragwürdig, den gleichen Button für unterschiedlichste Aktionen zu verwenden.
Du musst dann ja auch sicherstellen, dass er sich in allen Programmzuständen im richtigen (gewünschten) Zustand befindet!

Was spricht gegen zwei Button ??
Gruß Klaus
 

TDO88

Bekanntes Mitglied
Hmm...Prinzipiell eig. nichts, aber wie kann ich von der Methode eines anderen Buttons auf den Thread zugreifen und diesen Beenden?
 

Flown

Administrator
Mitarbeiter
Hier hast du ein kleines Beispiel wie man sowas beenden könnte:
Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ThreadTest {

   public static void main(String...args) {
     SwingUtilities.invokeLater(new Runnable() {

       @Override
       public void run() {
         new ThreadTest();
       }
     });
   }

   private MyCurrentWork work;

   public ThreadTest() {
     JFrame frame = new JFrame();
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.setLocationByPlatform(true);

     JPanel mainPanel = new JPanel();

     JButton startButton = new JButton("Start");
     JButton stopButton = new JButton("Stop");
     stopButton.setEnabled(false);

     startButton.addActionListener(new ActionListener() {

       @Override
       public void actionPerformed(ActionEvent e) {
         new Thread(work = new MyCurrentWork()).start();
         stopButton.setEnabled(true);
         startButton.setEnabled(false);
       }
     });

     stopButton.addActionListener(new ActionListener() {

       @Override
       public void actionPerformed(ActionEvent e) {
         work.stop();
         work = null;
         stopButton.setEnabled(false);
         startButton.setEnabled(true);
       }
     });

     mainPanel.add(startButton);
     mainPanel.add(stopButton);

     frame.add(mainPanel);
     frame.pack();
     frame.setVisible(true);

   }

   class MyCurrentWork implements Runnable {
     private boolean stop = false;

     @Override
     public void run() {
       while (!stop) {
         System.out.println("running");
         try {
           Thread.sleep(200);
         } catch (InterruptedException e) {
           e.printStackTrace();
         }
       }
       System.out.println("stopped");
     }

     public void stop() {
       stop = true;
     }
   }
}
 

Ähnliche Java Themen

Neue Themen


Oben