usypianie wątku

0

Witam
oto kod

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class cos extends JFrame implements ActionListener{
	private static JTextField x1;
	private static JButton start;
	
	public cos() {
	    setBounds(50,50,120, 150);
            setLayout(null);
	    x1 = new JTextField();
	    x1.setBounds(10, 20, 85, 30);
	    start = new JButton("start");
	    start.setBounds(10, 65, 85, 30);
	    add(x1);
	    add(start);
	    start.addActionListener(this);
	    setVisible(true);      
	    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 	
	}
	
	public static void jeden(){
		x1.setText("jeden");
	}
	
	public static void dwa(){
		x1.setText("dwa");
	}
	
	public static void trzy(){
		x1.setText("trzy");
	}
	
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
		
		UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); 
		cos program = new cos ();
	}
	
	public void actionPerformed(ActionEvent e) {
		if (e.getSource()==start)
	    {
			jeden();
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			dwa();
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			trzy();	  
	    }		
	}	
} 

niestety wyświetla się po czasie tylko "trzy"
dlaczego?
i jak to poprawnie zrobić aby wyświetlało się po kolei w odstępach czasu?
poooomocy
czekam na wszelkie sugestie

0

Moze sprobuj wymusic odswiezanie kontrolki (revalidate/update) po kazdej zmianie zawartosci ?

0

gdzie tu masz usypianie wątku? masz jeden wątek, więc usypiasz cały proces, więc także i wyświetlanie/aktualizowanie kontrolek, a to powoduje, że jak po 4s sterowanie wraca do kodu obsługującego gui, to text == "trzy".
zrób to w nowym, osobnym wątku albo na timerze, to nie będziesz zawieszać całej aplikacji.

0

Dokładnie tak jak mówi ŁF, actionPerformed() wykonuje się w EDT, jedynym wątku, w którym aktualizuje się Swing. Poczytaj o EDT (Event Dispatch Thread) i klasie SwingWorker i funkcjach SwingUtilities.invokeLater(), SwingUtilities.invokeAndWait().

0

przerobione

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;


class Czas extends Thread{
    JTextField pole;
    Czas (JTextField x1){
    	pole=x1;
    }
    public void run(){
       int time=0;
       while (time<3){
           try {
        	   this.sleep(1000);
           } catch (InterruptedException e) {
        	   e.printStackTrace();
           }
           if(time == 0){
        	   cos.jeden(); 
           }
           else if(time == 1){
        	   cos.dwa(); 
           }
           else if(time == 2){
        	   cos.trzy(); 
           }
           time++;
       }
    }
}

public class cos extends JFrame implements ActionListener{
	private static JTextField x1;
	private static JButton start;
	
	public cos() {
		setBounds(50,50,120, 150);
		setLayout(null);
		x1 = new JTextField();
	    x1.setBounds(10, 20, 85, 30);
	    start = new JButton("start");
	    start.setBounds(10, 65, 85, 30);
	    add(x1);
	    add(start);
	    start.addActionListener(this);
	    setVisible(true);      
	    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 	
	}
	
	public static void jeden(){
		x1.setText("jeden");
	}
	
	public static void dwa(){
		x1.setText("dwa");
	}
	
	public static void trzy(){
		x1.setText("trzy");
	}
	
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
		
		UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); 
		cos program = new cos ();
	}
	
	public void actionPerformed(ActionEvent e) {
		if (e.getSource()==start)
	    {
			Czas nowyWatek = new Czas(x1);
			nowyWatek.start();
	    }		
	}	
}

nie wiem czy optymalnie ale spełnia założenia
wielkie dzięki

0

Oczywiście, że źle, bo nie wykonujesz tego w EDT. Dalej nie korzystasz w invokeLater() czy invokeAndWait(), które kolejkują task do EDT.

http://download.oracle.com/javase/tutorial/uiswing/concurrency/index.html

Google nie działa? Napisałem ci o czym masz poczytać.

0

czy dobrze, czy źle, to można polemizować. według mnie można zrobić prościej, ale tak też będzie dobrze, z wyjątkiem jednej rzeczy - jeśli swing nie jest thread safe, to co jakiś czas program będzie się wywalać (dwa wątki jednocześnie będą żądać dostępu do tej samej kontrolki).

0

Swing nie jest thread-safe i właśnie dlatego stworzono SwingWorkery, invokeLater i invokeAndWait. Żadna operacja na Swingu nie jest synchronizowana.

W czasach gdy Swing był tworzony, nie było pomysłu na wielowątkowe GUI: http://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html

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