PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : QT Signals/Slots: Wie der Ochs form Berge



zeeman
26-02-2004, 17:06
Hi!

Ich hab gestern mal mit QT angefangen.
Soweit, so gut.
Ich programmiere direkt in Kate, also zu Fuß, ohne irgendwelche Designer.

Ne Oberfläche krieg ich ja noch zusammengebastelt.

Aber dann kommen die Signals und Slots.
Öh ja.

Eigenltich will ich ja nur die 'activated'-Funktion von ner Combobox mit ner äffen void-Funktion verbinden und der index, der von activated kommt soll mit an diese void-funktion übergeben werden.

aber irgendwie krieg ich das net hin.
wo muss denn bitte die deklaration von der funktion, die ich aufrufe rein.
mit in die widget klasse?
in ne eigene klasse?
einfach als normale funktion in dem programm?

ich werd aus den dokus bei trolltech irgendwie nicht schlau

hoffe hier kann mir einer den tipp geben, damit ich das system komplett durchschaue.

zeeman

P.S.: was heißt widget übersetzt eigentlich?

axeljaeger
26-02-2004, 17:48
so:



class MyWidget : public QWidget{
Q_OBJECT
public slots:
void handleActivated(int id);

};

zeeman
26-02-2004, 18:24
also hier mal ein paar codestellen von mir:



class MyWidget : public QWidget
{
//Q_OBJECT
public slots:
void handleActivated(int id);
public:
MyWidget( QWidget *parent=0, const char *name=0 );
};

wenn ich da Q_OBJECT einfüge prasselt es fehlermeldungen beim kompilieren:


main.o(.text+0x43): In function `MyWidget::MyWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x4f): In function `MyWidget::MyWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x11a3): In function `MyWidget::MyWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x11af): In function `MyWidget::MyWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x23ea): In function `main':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x23f5): more undefined references to `vtable for MyWidget' follow
collect2: ld returned 1 exit status




void handleActivated(int id)
{
qWarning( "test" );
}

einfach nur mal zum testen



MyWidget::MyWidget( QWidget *parent, const char *name )
: QWidget( parent, name )
{
[...]
connect ( GK, SIGNAL(activated()), qApp, SLOT (quit()));
// connect ( GK, SIGNAL(activated(index)), qApp, SLOT (handleActivated(index)));

beides davon geht nicht
es kommt immer zur laufzeit:


QObject::connect: No such signal QComboBox::activated()
QObject::connect: (sender name: 'GK')


GK ist ein pointer auf eine QCombobox.

ich verstehs net..... :rolleyes:

anda_skoa
26-02-2004, 18:56
Das Q_OBJECT Macro muss im der Dekaration drinnen sein, weil sonst das Objekte keinen Signals oder Slots hat (sondern nur normale Methoden)

Der Fehler ist kein MOC File, also moc hat den Header nicht geparst und kein entsprechendes File mit den QObject Sachen angelegt.

Auch wenn du zu Fuß arbeitest, spricht nichts dagegen, qmake zu Makefilegenerierung zu verwenden.

Beide Möglichkeiten (händischer moc Aufruf und qmake Benutzung) werden im Qt Tutorial im Tutorial Unterforum beschrieben.

Widget:
ist ein Kunstwort, eine Verknüpfung von Window und Gadget.

Ciao,
_

zeeman
26-02-2004, 19:07
qmake hab ich eigentlich immer verwendet, gut schau ich da nochmal
weiß ja jetzt nach was ich ausschau halten muss.

danke für die erklärung
nur was ist ein gadget? :confused:

peschmae
26-02-2004, 19:35
Gadget ist einerseits irgend so n technischer Apparat. Andererseits (und das triffts wohl) ein Zubehörteil.

MfG Peschmä

zeeman
26-02-2004, 20:44
ich krieg gleich ne kramp.

nach dem studium der doku von qt hieß es eigenltich qmake macht das alles selber
qmake -project
qmake

und dann
make

fertig.
pustkuchen.

ich habs jetzt mal mit folgendem versucht:
qmake -project
qmake
dann ganz unten in meine main.cpp (ist nur eine datei das programm)
include <main.moc>
abspeichern
moc main.cpp > main.moc
make

soweit so gut

nu bin ich hier:
main.o(.text+0x298d): In function `MyWidget::qt_invoke(int, QUObject*)':
: undefined reference to `MyWidget::handleActivated(int)'
collect2: ld returned 1 exit status

also irgendwas stimmt hier net.
HILFE :rolleyes:

tuxipuxi
26-02-2004, 20:53
Hi,

wenn du qmake benutzt brauchst du dich nicht um moc Dateien zu kümmern, da qmake diese automatisch generiert und mit reinkompiliert.

Also einfach qmake -project && qmake && make.

Falls irgendwas schiefläuft, nochmal die .pro Datei überprüfen.

Gruss,
Michael.

zeeman
26-02-2004, 21:02
wie schon oben gepostet, dann kommt das hier:


main.o(.text+0x43): In function `MyWidget::MyWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x4f): In function `MyWidget::MyWidget[not-in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x11a3): In function `MyWidget::MyWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x11af): In function `MyWidget::MyWidget[in-charge](QWidget*, char const*)':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x23ea): In function `main':
: undefined reference to `vtable for MyWidget'
main.o(.text+0x23f5): more undefined references to `vtable for MyWidget' follow


meine pro-file:


##############################################
# Automatically generated by qmake (1.06c) Thu Feb 26 22:01:07 2004
##############################################

TEMPLATE = app
CONFIG -= moc
INCLUDEPATH += .

# Input
SOURCES += main.cpp

also irgendwie stört mich dieses -=
+= heißt ja an liste anfügen
= liste ersetzen
aber -=
von liste abziehen?!?!

anda_skoa
27-02-2004, 04:36
Gib mal das Widget in ein eigenes header/source Paar, also zB mywidget.h und mywidget.cpp

Dann würde ich das .pro File händisch erzeugen, etwa so



TEMPLATE = app
CONFIG += qt thread warn_on

HEADERS = mywidget.h
SOURCES = main.cpp mywidget.cpp


Ciao,
_

zeeman
27-02-2004, 14:17
ich weiß einfach nicht mehr weiter, bitte einer mal drauf schaun:


#include <qapplication.h>
#include <qapplication.h>
#include <qpushbutton.h>
#include <qfont.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qtextedit.h>
#include <qsqldriver.h>
#include <qsqldatabase.h>

#define DB_ADRESS_DRIVER "QMYSQL3"
#define DB_ADRESS_DBNAME "stundenplan"
#define DB_ADRESS_USER "xxxx"
#define DB_ADRESS_PASSWD "xxxxx"
#define DB_ADRESS_HOST "wodan"


class Hausaufgabe: public QObject
{
Q_OBJECT
public slots:

signals:

private:
char *username;
char *password;
char *dateiname;
char *titel;
char *nachricht;
public:
void SetUsername(char *user);
void SetPassword(char *pw);
void SetDateiname(char *filename);
void SetTitle(char *text);
void SetNachricht(char *text);
};



class MyWidget : public QWidget
{
Q_OBJECT
public slots:
void handleActivated( int Schiene);
public:
MyWidget( QWidget *parent=0, const char *name=0 );
};

MyWidget::MyWidget( QWidget *parent, const char *name )
: QWidget( parent, name )
{
setMinimumSize( 400, 600 );
setMaximumSize( 400, 600 );

QLabel *lbUsername = new QLabel(this);
QLabel *lbPassword = new QLabel(this);

QLineEdit *username = new QLineEdit("", this, "username");
QLineEdit *password = new QLineEdit("", this, "password");
QLineEdit *filename = new QLineEdit("", this, "filename");

QPushButton *quit = new QPushButton( "Beenden", this, "quit" );
QPushButton *login=new QPushButton("Einloggen",this,"login");
QPushButton *datei=new QPushButton(". . .", this, "datei");
QPushButton *upload=new QPushButton("Hochladen", this, "upload");

QComboBox *GK = new QComboBox( FALSE, this, "GK" );
QComboBox *Fach = new QComboBox( FALSE, this, "Fach" );

QTextEdit *Nachricht = new QTextEdit (this, "Nachricht");

quit->setFont( QFont( "Arial", 10 ) );
quit->setGeometry(320, 565, 75, 30 );

login->setFont(QFont("Arial,10"));
login->setGeometry(320,45,75,25);

lbUsername->setText ( "Benutzername:");
lbUsername->setGeometry(5,10,100,25);
lbUsername->setFont( QFont("Arial",10));

lbPassword->setText("Passwort:");
lbPassword->setFont(QFont("Arial",10));
lbPassword->setGeometry(210,10,70,25);

username->setFont(QFont("Arial",10));
username->setGeometry(105,10,100,25);

password->setFont(QFont("Arial",10));
password->setGeometry(285,10,100,25);
password->setEchoMode(QLineEdit::Password);

GK->setFont(QFont("Arial",10));
GK->setGeometry(105, 80, 100, 25);
GK->insertItem("LK 1",-1);
GK->insertItem("LK 2",-1);
GK->insertItem("GK 1",-1);
GK->insertItem("GK 2",-1);
GK->insertItem("GK 3",-1);
GK->insertItem("GK 4",-1);
GK->insertItem("GK 5",-1);
GK->insertItem("GK 6",-1);
GK->insertItem("GK 7",-1);
GK->insertItem("GK 8",-1);

Fach->setFont(QFont("Arial",10));
Fach->setGeometry(285, 80, 100, 25);

Nachricht->setFont(QFont("Arial",10));
Nachricht->setGeometry(5, 115, 390,350);

filename->setFont(QFont("Arial",10));
filename->setGeometry(5,475,355,25);

datei->setFont(QFont("Arial",10));
datei->setGeometry( 365,475,30,25);

upload->setFont(QFont("Arial",10));
upload->setGeometry(150,510,100,50);

connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );
connect ( GK, SIGNAL(activated(index)), qApp, SLOT(handleActivated(index)));

}

void MyWidget::handleActivated( int Schiene)
{
Schiene=1;
qWarning( "test" );
}

int main( int argc, char **argv )
{
QApplication a( argc, argv );

MyWidget w;
w.setGeometry( 100, 100, 200, 120 );
a.setMainWidget( &w );
w.show();
QSqlDatabase *defaultDB = QSqlDatabase::addDatabase( DB_ADRESS_DRIVER );
if ( ! defaultDB )
{
qWarning( "main: Keine Verbindung zur Datenbank" );
return 1;
}
return a.exec();
}

#include "main.moc"

dann krieg ich das programm auch so kompiliert:
# qmake -project
# qmake
# moc main.cpp > main.moc
# make

nur dann kommt das (wie orginell):


QObject::connect: No such signal QComboBox::clicked()
QObject::connect: (sender name: 'GK')
QObject::connect: (receiver name: 'Hausaufgaben')


- ja, ich weiß, die schriftart hätte man auch global definieren können
- die klasse hausaufgaben ist untinteressant, ich hab sie nur schonmal definiert
- meine void-funktion is erstmal nur ne dummyfunktion. das soll erstmal laufen
der rest sollte klar sein, ansonsten bitte mal melden.
ich seh da echt keine fehler mehr

MfG
Sebastian:rolleyes:

anda_skoa
27-02-2004, 15:19
Original geschrieben von zeeman
ich weiß einfach nicht mehr weiter, bitte einer mal drauf schaun:


#include <qapplication.h>
#include <qapplication.h>


zweimal? :)



private:
char *username;
char *password;
char *dateiname;
char *titel;
char *nachricht;


Bitte, bitte, bitte QString!



public:
void SetUsername(char *user);
void SetPassword(char *pw);
void SetDateiname(char *filename);
void SetTitle(char *text);
void SetNachricht(char *text);
};

const QString& statt char*



QLineEdit *username = new QLineEdit("", this, "username");
QLineEdit *password = new QLineEdit("", this, "password");
QLineEdit *filename = new QLineEdit("", this, "filename");


Gefährlich lokale Variablen wie Instanzvariablen zu benennen, da kann man schnell durcheinander kommen.



connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );
connect ( GK, SIGNAL(activated(index)), qApp, SLOT(handleActivated(index)));


Die Macros SIGNAL und SLOT brauchen bei den Parametern nur den Typ, nicht den Namen des Parameters, also


connect ( GK, SIGNAL(activated(int)), qApp, SLOT(handleActivated(int)));



Ich denke bei einer UI mir mehreren Elementen ist es wesentlich einfacher im Designer.
Dann die eigentliche Klasse davon ableiten und die Sachen wie zB Slots implementieren.

Ciao,
_

axeljaeger
27-02-2004, 15:20
QComboBox hat ja auch kein Signal clicked():

Signals

*
void activated ( int index )
*
void highlighted ( int index )
*
void activated ( const QString & string )
*
void highlighted ( const QString & string )
*
void textChanged ( const QString & string )

von http://doc.trolltech.com/3.3/qcombobox.html

zeeman
27-02-2004, 15:56
es geht.
lag nur an dem 'int' was für das signal mit rein muss

*freufreu*

das mit den lokalen, gleichen vars
da ich net gleichzeitig auf beide zugreifen kann (sind ja privat in der klasse, nur über SetXXX) fand ich das vertrebar.

zu den qstrings mach ich mich mal schlau (das sind dann wohl irgendwelche eierlegenden wollmilchsäue die overflows und sowas abfangen. ich schau mal)

qmake will zwar noch net ganz automatisch, aber das krieg ich selber hin.

nochmal dickes Danke an alle die geholfen haben

anda_skoa
27-02-2004, 19:04
Original geschrieben von zeeman

das mit den lokalen, gleichen vars
da ich net gleichzeitig auf beide zugreifen kann (sind ja privat in der klasse, nur über SetXXX) fand ich das vertrebar.

Die lokalen Variablen waren im Konstruktor der Klasse und der Code des Konstruktors hat üblicherweise direkten Zugriff auf die private Variablen, wie andere Methoden auch.



zu den qstrings mach ich mich mal schlau (das sind dann wohl irgendwelche eierlegenden wollmilchsäue die overflows und sowas abfangen. ich schau mal)

Unter anderem.
In C++ verwendet man praktisch immer eine Stringklasse, nur bei der Benutzung von C Funktionen geht man auf das char* zurück.
char* ist nämlich wesentlich umständlicher in der Handhabung und warum sollte man sich das Lebem unnötig schwer machen.

In Qt benutzt man praktisch immer QString, in C++ ohne Qt meistens std::string

Ciao,
_