Swing Timer in SwingWorker stoppen

ralfb1105

Bekanntes Mitglied
Hallo zusammen,

ich bin auf der Suche nach einer Lösung für mein Problem mit dem Swing Timer aufgerufen in einer Klasse die um SwingWorker erweitert ist um eine Nebenläufigekit im GUI zu erzielen.

Hier kurz die Problembeschreibung.
Ich möchte ein GUI programmieren welches einen DB Test startet dr so lange ausgeführt wird bis eine vorher gesetzte Laufzeit abgelaufen ist.
Ich habe damit angefangen zu versuchen einen Counter zu programmieren der nebenläufig ist, soll heißen die GUI Ausführung nicht unterbricht. Im Prinzip habe ich das hin bekommen, mit Hilfe eines Beispiels welches mir zu einem ähnlichen Thema in diesem Forum schon mal vorgestellt wurde. Jetzt habe ich aber das Problem das der Counter läuft, ich kann auch andere Aktionen im GUI ausführen, doch leider endet der Counter nicht nach der Zeit sondert läuft endlos weiter.

Hier meine Code Idee zu dem Thema:

Java:
class ProcessWorkerCounter extends SwingWorker<Void, String>
    {
        private JLabel jLCounter;
        private long seconds;
       
        public ProcessWorkerCounter(JLabel counter, long seconds)
        {
            this.jLCounter = counter;
            this.seconds = seconds;
        }


        @Override
        protected Void doInBackground() throws Exception
        {
            //hier läuft alles in einem eigenen Thread (nebenläufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert.
            Timer timer;
                timer = new Timer(1000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                            publish(String.valueOf(seconds));
                            seconds--;
                            if (seconds == 0) {
                                //cancel(true);
                                //timer.removeActionListener(this);
                                //timer.stop();
                        }
                       
                    }
                });
                timer.start();
            return null;
        }
       
        @Override
        protected void process(List<String> chunks)
        {
            //hier läuft alles auf dem EDT (Event Dispatch Thread). Darum können (und sollten) wir hier die GUI Komponenten manipulieren.
            for(int i = 0; i < chunks.size(); i++)
            {
                jLCounter.setText(chunks.get(i));
            }
        }
    }

Der Timer wird über einen Button gestartet:

Java:
private void jBStartCounterActionPerformed(ActionEvent evt) {
        ProcessWorkerCounter pc = new ProcessWorkerCounter(jLCounter, 10);
        pc.execute();
    }

Wie man sieht war meine Idee über "timer.stop()" den Timer zu beenden, aber ich kann timer.stop() an der Stelle im Code nicht aufrufen:
"the local variable timer may have not been initialized".
Auch mit "timer.removeActionListener(this);" habe ich keinen Erfolg. Der Abbruch über die SwingWorker "cancel()" Methode scheitert auch, denn wenn ich eine Schleife darum herum baue mit (while (!isCancelled()) soielt das ganze Programm verrückt was vermutlich daran liegt das ich den Timer immer wieder aufrufe ... ??

Irgendwie sehe ich meinen fehler nicht 🙁 und ich hoffe Ihr könnt mich wieder auf die Spur bringen 🙂

Danke schon mal .. ich hoffe ich habe mein Problem verständlich ausgedrückt.

Gruß

Ralf
 
Hallo,

vielen dank für Deinen Vorschlag, aber wenn ich die Zeile
Java:
Timer timer ;
in
Code:
Timer timer = null;
ändere, bekomme ich in Eclipse folgende Fehler bei der Zeile "timer.stop();"
Code:
- Local variable timer defined in an enclosing scope must be final or effective final
- Null pointer access: The variable timer can only be null at this location
Hast Du noch eine Idee, mir sagt das ehrlich gesagt nicht was ich hier genau falsch mache .. ??

Danke schon mal für Deine Hilfe!

Gruß

Ralf
 
Hallo,

Bingo 🙂 das war es! Wenn ich die Variable "timer" in der Klasse defuniere funktioniert es.
Java:
class ProcessWorkerCounter extends SwingWorker<Void, String>
    {
        private JLabel jLCounter;
        private long seconds;
        Timer timer = null;
       
        public ProcessWorkerCounter(JLabel counter, long seconds)
        {
            this.jLCounter = counter;
            this.seconds = seconds;
        }


        @Override
        protected Void doInBackground() throws Exception
        {
            //hier läuft alles in einem eigenen Thread (nebenläufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert.
            timer = new Timer(1000, new ActionListener() {
            @Override
                public void actionPerformed(ActionEvent e) {
                    publish(String.valueOf(seconds));
                    seconds--;
                    if (seconds == 0) {
                        timer.stop();
                        publish("Timer finished!");
                    }
                 }
            });
            timer.start();
            return null;
        }
       
        @Override
        protected void process(List<String> chunks)
        {
            //hier läuft alles auf dem EDT (Event Dispatch Thread). Darum können (und sollten) wir hier die GUI Komponenten manipulieren.
            for(int i = 0; i < chunks.size(); i++)
            {
                jLCounter.setText(chunks.get(i));
                //jTAOutput.append(System.getProperty("line.separator"));
            }
        }
    }

Da hätte ich auch selbst daruf kommen könne/müssen ... anyway, da habe ich mal wieder etwas dazu gelernt, und darauf kommt es ja beim lernen drauf an.

Ich danke Dir vielmals für Deine Hilfe und wünsche noch einen schönen Sonntag!!

LG

Ralf
 

Neue Themen


Zurück
Oben