• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed GUI Wielowątkowość [Java]

42 Warsaw Coding Academy
0 głosów
1,960 wizyt
pytanie zadane 24 listopada 2015 w Java przez Mikrokontroler xD Stary wyjadacz (13,500 p.)
zamknięte 27 listopada 2015 przez Mikrokontroler xD
labelAlfa.setText(i+" ");
Thread.sleep(delay); //1sekunda 

Po naciśnięciu na przycisk chce żeby w miejsce labelka nastąpiło odliczanie co sekunde jednak jak wrzucam to w wątek główny to rzecz jasna cała aplikacja zostaje "uspana" i dstaje na ekranie ostatnią liczbę.
Z kolei jak wrzucam to do metody run to co prawda funkcja się wykonuje ale zmiana tekstu w labelku nie zachodzi.
To wygląda mniejwięcej tak
 

public class KlasaTestowa extends JFrame implements Runnable{

	@Override
	public void run() {
		System.out.println("dziala");
		labelAlfa.setText("a"); // nie dziala
	}
	
	public void buttonStart(){
		Runnable zadanie = new KlasaTestowa();
		Thread watek = new Thread(zadanie);
		watek.start();
	}

}

Ma ktoś pomysły?

komentarz zamknięcia: Problem rozwiązany

1 odpowiedź

+3 głosów
odpowiedź 24 listopada 2015 przez Javowiec Pasjonat (21,560 p.)
wybrane 25 listopada 2015 przez Mikrokontroler xD
 
Najlepsza

Cześć, zadałeś bardzo dobre pytanie, na które już Ci odpowiadam smiley

Po 1: Większość komponentów Swing nie jest bezpieczna wątkowo i nie można robić czegoś takiego jak:

extends JFrame implements Runnable

Po 2: Używając wątków w połączeniu z biblioteką Swing, trzeba dostosować się do dwóch prostych zasad:

  1. Jeżeli jakieś działanie jest czasochłonne, należy je wykonać w osobnym wątku roboczym - nigdy w wątku dystrybucji zdarzeń.
  2. Nie należy operować na komponentach Swing w żadnym innym wątku niż wątek dystrybucji zdarzeń.

Teraz przeanalizujmy to na przykładzie, który napisałem na szybko:

import java.awt.EventQueue;

public class Main {
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				new KlasaTestowa();
			}
		});
	}
}

EventQueue to wątek dystrybucji zdarzeń, o którym wspomniałem wyżej. W nim tworzymy i operujemy elementami Swinga. Powyżej tworzę po prostu główne okno programu (JFrame) - KlasaTestowa.

import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;

public class KlasaTestowa extends JFrame {
	public static final int MAX = 10;
	
	private JLabel labelAlfa;
	private JButton buttonAlfa;
	
	public KlasaTestowa() {
		labelAlfa = new JLabel("Test");
		buttonAlfa = new JButton("Wielowątkowość");
		
		setLayout(new GridLayout(2, 1));
		add(labelAlfa);
		add(buttonAlfa);

		buttonAlfa.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				new Thread(new Odliczanie(MAX, labelAlfa)).start();
			}
		});

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		setVisible(true);
	}
}

Powyżej definiuję główne okno programu. Zwróc uwagę na dodany ActionListener do przycisku buttonAlfa. Tworzymy tutaj nowy wątek (zasada 1), który będzie odliczał do 0 i aktualizował wartość labelAlfa. Oczywiście od razu go uruchamiamy metodą start(). Odliczanie jest czasochłonne, bo trwa przez dany okres czasu smiley

import java.awt.EventQueue;
import javax.swing.JLabel;

public class Odliczanie implements Runnable {
	private static final int DELAY = 1000;
	
	private int max;
	private JLabel labelAlfa;

	public Odliczanie(int max, JLabel labelAlfa) {
		this.max = max;
		this.labelAlfa = labelAlfa;
	}

	@Override
	public void run() {
		try {
			while(max > 0) {
				EventQueue.invokeLater(new Runnable() {
						@Override
						public void run() {
							labelAlfa.setText(String.valueOf(max));
						}
				});

				max = max - 1;
				Thread.sleep(DELAY);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Naszym celem jest zmienić napis w labelAlfa (przekazany w konstruktorze wątku - robimy to przez referencję). Aby go osiągnąć, w metodzie run() klasy Odliczanie wykonujemy ową operację wewnątrz wątku dystrybucji zdarzeń EventQueue (zasada 2).

komentarz 25 listopada 2015 przez Mikrokontroler xD Stary wyjadacz (13,500 p.)
Dokładnie o to mi chodziło DZIĘKI sam bym nigdy na to nie wpadł :)
wielkie dzięki jeszcze raz :D

Podobne pytania

0 głosów
1 odpowiedź 492 wizyt
+2 głosów
2 odpowiedzi 902 wizyt
0 głosów
0 odpowiedzi 137 wizyt
pytanie zadane 28 kwietnia 2024 w Algorytmy przez overcq Pasjonat (22,540 p.)

93,385 zapytań

142,383 odpowiedzi

322,540 komentarzy

62,745 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...