Warum wird Slot nicht gerufen?

Alles rund um die Programmierung mit Qt
Antworten
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Warum wird Slot nicht gerufen?

Beitrag von joebar »

Hallo,

naja der Titel muesste eigentlich heissen, warum compeliert er nicht mehr wenn ich den Slot haben will...

Also ich habe folgendes:

Code: Alles auswählen

testapp : QMainwindow
myWidget : QWidget
Add : myWidget
Sub : myWidget
Im Header von testapp habe ich den Prototypen einer Funktion:

Code: Alles auswählen

virtual void calculate_add();
Wobei ich alles was mit "Add" zutun hat ich auch in Add.cpp implementieren moechte. Also habe ich in Add.cpp

Code: Alles auswählen

void Add::calculate_add(){
	qDebug() << "calling method calculate_add";
	app->c1 -> setText("add");
	return;
}
Soweit kompeliert alles prima, wenn ich nun im Konstruktor von testapp folgendes connect einfuege:

Code: Alles auswählen

connect(add,SIGNAL (clicked()), this, SLOT(addWidget -> calculate_add()));
bekomme ich beim make

Code: Alles auswählen

g++  -o testapp Add.o main.o mywidget.o Sub.o testapp.o moc_testapp.o   -L/usr/lib -L/usr/lib -L/usr/src/packages/BUILD/qt-x11-opensource-src-4.0.1/lib -lQtGui -L/usr/X11R6/lib -lpng -lSM -lICE -lXi -lXrender -lXrandr -lXcursor -lXinerama -lfreetype -lfontconfig -lXext -lX11 -lm -lQtCore -lz -ldl -lpthread
moc_testapp.o:(.gnu.linkonce.r._ZTV7testapp[vtable for testapp]+0xe4): undefined reference to `testapp::calculate_add()'
collect2: ld returned 1 exit status
make: *** [testapp] Error 1
Mein Gedankengang warum ich das alles gemacht habe:

Funktion calculate_app() als virtual deklariert damit sich zur Laufzeit das System die passende Funktion sucht.

Da das connect Statement im Konstruktor von testapp sein muss (da hier das ui File eingebunden wird) muss der Prototyp also im testapp.h File stehen.

Die Funktion calculate_add() gehoert zur Klasse Add, fuer die Klasse Add habe ich ein Objekt addWidget angelegt. Von diesem Objekt moechte ich jetzt die Funktion calculate_add() rufen also addWidget -> calculate_add().

Tja da der Compiler meckert, ist da wohl was falsch in meinem Gedankengang. Die Fehlermeldung besagt ja noch dass er kein testapp::calculate_add() finden kann, genau das will ich ja nicht mehr haben, aber wie sag ich es ihm? Oder besser warum ignoriert er mein "addWidget ->"
Bin mir sicher, dass mir jemand von euch einen Hinweis geben kann.

Der komplette Sourcecode ist angehangen.

Danke,
J.
Dateianhänge
testapp.tar.gz
(19.94 KiB) 145-mal heruntergeladen
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Das hier ist falsch:
connect(add,SIGNAL (clicked()), this, SLOT(addWidget -> calculate_add()));
-> http://doc.trolltech.com/4.2/qobject.html#connect

Der Slot heisst nicht addWidget -> calculate_add() sondern calculate_add(). Das Target hast Du ja schon vorher mit 'this' angegeben.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Beitrag von joebar »

okay das klingt jetzt vielleicht bloed, aber das dachte ich auch zu erst, leider kommt da auch

Code: Alles auswählen

++  -o testapp Add.o main.o mywidget.o Sub.o testapp.o moc_testapp.o   -L/usr/lib -L/usr/lib -L/usr/src/packages/BUILD/qt-x11-opensource-src-4.0.1/lib -lQtGui -L/usr/X11R6/lib -lpng -lSM -lICE -lXi -lXrender -lXrandr -lXcursor -lXinerama -lfreetype -lfontconfig -lXext -lX11 -lm -lQtCore -lz -ldl -lpthread
moc_testapp.o:(.gnu.linkonce.r._ZTV7testapp[vtable for testapp]+0xe4): undefined reference to `testapp::calculate_add()'
collect2: ld returned 1 exit status
make: *** [testapp] Error 1

Aber das 'this' bezieht sich doch auf die aktuelle Instanz wo der Aufruf statt findet, sprich im Konstruktor von testapp, also bezieht das 'this' sich auf die Instanz von testapp die ich in main.cpp anlege. Danach muesste er wiederum nach testapp::calculate_add() suchen. Ich habe auch mal das 'this' im connect gegen 'addWidget' getauscht, bringt aber auch wieder den gleichen Fehler. Mir ist nicht ganz klar woher er sich jetzt das Target ziehen will. Die einzigen Ideen die ich gehabt habe sind:

- Automatisch irgendwie
- target im connect string
- ueber '->' (was wohl nicht erlaubt ist)

keins hat geklappt, so wie ich dich verstehe muesste es die erste Option sein. Aber woher will er das erkennen?
aw
Beiträge: 3
Registriert: 25. Februar 2007 19:38
Wohnort: Regensburg

Beitrag von aw »

Hallo,

dein Problem ist, das du in der testapp - Header die Methode calculate_add() zwar deklariert hast, diese aber nicht definiert ist.
Sofern ich in deinen Sourcen gesehen habe, hast du die Methode auskommentiert. Kommentier die mal wieder ein (Kommentare löschen), dann sollte es übersetzten.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

joebar hat geschrieben:okay das klingt jetzt vielleicht bloed, aber das dachte ich auch zu erst, leider kommt da auch
Trotzdem ist der connect - Aufruf falsch. Siehe auch http://doc.trolltech.com/4.2/signalsandslots.html
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

1. Heißt es

Code: Alles auswählen

connect(add, SIGNAL(clicked()), this, SLOT(calculate_add()));
2. Schau dir mal diese Fehlermeldung genau an:
moc_testapp.o:(.gnu.linkonce.r._ZTV7testapp[vtable for testapp]+0xe4): undefined reference to `testapp::calculate_add()'
Und dann überleg dir mal woher das kommen könnte.
3. Dann räum mal deinen Code auf, du kennst dich darin ja selber nicht mehr aus und auch wenn deine .tar.gz's relativ klein sind haben die Object-Dateien (*.o) darin nichts zu suchen.
4. Schau dir endlich mal ein C++-Buch an...
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Beitrag von joebar »

zu 1:
okay hatten wir ja oben, war schon geaendert. Hatte nur nochmal meine Gedanken dar gestellt, nicht dass es heisst ich wuerde nicht nachdenken.

zu 2:
Okay brauchte wohl den Prototypen in testapp.h nicht mehr. Uebersetzen kann ich es jetzt, funtkionieren tut es nicht. calculate_add() wird nicht gerufen.

zu 3:
gemacht. Wie du abr in meine Gedankengaengen oben lesen kannst hatte ich das bewust eingefuegt. War falsch, ja, hat aber nichts damit zu tun dass ich mich nicht mit meinem Code auskenne.

zu 4:
Auf die Gefahr hin, dass du mir nie wieder ein Frage beantwortest: Ich halte es fuer eine Unverschaemtheit und arrogant zu behaupten, dass ich kein c++ Buch lese. Die Hello World Beispiele aus C++ in die echte Qt Welt zu uebertragen macht mir halt Probleme. Die Fragen im C++ Forum zu stellen macht keinen Sinn da man da kein Qt kennt. Wie erwaehnt bin ich gerne bereit Vorschlaege anzunehmen wo ich meine Fragen posten soll, wenn nicht hier.

So und nun wieder zum Problem:

Ich hatte Add::calculate_add() als private slot definiert, da ich es aus einer anderen Klasse aufrufe muesste es wohl ehr public slot sein. Hat aber leider auch nichts gebracht. Was mich wundert ist, dass er das Programm uebersetzt, d.h. doch dass er zur Compiletime eine pasende Funktion sieht. Die einzige Stelle wo ich die Funktion calculate_add() habe ist in Add.cpp daher kann er nicht wo anders eine ueberladene Funktion ziehen.

So jetzt freue ich mich auf konstruktive Vorschlaege wo meine Gedankengaenge falsch sind. Bitte, ich schreibe jetzt schon immer extra die ganze Prosa damit ihr a) seht dass ich mir Gedanken mache und b) man mir sagen kann wo mein Gedankengang falsch ist. Im obigen Post haette man z.B. einfach mal die Frage stellen koennen warum ich ueberhaupt Schritt 1 mache und ob ich das wirklich will.

Danke,
J.
Dateianhänge
testapp.tar.gz
(3.91 KiB) 172-mal heruntergeladen
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ok, wie oft denn noch? Dein Slot ist nicht korrekt.

connect(add,SIGNAL (clicked()), this, SLOT(calculate_add()));
connect(SOURCE, SOURCESIGNAL, DEST, DESTSLOT) (siehe Doku )
Den Link habe ich aber schon weiter oben gegeben...
Noch ein Hinweis: Add hat kein Signal clicked und testapp kein Slot calculate_add()

Im Qt-Tutorial wird das ausserdem auch besprochen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Beitrag von joebar »

jungs, ihr treibt mich in den Wahnsinn...

1.
upsala schreibt oben wie mein connect statement heissen muss, (unter seinem 1.), du schreibst jetzt das es falsch ist

2. Wieso hat add kein Signal clicked? add ist ein QPushbutton.

3. testapp hat kein slot calculate_add(). Richtig genau das ist ja auch die Uebung an der ganzen Sache, der Slot soll in der Klasse Add liegen damit ich meinen Sourcecode nach Files trennen kann. Ich hatte erst einen virtual slot in testapp, aber vorgehende Diskussion hat mir ja gesagt, dass das falsch ist.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Du hast mich durcheinander gebracht weil deine Namensgebung so gut ist
1. Es gibt eine Klasse Add
2. es gibt einen Pushbutton add dem man nicht ansieht dass er einer ist
-> das connect ist also im ersten Teil korrekt und müsste demnach so aussehen

connect(add,SIGNAL (clicked()), addWidget, SLOT(calculate_add()));

Aber wie gesagt - das steht auch alles gut im Qt-Tutorial.


bitte benenne deine Variablen besser. Ausserdem beachtet dass

Add *addWidget = new Add(this);
Sub *subWidget = new Sub();

lokale Variablen anlegt (das ist pure C) was bestimmt nicht gewollt ist (zumal subWidget nicht zerstört wird)

Wenn Du Config += console reinschreibst (siehe Doku), wird Dir auch zur Laufzeit angezeigt dass das connect nicht korrekt ist.

/edit: Nochwas
class Add fehlt das Q_OBJECT -> DOKU!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
MichaelS
Beiträge: 240
Registriert: 27. Dezember 2005 12:49

Beitrag von MichaelS »

Hallo,

ich kann durchaus verstehen, dass Christian81 etwas ungeduldig wird, denn Du bist hier schon förmlich mit der Nase auf die Lösung gestoßen worden:
Die einzige Stelle wo ich die Funktion calculate_add() habe ist in Add.cpp daher kann er nicht wo anders eine ueberladene Funktion ziehen.
Genau das ist das Problem. Du hast in der Klasse add den Slot calculate_add definiert, im Konstruktor der Klasse testapp "sagst" Du dann aber:

Code: Alles auswählen

connect(add,SIGNAL (clicked()), this, SLOT(calculate_add()));
Auf deutsch: Verbinde das Signal 'click' von 'add' mit dem Slot 'calculate_add' dieser (THIS) Klasse (testapp). Diese Klasse testapp hat aber - wie Du selbst schon festgestellt hast - überhaupt keinen entsprechenden Slot.

Gruß Michael

Ergänzung: Da ist wohl während des Verfassens der Nachricht ein Teil der Diskussion an mir vorbeigegangen.
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Beitrag von joebar »

zu meiner Verteidigung, dass mit dem addWidget im connect hatte ich schon weiter oben erwaehnt - ich schaue durchaus in Tutorials. Auch wenn ich nicht alles dort in mein Programm uebertragen kann.

Werde die Variabeln umbennen damit sie nicht mehr aehnlich sind.

Verstehe nicht wie man meinem Pushbutton ansehen soll onder nicht ansieht, dass er ein Pushbutton ist? Ich habe ihn im Desinger angelegt, im generierten ui header file wird er als Pushbutton angelegt. Worauf willst du hinaus?

Ich habe das Config += console mal ins pro File aufgenommen und qmake/make nochmals laufen lassen. Aendert sich nichts, lt Doku http://doc.trolltech.com/4.2/qmake-vari ... tml#config hat es was mit Win32 zu tun, ich nutze Linux "console The target is a Win32 console application (app only). "

Q_Object, in der Doku sehe ich nur dazu "The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system." Ich habs eingefuegt, kommt leider

g++ -c -pipe -fno-strict-aliasing -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt/mkspecs/default -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I. -I. -I. -o Add.o Add.cpp
g++ -c -pipe -fno-strict-aliasing -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt/mkspecs/default -I. -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include -I. -I. -I. -o testapp.o testapp.cpp
testapp.cpp: In constructor ‘testapp::testapp(QMainWindow*)’:
testapp.cpp:18: warning: unused variable ‘subWidget’
g++ -o testapp Add.o main.o mywidget.o Sub.o testapp.o moc_testapp.o -L/usr/lib -lQtGui -L/usr/lib -L/usr/X11R6/lib -lpng -lSM -lICE -lXi -lXrender -lXrandr -lXcursor -lXinerama -lfreetype -lfontconfig -lXext -lX11 -lQtCore -lz -lm -ldl -lpthread
Add.o: In function `Add::Add(testapp*)':
Add.cpp:(.text+0x12): undefined reference to `vtable for Add'
Add.cpp:(.text+0x19): undefined reference to `vtable for Add'
Add.o: In function `Add::Add(testapp*)':
Add.cpp:(.text+0x42): undefined reference to `vtable for Add'
Add.cpp:(.text+0x49): undefined reference to `vtable for Add'
Add.o: In function `Add::~Add()':
Add.cpp:(.text+0x68): undefined reference to `vtable for Add'
Add.o:Add.cpp:(.text+0x6f): more undefined references to `vtable for Add' follow
collect2: ld returned 1 exit status
make: *** [testapp] Error 1
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Unter Linux braucht man die Option console nicht, da hast Du recht. Aber schaden tut sie auch nicht.

Das was da zu Q_OBJECT steht ist doch genau das was Du willst, oder? Einen eigenen Slot...
Du musst nach dem Einfügen von Q_OBJECT (und HEADERS += add.h in der pro-Datei) qmake neu aufrufen.

/Edit: Zum Pushbutton
z.B. Indem man ihn pushAdd nennt oder pbAdd oder was auch immer -> in Anlehnung an http://de.wikipedia.org/wiki/Ungarische_Notation
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
joebar
Beiträge: 177
Registriert: 3. Oktober 2006 02:04

Beitrag von joebar »

Ja das wollte ich.

Mir ist noch nicht ganz klar wann ich qmake aufrufen muss und wann nicht. Nach qmake war der Fehler weg. Also qmake ruf ich sonst immer nur auf wenn neue Dateien dazu gekommen sind o.ae. aber wenn ich im Source einer Datei die schon dabei ist was aendere hatte ich qmake jetzt noch nicht auf dem Plan. Werde nochmal googeln ob ich da ein Rezept finde wann qmake und wann nicht.

Jetzt funktioniert es, danke!
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

qmake wird normalerweise bei jeder Änderung in der pro-Datei automatisch aufgerufen. Ausserdem muss qmake aufgerufen werden, wenn Du in einem Header Q_OBJECT hinzufügst damit qmake die entsprechenden moc-Aufrufe generieren kann.
Ist bei cmake oder automake genauso.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten