# Berechnung abbrechen mit Button



## shark95 (4. Dez 2010)

Hallo!

folgendes Problem: Ich habe ein Programm welches eine sehr rechenintensive Funktion aufruft. Ich möchte jetzt gerne diese Funktion abbrechen können. Die Funktion beinhaltet eine Schleife (ein Schleifendurchlauf dauert ziemlich lange). Ich habe nun ein Flag, welches überprüft ob der Abbrechen Button betätigt wurde. 
Mein Problem ist, dass ich während der Berechnung leider keinen Button mehr anklicken kann und somit mein Flag auch nicht umstellen. Habt ihr eine Lösung dazu? oder eine andere Methode die Berechnung abzubrechen?

lg


----------



## LoR (4. Dez 2010)

Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 11 Threads und nebenläufige Programmierung

-> Evtl. SwingWorker verwenden.


----------



## André Uhres (5. Dez 2010)

Hallo shark95,

versuch's mal so:


```
import java.util.*;
import java.util.List;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class CuncurrencyDemo extends JFrame implements ActionListener {

    private final JTextField dataBox;
    private final JButton startButton, stopButton;
    private MyTask myTask;

    private JTextField makeText() {
        JTextField t = new JTextField(20);
        t.setEditable(false);
        t.setHorizontalAlignment(JTextField.RIGHT);
        getContentPane().add(t);
        return t;
    }

    private JButton makeButton(final String caption) {
        JButton b = new JButton(caption);
        b.setActionCommand(caption);
        b.addActionListener(this);
        getContentPane().add(b);
        return b;
    }

    public CuncurrencyDemo() {
        super("CuncurrencyDemo");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Make text box
        getContentPane().setLayout(new FlowLayout());
        dataBox = makeText();
        //Make buttons
        startButton = makeButton("Start");
        stopButton = makeButton("Stop");
        stopButton.setEnabled(false);
        //Display the window.
        pack();
        setVisible(true);
    }

    private static class MyData {

        private final long data;

        MyData(final long data) {
            this.data = data;
        }
    }

    private class MyTask extends SwingWorker<Void, MyData> {

        @Override
        protected Void doInBackground() {
            long data = 0;
            Random random = new Random();
            while (!isCancelled()) {
                if (random.nextBoolean()) {
                    data++;
                }
                publish(new MyData(data));
            }
            return null;
        }

        @Override
        protected void process(final List<MyData> myDataList) {
            MyData myData = myDataList.get(myDataList.size() - 1);
            dataBox.setText(String.format("%d", myData.data));
        }
    }

    public void actionPerformed(final ActionEvent e) {
        if ("Start".equals(e.getActionCommand())) {
            startButton.setEnabled(false);
            stopButton.setEnabled(true);
            (myTask = new MyTask()).execute();
        } else if ("Stop".equals(e.getActionCommand())) {
            startButton.setEnabled(true);
            stopButton.setEnabled(false);
            myTask.cancel(true);
            myTask = null;
        }

    }

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

            public void run() {
                CuncurrencyDemo cuncurrencyDemo = new CuncurrencyDemo();
            }
        });
    }
}
```
Siehe auch die Swing Tutorials: Trail: Creating a GUI With JFC/Swing: Table of Contents (The Java™ Tutorials)
besonders unter *Concurrency in Swing | Canceling Background Tasks*.

Gruß,
André


----------



## shark95 (5. Dez 2010)

super vielen Dank für die Antworten - funktioniert soweit :toll:

Jetzt hab ich nur noch das Problem, dass er nicht einfach abbrechen soll, sondern dass er mir zumindest das Ergebnis bis dort hin ausgibt.

Bis jetzt habe ich den SwingWorker in die actionPerformed(ActionEvent e) Methode gepackt (und zwar zu dem ActionEvent, welcher die Berechnung auslöst). Ich hab zusätzlich im ganzen Programm eine statische Variable "abbrechen", welche mir signalisiert, ob der Abbrechen Button gedrückt wurde. In der rechenintensiven Methode wird in jedem Schleifendurchlauf geprüft ob die Variable Abbrechen false ist. Im else Bereich habe ich ein break; zum Abbruch der Schleife. Leider funktioniert das nicht, ich kann zwar im Programm abbrechen anklicken, es tut sich aber nichts ???:L


----------



## Gast2 (5. Dez 2010)

Ohne Code kann man schlecht was sagen.


----------



## André Uhres (5. Dez 2010)

shark95 hat gesagt.:


> Jetzt hab ich nur noch das Problem, dass er nicht einfach abbrechen soll, sondern dass er mir zumindest das Ergebnis bis dort hin ausgibt.



Mit 
	
	
	
	





```
cancel+isCancelled
```
 können wir den SwingWorker stoppen und mit 
	
	
	
	





```
publish+process
```
 können wir Zwischenergebnisse ausgeben, so wie es in obigem Beispiel gezeigt wird.

Gruß,
André


----------



## shark95 (5. Dez 2010)

vielen Dank, hat sich erledigt. Nach langem Fehlersuchen und Tutorials lesen bin ich draufgekommen, dass ich vergessen hatte meinen Abbruchbutton zum ActionListener hinzuzufügen.... ;( 

Naja, hauptsache es funktioniert jetzt


----------

