Slot funktioniert nicht
-
Hallo alle miteinander,
ich bin derzeit dabei, mir QT beizubringen.
Ich habe versucht ein kleiner Prog zu schreiben, dass, wenn man auf einen Knopf klick, eine Zufallszahl in einer LCD-Anzeige anzeigt.
Nun habe ich mir folgenden Code geschrieben:
# include <QPushButton> # include <QLCDNumber> # include <QApplication> # include <QMainWindow> # include <QHBoxLayout> # include <QVBoxLayout> # include <QWidget> # include <Q3HBox> # include <Q3VBox> class ONOLCD : public QLCDNumber { public: ONOLCD(QWidget *parent); private slots: void gen_rand(); }; ONOLCD::ONOLCD(QWidget *parent) : QLCDNumber(parent) { display(23); } void ONOLCD::gen_rand() { int tmp = 0; tmp = rand()%99; display(tmp); } int main(int argc, char **argv) { QApplication app(argc,argv); Q3HBox hbox; Q3VBox vbox (&hbox); ONOLCD lcd(&vbox); QPushButton gen ("Generate",&vbox); QPushButton quit ("Quit",&hbox); QObject::connect(&gen,SIGNAL(clicked()),&lcd,SLOT(gen_rand())); QObject::connect(&quit,SIGNAL(clicked()),&hbox,SLOT(close())); hbox.show(); return app.exec(); }
Das Problem ist, dass wenn ich auf meinen schönen Knopf klicke, absolut nichts mit dem LCD passiert.
Kann mir vieleicht jemand einen Tipp geben, was an dem Code zu ändern ist, damit es funktioniert?
Ich wäre sehr dankbar für die Hilfe,
Danke im Voraus,
Ciao,Prof. MAAD
-
Lies nochmal über Signals und Slots nach:
http://doc.trolltech.com/4.0/signalsandslots.html
Achte dabei auf Q_OBJECT und den Metacompiler.
-
Ok, danke erstmal.
Ich habe bemerkt, dass ich bei der Klassendefinition wohl noch Q_Object eibeziehen muss:
class ONOLCD : public QLCDNumber { Q_OBJECT public: ONOLCD(QWidget *parent); private slots: void gen_rand(); };
Dummerweise bekomme ich mehrere "undefined refernce"-Meldungen, wenn ich versuche, dass zu compilieren.
Ich benutze Windows und compiliere dort mit Hilfe von qmake:qmake -project qmake make
Kann mir vieleicht jemand sagen, wie ich diese "undefined refernce"-Probleme beheben kann?
Danke im Voraus,
CiaoProf. MAAD
-
Werden die moc Dateien erzeugt und auch kompiliert?
Eventuell musst du deine Klasse in Header und Implementierung aufspalten.
-
Ok, danke.
Also, ich habe nun folgende Codeaufteilung vorgenommen:
onolcd.h:
class ONOLCD : public QLCDNumber { Q_OBJECT public: ONOLCD(QWidget *parent); private slots: void gen_rand(); }; ONOLCD::ONOLCD(QWidget *parent) : QLCDNumber(parent) { display(23); } void ONOLCD::gen_rand() { int tmp = 0; tmp = rand()%99; display(tmp); }
main.cpp:
# include <QPushButton> # include <QLCDNumber> # include <QApplication> # include <QMainWindow> # include <QHBoxLayout> # include <QVBoxLayout> # include <QWidget> # include <Q3HBox> # include <Q3VBox> # include <QObject> # include <onolcd.h> int main(int argc, char **argv) { QApplication app(argc,argv); Q3HBox hbox; Q3VBox vbox (&hbox); ONOLCD lcd(&vbox); QPushButton gen ("Generate",&vbox); QPushButton quit ("Quit",&hbox); QObject::connect(&gen,SIGNAL(clicked()),&lcd,SLOT(gen_rand())); QObject::connect(&quit,SIGNAL(clicked()),&hbox,SLOT(close())); //window.show(); hbox.show(); return app.exec(); }
Wenn ich dass nun compiliere, erzeugt er zwar erfolgreich ein "moc"-File, spukt mir aber sehr viele Fehler der folgenden Machart aus:
In file included from release\moc_onolcd.cpp:10: release\/../onolcd.h:2: error: expected class-name before '{' token release\/../onolcd.h:4: error: ISO C++ forbids declaration of `Q_OBJECT' with no type release\/../onolcd.h:4: error: expected `;' before "public" release\/../onolcd.h:6: error: expected `:' before "slots" release\/../onolcd.h:7: error: expected primary-expression before "void" release\/../onolcd.h:7: error: ISO C++ forbids declaration of `slots' with no type
Kann mir vieleicht jemand erklären, wieso jetzt auf einmal alles falsch sein soll am Code?
Danke im Voraus,
Ciao
Prof. MAAD
-
Naja, wie kommen normalerweise solche Fehler zustande?
Richtig, es fehlen Header in der onolcd.h
-
Ponto schrieb:
Naja, wie kommen normalerweise solche Fehler zustande?
Richtig, es fehlen Header in der onolcd.h
nope, sieh dir an, in welcher reihenfolge der kram inkludiert wird (mal ganz davon abgesehen, dass die codeaufteilung nicht wirklich schlau ist). Gibt es nicht so einen qt-compiler, der z.B. private slots auflöst? Sieht mir nicht so aus, als ob der zur anwendung kommt.
-
ness schrieb:
Ponto schrieb:
Naja, wie kommen normalerweise solche Fehler zustande?
Richtig, es fehlen Header in der onolcd.h
nope, sieh dir an, in welcher reihenfolge der kram inkludiert wird (mal ganz davon abgesehen, dass die codeaufteilung nicht wirklich schlau ist). Gibt es nicht so einen qt-compiler, der z.B. private slots auflöst? Sieht mir nicht so aus, als ob der zur anwendung kommt.
Ich sehe, dass moc_onolcd.cpp die Datei onolcd.h einbindet und dann zum Beispiel Q_OBJECT nicht gefunden wird. Das ist meiner Meinung nach eindeutig.
-
Äh, ja, ich habe eigentlich keine ahnung von qt, aber prof_maads letztem post entnehme ich, dass es nur noch main.cpp/onolcd.h gibt. Außerdem: wie könnte ein header aussehen, der diesen fehler auflöst:
release\/../onolcd.h:6: error: expected `:' before "slots"
?
-
ness schrieb:
Äh, ja, ich habe eigentlich keine ahnung von qt, aber prof_maads letztem post entnehme ich, dass es nur noch main.cpp/onolcd.h gibt. Außerdem: wie könnte ein header aussehen, der diesen fehler auflöst:
release\/../onolcd.h:6: error: expected `:' before "slots"
?
#define slots
-
Sicher? Aber egal, ich glaube nicht, dass das sinn macht...
-
Das macht schon Sinn. Slots und signals werden vom MOC, dem Meta-Object-Compiler ausgewertet. Damit das ganze jedoch legaler C++ Code wird, müssen die Sachen rausgefiltert werden, wenn der C++ Compiler das vorgesetzt bekommt.
-
So, ich habe das ganze jetzt auf Grund eurer Hilfe nochmals geändert, und es sieht jetzt besser aus.
Hier der Code:
onolcd.hpp:
# include <QPushButton> # include <QLCDNumber> # include <QApplication> # include <QMainWindow> # include <QHBoxLayout> # include <QVBoxLayout> # include <QWidget> # include <Q3HBox> # include <Q3VBox> # include <QObject> class ONOLCD : public QLCDNumber { Q_OBJECT public: ONOLCD(QWidget *parent); private slots: void gen_rand(); }; ONOLCD::ONOLCD(QWidget *parent) : QLCDNumber(parent) { display(23); } void ONOLCD::gen_rand() { int tmp = 0; tmp = rand()%99; display(tmp); }
main.cpp:
# include "onolcd.hpp" int main(int argc, char **argv) { QApplication app(argc,argv); Q3HBox hbox; Q3VBox vbox (&hbox); ONOLCD lcd(&vbox); QPushButton gen ("Generate",&vbox); QPushButton quit ("Quit",&hbox); QObject::connect(&gen,SIGNAL(clicked()),&lcd,SLOT(gen_rand())); QObject::connect(&quit,SIGNAL(clicked()),&hbox,SLOT(close())); hbox.show(); return app.exec(); }
Funktionieren tut es jedoch immer noch nicht. Der Compiler liefert mir nun folgende Fehler:
release\moc_onolcd.o(.text+0x0):moc_onolcd.cpp: multiple definition of `ONOLCD:: ONOLCD(QWidget*)' release\main.o(.text+0x0):main.cpp: first defined here release\moc_onolcd.o(.text+0xd0):moc_onolcd.cpp: multiple definition of `ONOLCD: :ONOLCD(QWidget*)' release\main.o(.text+0xd0):main.cpp: first defined here release\moc_onolcd.o(.text+0x1a0):moc_onolcd.cpp: multiple definition of `ONOLCD ::gen_rand()' release\main.o(.text+0x1a0):main.cpp: first defined here
Falls jemand ne Lösung oder nen Hinweis parat hat, dann wäre ich sehr dankbar dafür.
Danke im Voraus,
Ciao,Prof. MAAD
-
entweder du steckst die beiden Methoden-definitionen der Klasse in eine seperate .cpp datei oder du fügst folgendes in den header:
am anfang:
#ifndef __ONOLCD__
#define __ONOLCD__und am ende noch das fehlende
#endif
-
ss schrieb:
entweder du steckst die beiden Methoden-definitionen der Klasse in eine seperate .cpp datei oder du fügst folgendes in den header:
am anfang:
#ifndef __ONOLCD__
#define __ONOLCD__und am ende noch das fehlende
#endif
Verwende auf keinen Fall __ONOLCD__ als Makronamen. Doppelte Unterstriche sind für den normalen Programmierer verboten.
In diesem Fall würde das die doppelte Definition auch nicht verhindern. Das ist kein Qt sondern ein grundsätzliches C++ Problem. Wenn du im Header Funktionen definierst, sollten die inline sein oder templates sein. Ansonsten wird die Funktion in jede Übersetzungseinheit eingefügt, die auch den Header benutzt.
Verschiebe einfach die Definition in die .cpp Datei. Und du solltest dich nochmals über die Aufteilung in mehrere Dateien in C++ erkundigen.
-
So, danke erstmal alle sammt.
Also, ich habe die Funktionsdefinitionen der Klasse nun nach "main.cpp" verschoben, und es funzt endlich.
Juhu!
Also, danke nochmal und ich werde mir deinen Rat zu Herzen nehmen, Ponto.
Ach so, mal ganz so nebenbei: Kennt jemand nen gutes Einsteigerwerk zu QT 4 (Tutorial oder Buch)? Wäre ne gute Sache.
Danke alle miteinander,
Ciao,
Prof. MAAD
-
prof_maad schrieb:
So, danke erstmal alle sammt.
Also, ich habe die Funktionsdefinitionen der Klasse nun nach "main.cpp" verschoben, und es funzt endlich.
Juhu!
Also, danke nochmal und ich werde mir deinen Rat zu Herzen nehmen, Ponto.
Ach so, mal ganz so nebenbei: Kennt jemand nen gutes Einsteigerwerk zu QT 4 (Tutorial oder Buch)? Wäre ne gute Sache.
Danke alle miteinander,
Ciao,
Prof. MAAD
Das Tutorial bei Qt4 selbst ist ganz gut. Ebenso die ganzen Howtos.