Hi, I'm a 10+ year C++ programmer but n3wb to Qt...
I've successfully installed the Qt 4.5.2 SDK (MinGW g++) but, since I primarily use VC++, also installed the VS2008 plugin and built the Qt 4.5.2 sources for VC++ in a separate directory. After fixing some Environmental Values/Paths issues between the 2 Qt now works fine under both compilers/IDEs.
I've made some simple test programs to try out Qt, but noticed that my custom slots always gets called twice for a single signal - and it happens in both IDEs
In QtDesigner I add a signal/slot to a QPushButton where the Sender is the QPushButton (signal is clicked()) and the Receiver a custom slot (called on_pbAdd_clicked()) on my form class derived form QDialog.
Since QtDesigner does not automatically generate the slots anymore, I've declared the slots like this:
{
Q_OBJECT
public:
Dialog
(QWidget *parent
= 0, Qt
::WFlags flags
= 0);
~Dialog();
private:
Ui::DialogClass ui;
public slots:
virtual void on_pbAdd_clicked(void);
virtual void on_pbRemove_clicked(void);
};
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0, Qt::WFlags flags = 0);
~Dialog();
private:
Ui::DialogClass ui;
public slots:
virtual void on_pbAdd_clicked(void);
virtual void on_pbRemove_clicked(void);
};
To copy to clipboard, switch view to plain text mode
The slot is implemented like this:
void Dialog::on_pbAdd_clicked(void)
{
if(ui.leEdit->text().length() > 0) {
...
}
}
void Dialog::on_pbAdd_clicked(void)
{
if(ui.leEdit->text().length() > 0) {
...
}
}
To copy to clipboard, switch view to plain text mode
I've tried to debug the issue: When the button is clicked one of the void QMetaObject::activate(...) functions in qobject.cpp gets called, specifically:
void QMetaObject::activate(QObject *sender,
int from_signal_index,
int to_signal_index,
void **argv
) {
....
int count = connectionLists->at(signal).count();
for (int i = 0; i < count; ++i) {
const QObjectPrivate::Connection *c = &connectionLists->at(signal)[i];
...
receiver->qt_metacall
(QMetaObject::InvokeMetaMethod, method, argv ? argv
: empty_argv
);
...
}
...
}
void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
{
....
int count = connectionLists->at(signal).count();
for (int i = 0; i < count; ++i) {
const QObjectPrivate::Connection *c = &connectionLists->at(signal)[i];
...
receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
...
}
...
}
To copy to clipboard, switch view to plain text mode
The count variable is set to 2 from the call to connectionLists->at(signal).count();. This means the next for loopis executed twice - which causes the slot to be called twice in the receiver->qt_metacall() function call. This resolves to a call to Dialog::qt_metacall(...) that was generated by the moc, which looks like this:
int Dialog
::qt_metacall(QMetaObject::Call _c,
int _id,
void **_a
) {
_id
= QDialog::qt_metacall(_c, _id, _a
);
if (_id < 0)
return _id;
switch (_id) {
case 0: on_pbAdd_clicked(); break;
case 1: on_pbRemove_clicked(); break;
default: ;
}
_id -= 2;
}
return _id;
}
int Dialog::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QDialog::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: on_pbAdd_clicked(); break;
case 1: on_pbRemove_clicked(); break;
default: ;
}
_id -= 2;
}
return _id;
}
To copy to clipboard, switch view to plain text mode
The case 0 in the switch statement then calls my on_pbAdd_clicked() slot - which seems perfect. So everything seems to work fine, with the exception of that connectionLists->at(signal).count(); value that is returned, which result in the slot being called twice!
I am not yet familiar with the Qt code-base, so can anybody maybe help and maybe shed some light on this? How does one overcome this?
Thanx
Bookmarks