Signal<->Slot zwischen Thread und Hauptwidget

Alles rund um die Programmierung mit Qt
Antworten
Mandel
Beiträge: 12
Registriert: 30. November 2008 20:53

Signal<->Slot zwischen Thread und Hauptwidget

Beitrag von Mandel »

Hallo zusammen ...

Ich versuche mich gerade in Qt einzuarbeiten, da ich demnächst ein Programm mit grafischer Benutzeroberfläche konstruieren muss. Zur Zeit beschäftige ich mich gerade mit Threads, da auch das Programm später mal eine (Endlos)Schleife besitzen wird, welche Daten verarbeitet.

Ich bin nun auf ein Problem gestoßen, welches ich nicht lösen kann.
Mir ist es möglich, aus dem Thread heraus ein Signal zu sende, auf welches ein Slot im Hauptwidget reagiert, umgekehrt geht es allerdings anscheinend nicht...

Hier mal der Konstruktor des Threads:

Code: Alles auswählen

MyThread::MyThread(QObject *parent)
: QThread(parent)
{
	connect(this, SIGNAL(ThreadSignal(int)), parent, SLOT(talk(int)));
	connect(parent, SIGNAL(customSignal2()), this, SLOT(RePos()));
}
Im Widget aus dem der Thread aufgerufen wird (wenn ich das recht verstehe also das parent QObject) befindet sich der Slot "talk(int)". Dieser wird auch aufgerufen, wenn im Thread "Threadsignal" aufgerufen wird.
Im Thread existiert nun der Slot "RePos()", welcher aufgerufen werden soll, wenn im Widget das Signal "customSignal2()" gesendet wird.
Dies geschieht allerdings nicht.
Wenn ich das Programm starte erscheint im Konsolenfenster auch immer folgende Meldung:
"Object::connect: No such slot MyThread::RePos() in c:\...\mythread.cpp:11
Object::connect: (sender name: 'myQtAppDLG')"

In Zeile 11 steht der besagte connect-Befehl im Konstruktor. Ich bin mir nicht sicher, aber wenn ich das richtig Verstehe, ist myQtAppDLG die Klasse, welche vom Designer erstellt wird, wenn ich die Benutzeroberfläche erstelle, oder?

Ich würde mich sehr über euere Hilfe freuen :D
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Warum connectest im Thread und nicht dort wo den Thread erstellst?

zB so:

Code: Alles auswählen

MyThread *thread = new MyThread(this);
connect (this, SIGNAL(a()), thread(), SLOT(on_a()));
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Zeig mal die Klassen-Definition von MyThread.
Vor allem will ich wissen, wie MyThread::RePos() deklariert ist!
Denn die Warnung auf der Console

Code: Alles auswählen

Object::connect: No such slot MyThread::RePos() in c:\...\mythread.cpp:11 
Ist eigentlich eindeutig...
Mandel
Beiträge: 12
Registriert: 30. November 2008 20:53

Beitrag von Mandel »

Hier erstmal die Klassendefinition von RePos(). zZ steht da aber noch nicht viel drin. War ja erstmal nur nen Versuch, um zu schauen, ob ichs verstanden hab ;)

Code: Alles auswählen

MyThread::MyThread(QObject *parent)
: QThread(parent)
{
	connect(this, SIGNAL(ThreadSignal(int)), parent, SLOT(talk(int)));
	connect(parent, SIGNAL( customSignal2() ), this, SLOT( RePos() ));
}

void MyThread::run()
{
	int i=0;
	printf("\nMyThread läuft ...\n");
	
	for(i=0;i<10;i++)
	{
		_sleep(1000);
		emit ThreadSignal(i);

	}
	exec();
}

void MyThread::SetPos(int x)
{
	Pos=x;
}

void MyThread::RePos()
{
	printf("Tada\n");
}
@AuE
Also "anders herum" hab ichs auch schon probiert und die gleiche Meldung erhalten...
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Mandel hat geschrieben:Hier erstmal die Klassendefinition von RePos().
Das was du postest ist die Definition der Methoden, ich will aber die der Klasse :D

Code: Alles auswählen

class MyThread : public QThread
{
public:
   /* und so weiter */
};
Ich nehme an dass da was mit der deklaration deines SLOT RePos nicht stimmt, z.B. ein "public slots:" oder so vergessen.
Mandel
Beiträge: 12
Registriert: 30. November 2008 20:53

Beitrag von Mandel »

:oops:
Das ist jetzt aber peinlich... Nicht nur, dass ich mich verlesen hab...
Auch das ich das "slots" hinter "public" vergessen hab.
Und da saß ich jetzt über nen Tag dran, weil ich gedacht hab, dass durch die Threads irgendwelche Besonderheiten zu beachten sind ...

Jetzt funktionierts, danke :roll:
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Und da saß ich jetzt über nen Tag dran, weil ich gedacht hab, dass durch die Threads irgendwelche Besonderheiten zu beachten sind ...
Bei Threads gibt es verdammt viel zu beachten... nur noch ein kleiner Hinweis:

Code: Alles auswählen

MyThread::MyThread(QObject *parent)
: QThread(parent)
{
   connect(this, SIGNAL(ThreadSignal(int)), parent, SLOT(talk(int)));
   connect(parent, SIGNAL( customSignal2() ), this, SLOT( RePos() ));
} 
So wird der Slot "talk" im Kontext des Threads ausgeführt und "RePos" im Kontext der GUI... das kann durchaus so gewollt sein... muss es aber nicht (siehe zahlreiche andere Threads in diesem Forum).

hth..
Mandel
Beiträge: 12
Registriert: 30. November 2008 20:53

Beitrag von Mandel »

Vielen Dank für deinen Hinweis!
Das ist nicht gewollt, in dem Fall aber auch nicht störend...

Angenommen, ich wöllte, dass talk(int) im Thread selbst und RePos() im Kontext der GUI ausgeführt wird, was habe ich da für Möglichkeiten?

Naiverweise würde ich erstmal vermuten, dass es in diesem Fall reichen würde connect(..) in die GUI umzulagern, oder?

Allerdings könnte ich mir auch vorstellen, dass es Situationen gibt, wo vielleicht andere Lösungen sinnvoll wären?! Gibt es also noch andere Möglichkeiten? Einem Slot sozusagen bewusst in einem bestimmten hread auszuführen...
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Wenn du Sachen der GUI ändern möchtest geht das nur im GUI thread. Da wäre es sinnvoll!
qqq
Beiträge: 3
Registriert: 22. Januar 2010 16:00

Beitrag von qqq »

Hallo Zusammen,

also ich habe ein ähnliches Anliegen wie Mandel. Ich möchte, dass mein angelegter Thread indirekt Sachen auf dem GUI verändern kann.

Nur leider funktioniert es bei mir nicht...

ich habe mir ganz normal einen eigenen Thread von QThread abgeleitet run() implementiert (was auch alles super klappt)...

wenn ich jetzt im Thread ein Signal Signal1(int) erstelle
-> in der run methode steht "emit Signal1(i)"
-> Signal1(int) steht in thread headerdatei unter signals:
und in der GUI Klasse einen Slot zeichne(int)
-> steht in GUI headerdatei .h unter public slots:
dann funktioniert das aber irgendwie nicht.

Im Konstruktor von meinem Thread steht:
connect(this, SIGNAL(Signal1(int)), parent, SLOT(zeichnen(int a)));

(habe auch probiert in der GUI Klasse nach dem Erstellen des Threads folgendes einzugeben:
connect(threadobjektname, SIGNAL(Signal1(int)), this, SLOT(zeichnen(int)));
)

führt aber alles immer zu der gleichen Fehlermeldung:

Fehler 1 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""protected: void __thiscall test::Signal1(int)" (?Signal1@test@@IAEXH@Z)" in Funktion ""public: virtual void __thiscall test::run(void)" (?run@test@@UAEXXZ)". test.obj power

(test ist meine QThread Klasse)

Was mache ich falsch? :(
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Q_OBJECT in der test - Klasse auch vorhanden?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
qqq
Beiträge: 3
Registriert: 22. Januar 2010 16:00

Beitrag von qqq »

Ja, der Konstruktor der Thread Klasse beinhaltet
(QObject *parent)
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

qqq hat geschrieben:Ja, der Konstruktor der Thread Klasse beinhaltet
(QObject *parent)
Das ist nicht gemeint!
Du sollst das Macro "Q_OBJECT" in deine Test-Klasse-Definition legen.
Nix Q_OBJECT, nix SIGNAL/SLOT.
qqq
Beiträge: 3
Registriert: 22. Januar 2010 16:00

Beitrag von qqq »

ahhh :)

Daran lag es... vielen Dank :)
Antworten