JCheckBox wstrzymujący działanie programu

0

Mam program, który w pętli wykonuje działania i wypisuje w notatniku (JTextArea) ich rezultaty. Chciałbym móc w dowolnej chwili wstrzymać wykonywanie programu, a później je wznowić. Próbuję zastosować w tym celu JCheckBox, w następujący sposób:

    while (chZatrzymajDzialanieProgramu.isSelected())
    {
	  if (!chZatrzymajDzialanieProgramu.isSelected())
	  {
	      break;
  	  }
    }

Po zaznaczeniu wstrzymuje się działanie programu, niestety po odznaczeniu nie rusza ponownie. Co robię źle? W jaki sposób można jeszcze podejść do tematu?

1

if w środku jest zbędny. Stwórz nowy watek który będzie obsługiwał while, a action listener do checkboxa niech zmienia wartość boolean zmienna

run(){
    while (zmienna)
    {
  
    }
}
0

Próbuję na takim prostym przykładzie.

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.DefaultCaret;

public class Test implements ActionListener
{ 
	JFrame ramka;
	JTextArea notatnik;
	JMenuBar menuBar;
	JMenu menuUstawienia;
	JCheckBox chZatrzymajDzialanieProgramu;
	boolean programJestWstrzymany;
	Petla petla;
	
    public static void main(String[] args) throws InterruptedException
    {
        Test test = new Test();
        test.zbudujGUI();   
        test.dzialaj();
    }   
    
    public void zbudujGUI() throws InterruptedException
	{  
    	ramka = new JFrame();
		ramka.setSize(1000,500);
		ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		ramka.setExtendedState(JFrame.MAXIMIZED_BOTH);
		ramka.setLayout(null);
		
		notatnik = new JTextArea();
		JScrollPane przewijalnePole = new JScrollPane(notatnik);
		przewijalnePole.setBounds(420,20,500,790);
		DefaultCaret caret = (DefaultCaret)notatnik.getCaret();
		caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
		ramka.add(przewijalnePole);	
		
		menuBar = new JMenuBar();
		ramka.setJMenuBar(menuBar);

		menuUstawienia = new JMenu("Ustawienia");
		menuBar.add(menuUstawienia);
		
		chZatrzymajDzialanieProgramu = new JCheckBox("Zatrzymaj działanie programu");
		menuUstawienia.add(chZatrzymajDzialanieProgramu);
		chZatrzymajDzialanieProgramu.addActionListener(this);
		
		ramka.setVisible(true);
		return;
	}
		
    public void dzialaj()
    {
    	programJestWstrzymany = false;
    	petla = new Petla(this);
    	for (int i=0; i<10000; i++)
    	{	
    		notatnik.append("\n" + i);
    		try 
    		{
				Thread.sleep(100);
			} 
    		catch (InterruptedException e) 
    		{
				e.printStackTrace();
			}
    		Thread watekPetla = new Thread(petla);
    		watekPetla.run();	
    	}
    	return;	
    }

	@Override
	public void actionPerformed(ActionEvent e) 
	{
		Object source = e.getSource();	
		if (source == chZatrzymajDzialanieProgramu)
		{
			if (chZatrzymajDzialanieProgramu.isSelected())
			{
				programJestWstrzymany = true;
				return;
			}
			else if (!chZatrzymajDzialanieProgramu.isSelected())
			{
				programJestWstrzymany = false;
				return;
			}	
		}
	}
}
public class Petla implements Runnable
{ 
	Test test;
	
	public Petla(Test test)
	{
		this.test = test;
	}
	
	public void run()
	{	
		while (test.programJestWstrzymany)
		{
			
		}
		return;
	}
}

Wstrzymać wykonywanie programu udaje się, ale po odznaczeniu CheckBox'a program nie rusza. Co namieszałem?

0

Jeżeli wątek ma działać w nieskończoność to

While(true){
  If(warunek){
    Akcja 
  }
}
0

Nie w nieskończoność. W przedstawionym przykładzie chciałem żeby wypisywał cyfry od 0 do 9999. Gdy zaznaczę CheckBox ma wstrzymać wypisywanie, np. na 124, a gdy odznaczę CheckBox ma wznowić wypisywanie od 125.

0
run(){
int i=0;
While(i<10000){
  If(booleanStartStop){
    Akcja 
    i++;
  }
}
}
3

Bez osobnego wątku się nie da. Jak sobie zablokujesz wątek Swinga to już nic nie poklikasz w UI bo wątek który miałby obsłużyc twoje kliknięcie wisi na tej twojej pętli ;]

2

Jak chcesz to zrobić porzadnie, to sugeruję użyć Condition, żeby nie palić CPU i nie robić dziwnych sleepów:

abstract class PausableJob implements Runnable {

    private final Lock pauseLock = new ReentrantLock();
    private final Condition resumedCondition = pauseLock.newCondition();
    private boolean paused;

    void pause() {
        pauseLock.lock();
        try {
            paused = true;
        } finally {
            pauseLock.unlock();
        }
    }

    void resume() {
        pauseLock.lock();
        try {
            paused = false;
            resumedCondition.signalAll();
        } finally {
            pauseLock.unlock();
        }
    }

    protected void waitOnPause() {
        pauseLock.lock();
        try {
            while (paused) {
                try {
                    resumedCondition.await();
                } catch (InterruptedException ignore) {}
            }
        } finally {
            pauseLock.unlock();
        }
    }
}

class SimplePrintPausableJob extends PausableJob {

    @Override
    public void run() {
        for (int i = 0; i < 100000; i++) {
            waitOnPause();
            System.out.println(i);
            try {
                Thread.sleep(10);
            } catch (InterruptedException ignore) {}
        }
    }
}

Potem z poziomu action handlera możesz wywoływać pause() i resume()

0

Dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1