PDA

View Full Version : Understanding signals/slots - small chat example



caesius
12th January 2010, 00:54
I've written a network chat client in C and (for fun) I'm learning Qt with the eventual goal of writing a GUI for the chat program.

I'm sort of loosely following the structure of a GUI chat program, but I'm not worrying about connecting up the network code yet - just trying to understand signals and slots.

So I've (tried) to write a program with an output window, an input window, and a submit button. ALL I want the program to do is echo anything written in the input window to the display window when the submit button is pressed. I think it's clear what I'm trying to do by looking at the code, I'm just doing it wrong obviously.



#include <QApplication>
#include <QPushButton>
#include <QLineEdit>
#include <QTextEdit>
#include <QVBoxLayout>

class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
};

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{

QPushButton *quit = new QPushButton("Quit", this);
QPushButton *submit = new QPushButton("Submit", this);
QLineEdit *input = new QLineEdit;
QTextEdit *output = new QTextEdit;

output->setReadOnly(true);

connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
connect(submit, SIGNAL(clicked()), output, SLOT(append(input->text())));

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(quit);
layout->addWidget(output);
layout->addWidget(input);
layout->addWidget(submit);
setLayout(layout);

}

int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}


It compiles cleanly, but when it runs I get the error



Object::connect: No such slot QTextEdit::append(input->text()) in main2.cpp:24


EDIT: Here is the offending line from what I have been told


connect(submit, SIGNAL(clicked()), output, SLOT(append(input->text())));

What gives? According to here (http://doc.trolltech.com/3.3/qtextedit.html#append), append *is* a slot. Why can't I use it? What am I missing?

Thanks, Benjamin

bood
12th January 2010, 02:05
Two mistakes here:
1. When connecting to a slot, you cannot decide what should be passed. (like you input->text()), the parameter is always using the one passed from the signal. You can only specify a "prototype" here, e.g. SLOT(append(QString))
2. When connecting a signal to a slot, the parameters should be match, while they don't here. So you should connect the clicked signal to some use defined function in your class (e.g. could be named as submitClicked) and call input->appned() from that function.

Hope it helps.

caesius
12th January 2010, 02:47
Two mistakes here:
1. When connecting to a slot, you cannot decide what should be passed. (like you input->text()), the parameter is always using the one passed from the signal. You can only specify a "prototype" here, e.g. SLOT(append(QString))
2. When connecting a signal to a slot, the parameters should be match, while they don't here. So you should connect the clicked signal to some use defined function in your class (e.g. could be named as submitClicked) and call input->appned() from that function.

Hope it helps.

Thanks for the reply. I don't understand (2) however, if I wrote a function like what I've got below (which is what you're suggesting?), how would this function know that the varibles input and output exist?



MyWidget::submitClicked(void) {
output->append(input->text());
}


Wouldn't I have to pass the addresses of input and output along with this function?

bood
12th January 2010, 02:54
Of course you don't have to.
Usually, these variables are defined as member variables of your widget class, so that you can reference them in any member functions as you want.

caesius
12th January 2010, 03:45
Thanks for clearing that up, I've re-written the code based on what I've understood you to be saying.



#include <QApplication>
#include <QPushButton>
#include <QLineEdit>
#include <QTextEdit>
#include <QVBoxLayout>

class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
QLineEdit *input;
QTextEdit *output;

public slots:
void putMessage(void);

private:

};

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{

QPushButton *quit = new QPushButton("Quit", this);
QPushButton *submit = new QPushButton("Submit", this);
input = new QLineEdit;
output = new QTextEdit;

output->setReadOnly(true);

connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
connect(submit, SIGNAL(clicked()), this, SLOT(putMessage()));

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(quit);
layout->addWidget(output);
layout->addWidget(input);
layout->addWidget(submit);
setLayout(layout);

}

void MyWidget::putMessage(void)
{
output->append(input->text());
}

int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}


I'm still not doing something right because I still get


Object::connect: No such slot QWidget::putMessage() in main2.cpp:32

bood
12th January 2010, 04:43
Try adding a "Q_OBJECT" notation at the beginning of your class.


class MyWidget : public QWidget
{
Q_OBJECT
//blah blah blah
};