PDA

View Full Version : custom slot/signal



awnjoor
16th July 2006, 13:10
Hi Im new here and Id like to ask a few questions please,

In my program there is a QLineEdit and a QLabel. What I want to do is when the user enter something in the LineEdit, I want to do some processing with it then displaying the result in QLabel. I was thinking of something like

connect(lineEdit, SIGNAL(returnPressed()), qLabel, SLOT(setText("asdf")))
but after some reading i found out that you cannot pass values in connect and besides with the above code i cannot process the input from lineedit. I read the documentation about signals and slots and I understood it somehow but I just didnt understand it enough to write my own slot/signal.

so can somebody please help me to understand and write my own slot/signal. thank you.

jpn
16th July 2006, 13:36
Let's say you have a main window containing those widgets. Then the code could look something like this:

header:


...
class MainWindow: public QMainWindow
{
Q_OBJECT // <- this macro is important

public:
MainWindow(...);
~MainWindow();
...

// your own custom slot declaration looks like this:
private slots:
void processInput();
};


implementation:


MainWindow::MainWindow(...) : ...
{
// connection between line edit and your custom slot
connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(processInput()));
}

// custom slot implementation
void MainWindow::processInput()
{
// process the line edit text
QString text = process(lineEdit->text());

// set the result
qLabel->setText(text);
}

awnjoor
16th July 2006, 14:33
thank you for the speedy reply, now here is the code


#include<QApplication>
#include<QLabel>
#include<QLineEdit>
#include<QString>

class myWidget:public QWidget{
Q_OBJECT

public:
myWidget(QWidget *parent=0);
private slots:
void processInput();
};

myWidget::myWidget(QWidget *parent)
:QWidget(parent)
{
QLabel *display=new QLabel(this);

QLineEdit *lineEdit=new QLineEdit;

connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(processInput()));

}

void myWidget::processInput(){
QString text=lineEdit->text();
display->setText(text);
}

int main(int argc, char **argv){
QApplication app(argc, argv);
myWidget window;

window.show();
return app.exec();
}

and i got undeclared error of lineEdit and display

jacek
16th July 2006, 14:55
The problem is that you declare lineEdit as a local variable in the constructor. If you want to access it in a different method, you have to declare it as a member variable.

aMan
16th July 2006, 14:57
you have declared the objects in the constructor, so they are available only there.

you should do something like that



class myWidget:public QWidget{
Q_OBJECT
public:
myWidget(QWidget *parent=0);
private slots:
void processInput();
private:
QLabel display;
QLineEdit lineEdit;
};

awnjoor
16th July 2006, 15:11
now i got new error, undefined reference to vtable for myWidget


#include<QApplication>
#include<QLabel>
#include<QLineEdit>
#include<QString>

class myWidget:public QWidget{
Q_OBJECT

public:
myWidget(QWidget *parent=0);
private slots:
void processInput();
private:
QLabel *display;
QLineEdit *lineEdit;
};

myWidget::myWidget(QWidget *parent)
:QWidget(parent)
{
display=new QLabel;
lineEdit=new QLineEdit;

connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(processInput()));

}

void myWidget::processInput(){
QString text=lineEdit->text();
display->setText(text);
}

int main(int argc, char **argv){
QApplication app(argc, argv);
myWidget window;

window.show();
return app.exec();
}

jpn
16th July 2006, 15:27
Try adding line:

#include "main.moc"
somewhere in your main.cpp.

You will have to include the moc file by hand in case you don't have separate class header files.

awnjoor
16th July 2006, 22:48
so i just add the include line to main.cpp right? i did that but the compiler said that there is no such file or directory :confused:

jacek
16th July 2006, 23:09
i did that but the compiler said that there is no such file or directory
How do you compile your application?

awnjoor
17th July 2006, 00:09
kay, i deleted everything in the folder, except main.cpp. Then i did qmake -project then qmake and then make. Now the error is in the moc file

here is my moc file


/************************************************** **************************
** Meta object code from reading C++ file 'main.cpp'
**
** Created: Mon Jul 17 06:56:41 2006
** by: The Qt Meta Object Compiler version 59 (Qt 4.1.4)
**
** WARNING! All changes made in this file will be lost!
************************************************** ***************************/

#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'main.cpp' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 59
#error "This file was generated using the moc from 4.1.4. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

static const uint qt_meta_data_myWidget[] = {

// content:
1, // revision
0, // classname
0, 0, // classinfo
1, 10, // methods
0, 0, // properties
0, 0, // enums/sets

// slots: signature, parameters, type, tag, flags
10, 9, 9, 9, 0x08,

0 // eod
};

static const char qt_meta_stringdata_myWidget[] = {
"myWidget\0\0processInput()\0"
};

const QMetaObject myWidget::staticMetaObject = {
{ &QWidget::staticMetaObject, qt_meta_stringdata_myWidget,
qt_meta_data_myWidget, 0 }
};

const QMetaObject *myWidget::metaObject() const
{
return &staticMetaObject;
}

void *myWidget::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_myWidget))
return static_cast<void*>(const_cast<myWidget*>(this));
return QWidget::qt_metacast(_clname);
}

int myWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QWidget::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: processInput(); break;
}
_id -= 1;
}
return _id;
}


i dont know how to output the errors to a file so here is the image

http://us.share.geocities.com/dymlg/1.bmp

jacek
17th July 2006, 01:02
kay, i deleted everything in the folder, except main.cpp. Then i did qmake -project then qmake and then make.
Then it should work, unless your project is located in "qt" directory (in such case you must add "TARGET += something" to your .pro file).


Now the error is in the moc file
All moc files correct. The error must be in some other place.


i dont know how to output the errors to a file so here is the image
Just cut & paste them. If you are using windows console, you can find cut & paste tools after you left-click the icon in the top-left corner of the window.


http://us.share.geocities.com/dymlg/1.bmp
"This page is not available."

You can post images here --- just click "Manage Attachements" button below the editor, but please don't post BMPs (even MS Paint can save images as PNGs or GIFs).

awnjoor
17th July 2006, 01:28
>>Then it should work, unless your project is located in "qt" directory (in such case you must add "TARGET += something" to your .pro file)

no, my project is not located in qt directory.

here is the error


In file included from main.cpp:6:
release/main.moc:38: error: `myWidget' has not been declared
release/main.moc:43: error: `myWidget' has not been declared
release/main.moc:44: error: non-member function `const QMetaObject* metaObject()
' cannot have `const' method qualifier
release/main.moc:48: error: `myWidget' has not been declared
release/main.moc: In function `void* qt_metacast(const char*)':
release/main.moc:52: error: `myWidget' has not been declared
release/main.moc:52: error: expected `>' before '*' token
release/main.moc:52: error: expected `(' before '*' token
release/main.moc:52: error: expected primary-expression before '>' token
release/main.moc:52: error: invalid use of `this' in non-member function
release/main.moc:52: error: expected `)' before ';' token
release/main.moc:53: error: cannot call member function `virtual void* QWidget::
qt_metacast(const char*)' without object
release/main.moc: At global scope:
release/main.moc:56: error: `myWidget' has not been declared
release/main.moc: In function `int qt_metacall(QMetaObject::Call, int, void**)':

release/main.moc:58: error: cannot call member function `virtual int QWidget::qt
_metacall(QMetaObject::Call, int, void**)' without object
release/main.moc:63: error: `processInput' undeclared (first use this function)
release/main.moc:63: error: (Each undeclared identifier is reported only once fo
r each function it appears in.)
mingw32-make[1]: *** [release\main.o] Error 1
mingw32-make[1]: Leaving directory `C:/Thesis/temp'
mingw32-make: *** [release-all] Error 2

jacek
17th July 2006, 01:38
In file included from main.cpp:6:
Move #include "main.moc" directive to the end of file.

awnjoor
17th July 2006, 01:48
::bows down::

thank you all. now jacek would you care to explain why i have to move the moc directive down

jacek
17th July 2006, 01:56
why i have to move the moc directive down
Because main.moc contains implementation of myWidget methods (which were added by Q_OBJECT macro) and in C++ you have to place method implementation after corresponding class definition.

awnjoor
17th July 2006, 02:39
sigh, im trying to do the custom slot/signal again but it is not working. here is the code


#include<QTableWidgetItem>
#include<QApplication>
#include<QWidget>
#include<QPushButton>
#include<QLabel>
#include<QFont>
#include<QLineEdit>
#include<QTableWidget>
#include<QVBoxLayout>
#include<QHBoxLayout>
#include<QStringList>
#include<QtSql/QSqlDatabase>
#include<QtSql/QSqlQuery>
#include<QString>
#include<QObject>

class myWidget:public QWidget{
Q_OBJECT

public:
myWidget(QWidget *parent=0);

private slots:
void processInput();

private:
QLabel *displayItem;
QLineEdit *itemnumber;
};

myWidget::myWidget(QWidget *parent)
:QWidget(parent)
{
setWindowState(Qt::WindowFullScreen);

QLabel *title = new QLabel;
title->setFont(QFont("Verdana", 30, 0));
title->setText("title");
title->setAlignment(Qt::AlignHCenter);

QLabel *item=new QLabel;
item->setFont(QFont("verdana", 15, QFont::Bold));
item->setText("Item");

displayItem=new QLabel;
//displayItem->setFont(QFont("verdana", 15, QFont::Bold));
//displayItem->setText("asdf");

itemnumber=new QLineEdit;
itemnumber->setMaxLength(10);

QLabel *quantity=new QLabel;
quantity->setFont(QFont("verdana", 15, QFont::Bold));
quantity->setText("Quantity");

QLineEdit *quantitynumber=new QLineEdit;
quantitynumber->setMaxLength(10);

QStringList columnLabels;
columnLabels << "Item" << "#" << "TOTAL";

QTableWidget *tableWidget=new QTableWidget;
tableWidget->setRowCount(1);
tableWidget->setColumnCount(3);
tableWidget->setHorizontalHeaderLabels(columnLabels);
tableWidget->setColumnWidth(0, 250);
tableWidget->setColumnWidth(1, 30);
tableWidget->setColumnWidth(2, 100);

QHBoxLayout *hLeft1=new QHBoxLayout;
hLeft1->addWidget(item);
hLeft1->addWidget(itemnumber);

QHBoxLayout *hLeft2=new QHBoxLayout;
hLeft1->addWidget(quantity);
hLeft1->addWidget(quantitynumber);

QVBoxLayout *vLeft=new QVBoxLayout;
vLeft->addLayout(hLeft1);
vLeft->addLayout(hLeft2);

QHBoxLayout *hLeft=new QHBoxLayout;
hLeft->addLayout(vLeft);
hLeft->addStretch(0);

QVBoxLayout *mainLeft=new QVBoxLayout;
mainLeft->addWidget(displayItem);
mainLeft->addStretch(0);
mainLeft->addLayout(hLeft);
mainLeft->addStretch(0);

QHBoxLayout *mainBottom=new QHBoxLayout;
mainBottom->addLayout(mainLeft);
mainBottom->addWidget(tableWidget);

QVBoxLayout *mainLayout=new QVBoxLayout(this);
mainLayout->addWidget(title);
mainLayout->addSpacing(80);
mainLayout->addLayout(mainBottom);
setLayout(mainLayout);

itemnumber->setFocus();
//itemnumber->setText("asdf");

connect(itemnumber, SIGNAL(returnPressed()), this, SIGNAL(processInput()));

}

void myWidget::processInput(){
//QString text=itemnumber->text();
itemnumber->setText("asfd");
}

int main(int argc, char *argv[]){
QApplication app(argc, argv);
myWidget window;

window.show();
return app.exec();
}

#include "client.moc"

everything compiles fine, it just doesnt do the processInput() when i press enter in itemnumber lineedit.

EDIT:
it seems that item number is not emitting the returnPressed() signal because i tried replacing it with


connect(itemnumber, SIGNAL(returnPressed()), qApp, SIGNAL(quit()));

and when i pressed enter nothing happened.

jpn
17th July 2006, 07:51
The latter should be SLOT:


connect(itemnumber, SIGNAL(returnPressed()), this, SLOT(processInput()));

awnjoor
17th July 2006, 08:05
and i wonder how did i miss that one .. :o

thank you