Witam,

Co robi program?
Zmienia liczby w TextBox. Pochodza one z watku w niezaleznej klasie. Cel programu? Nauczyc powiadamiac GUI w Jambu o zmianach ktore pochodza od niezaleznego modelu (np. watek odbierajacy dane przez siec).

Idea jest następująca:

  1. Klasa GUI i model logiki są oddzielnie.
  2. Klasy te komunikują się ze sobą.

Problem: jak powiadomić wątek GUI o zmianie (sygnały - sloty, obserwator)?

Klasa GUI (wszystko z nią ok):

package JambiTest;

import com.trolltech.qt.gui.*;

public class MainWindow extends QMainWindow {
	/*
	 * Objects / controls.
	 */
	Ui_MainWindow mainw = new Ui_MainWindow();
	Client client = new Client();
	
	/*
	 * Methods.
	 */
	public MainWindow() {
		mainw.setupUi(this);
		setWindowIcon(new QIcon("classpath:com/trolltech/images/qt-logo.png"));
		set_signals_slots();
	}
	protected void set_signals_slots()
	{
		mainw.pushButton.clicked.connect(this, "start_counter()");
		client.send_number.connect(this, "recv_number(Integer)");
		client.send_info.connect(this, "display_info(String, String)");
	}
	
	/*
	 * Signals.
	 */
	
	/*
	 * Slots.
	 */
	protected void start_counter() {
		client.start_counter();
	}
	protected void recv_number(Integer i) {
		mainw.lineEdit.setText(i.toString());
	}
	protected void display_info(String title, String msg) {
		QMessageBox.information(this, title, msg);
	}
}

Model to kod widoczny poniżej. Wyjątek spowodowany tym, że procedura update wywołuje się w tym samym wątku, co tworzący ją wątek (procedura run), który ją wywołuje by powiadomić o zmianach obserwujących), a nie można używać sygnałów / slotów między wątkami. Jak to obejść?

package JambiTest;

import java.util.Observable;
import java.util.Observer;

import com.trolltech.qt.core.QObject;

public class Client extends QObject implements Observer {
	/*
	 * Data.
	 */
	protected int number;
	protected Thread t = null;
	protected CounterThread counter = null;
	
	/*
	 *  Signals.
	 */
	Signal1<Integer> send_number = new Signal1<Integer>();
	Signal2<String, String> send_info = new Signal2<String, String>();
	
	Client() {
		counter = new CounterThread();
		counter.addObserver(this);
		number = 0;
	}
	
	/*
	 * Slots.
	 */
	// runs counter thread
	public void start_counter() {
		t = new Thread(counter);
		send_info.emit("Info", "Thread started");
		t.start();
	}
	
	public class CounterThread extends Observable implements Runnable {
		@Override
		public void run() {
			while(true) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				++number;
				number %= 10;
				setChanged();
				notifyObservers(number);
			}
		}
	}

	@Override
	public void update(Observable arg0, Object arg1) 
	{
		if(arg1 instanceof Integer)
			send_number.emit((Integer) arg1);
	}
}

Wyjątek:

Exception in thread "Thread-2" QObject used from outside its own thread, object=JambiTest::Client(0x5549a80) , objectThread=Thread[main,5,main], currentThread=Thread[Thread-2,5,main]
at com.trolltech.qt.GeneratorUtilities.threadCheck(Un known Source)
at com.trolltech.qt.core.QObject.signalsBlocked(Unkno wn Source)
at com.trolltech.qt.internal.QSignalEmitterInternal$A bstractSignalInternal.emit_helper(Unknown Source)
at com.trolltech.qt.QSignalEmitter$Signal1.emit(Unkno wn Source)
at JambiTest.Client.update(Client.java:59)
at java.util.Observable.notifyObservers(Unknown Source)
at JambiTest.Client$CounterThread.run(Client.java:50)
at java.lang.Thread.run(Unknown Source)

Próbowałem to rozwiązać przechodząc na czyste sygnały sloty, niestety występuje ten sam problem: nie działają sygnały - sloty między wątkami.

package JambiTest;

import com.trolltech.qt.core.QObject;

public class Client extends QObject {
	/*
	 * Data.
	 */
	protected int number;
	protected Thread t = null;
	protected CounterThread counter = null;
	
	/*
	 *  Signals.
	 */
	Signal1<Integer> send_number = new Signal1<Integer>();
	Signal2<String, String> send_info = new Signal2<String, String>();
	
	Client() {
		counter = new CounterThread();
		number = 0;
		counter.send_thread_number.connect(this, "update(Integer)");
	}
	
	/*
	 * Slots.
	 */
	// runs counter thread
	public void start_counter() {
		t = new Thread(counter);
		send_info.emit("Info", "Thread started");
		t.start();
	}
	
	public class CounterThread extends QObject implements Runnable {
		public Signal1<Integer> send_thread_number = new Signal1<Integer>();
		@Override
		public void run() {
			while(true) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				++number;
				number %= 10;
				send_thread_number.emit(number);
			}
		}
	}

	public void update(Integer i) 
	{
		send_number.emit(i);
	}
}

Wyjątek:

Exception in thread "Thread-2" QObject used from outside its own thread, object=JambiTest::Client$CounterThread(0x56f9b20) , objectThread=Thread[main,5,main], currentThread=Thread[Thread-2,5,main]
at com.trolltech.qt.GeneratorUtilities.threadCheck(Un known Source)
at com.trolltech.qt.core.QObject.signalsBlocked(Unkno wn Source)
at com.trolltech.qt.internal.QSignalEmitterInternal$A bstractSignalInternal.emit_helper(Unknown Source)
at com.trolltech.qt.QSignalEmitter$Signal1.emit(Unkno wn Source)
at JambiTest.Client$CounterThread.run(Client.java:47)
at java.lang.Thread.run(Unknown Source)

Każda podpowiedź mile widziana.
Pozdrawiam,