Progress Bar

TDO88

Grünschnabel
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
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

warum deklarierst du deine Xpos und Ypos nicht innerhalb des Threads neu? Brauchst du die Werte die im Thread generiert werden später auch ausserhalb?
Falls du die Werte später brauchst kannst du anstatt mit int / Integer mit AtomicInteger arbeiten, das sind Objekte die du verändern kannst, obwohl diese final sind. Oder du deklarierst die beiden Variablen als Attribute deiner Klasse.

Grüsse,
BK
 

TDO88

Grünschnabel
Hi,

warum deklarierst du deine Xpos und Ypos nicht innerhalb des Threads neu? Brauchst du die Werte die im Thread generiert werden später auch ausserhalb?
BK

Hmm.. also die beiden Variablen brauche ich eig. nur in dem Thread. Aber die Variablen XCalPos, YCalPos, XRMPos und YRMPos werden vor dem Thread benutzt und mit Werten des motorisierten Tisches gefüllt.
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

wann werden diese verwendet? Wie sieht der genaue Programmablauf aus? Werden diese nachdem der Thread gelaufen ist weiter benötigt?

Grüsse,
BK
 

TDO88

Grünschnabel
Hab es jetzt hinbekommen!
Der Dauerlauf wird dabei in einem neuen Thread gestartet und übergibt seinen Status:
Aufruf des Dauerlaufs:
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;
        }
    }

Starten des Threads aus meiner Methode
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();
 

TDO88

Grünschnabel
Ich hab doch noch was... Weiß jemand eine Möglichkeit den Worker Thread abzubrechen?
Ich möchte den Thread abbrechen, wenn der Benutzer das möchte. Wie dem Code schon zu entnehmen ist, verändere ich den ButtonText, während des parallen Thread. Wie kann ich dann aber abfangen, dass der zunächst gestartet wird und NUR während des Threads abgebrochen werden kann?
Die zweite Möglichkeit wäre, das ganze über einen zweiten Button zu tun. Generell kann der Thread ja mit: DauerlaufWorker.cancel(true) abgebrochen werden. Aber wie komme ich aus einer Methode eines zweiten Buttons an den Thread?
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

ich bevorzuge zum Abbrechen von meinen Threads die Thread.interrupt(). Ein Beispiel mit Erklärung, wie man das machen kann findest du zum Beispiel hier und hier.

Zu deiner Frage: Du kannst dir den Thread als Klassenattribut merken. Wenn der Button gedrück wird, kannst du das Attribut prüfen:
- Falls es null oder nicht alive() ist, einen neuen Thread erstellen und starten.
- Andernfalls wie oben beschrieben stoppen und auf null setzen.

Grüsse,
BK