[solved] Trouble with Q_OBJECT Signals & Slots



  • Hello BoysNGirls,

    I have a problem with a dialog window which I have created. I thought I already had solved all related problems, but seems not.

    I have a small dialog window with a few QPushButtons and QLabels. Further on I created an own SLOT which I called deleteItem():
    @
    #pragma once

    #include <QDialog>
    #include <QString>
    #include <QtGui/QLineEdit>
    #include <QtGui/QLabel>
    #include <QtGui/QGridLayout>
    #include <QtGui/QHBoxLayout>
    #include <QtGui/QDialogButtonBox>
    #include <QtGui/QPushButton>
    #include "DataItem.h"

    class DlgDataDetails : public QDialog
    {
    //Q_OBJECT

    public:
    DlgDataDetails(const QString &title;, QWidget *parent, const DataItem * pPI);
    ~DlgDataDetails(void);

    QPushButton *btnOK, *btnAbort, *btnDelete;
    QLabel *lblID, *lblName, *lblCategorie;
    QLineEdit *leID, *leName, *leCategorie;
    QDialogButtonBox *btnHBox;
    QHBoxLayout *topLO;
    QGridLayout *leftLO;
    QGridLayout *rightLO;

    private slots:
    

    void deleteItem();
    };
    @

    @
    #include "DlgDataDetails.h"

    DlgDataDetails::DlgDataDetails(const QString &title;, QWidget *parent, const DataItem * pPI)
    : QDialog(parent)
    {
    topLO = new QHBoxLayout;
    leftLO = new QGridLayout;
    rightLO = new QGridLayout;

    lblID = new QLabel(tr("ID"));
    leID = new QLineEdit;
    leID->setText(tr("%1").arg(pPI->getDataID()));
    leID->setReadOnly(true);
    lblID->setBuddy(leID);

    lblName = new QLabel(tr("Name"));
    leName = new QLineEdit;
    leName->setText(tr("%1").arg(pPI->getDataName()));
    lblName->setBuddy(leName);

    lblCategorie = new QLabel(tr("Categorie"));
    leCategorie = new QLineEdit;
    leCategorie->setText(tr("%1").arg(pPI->getDataCat()));
    lblCategorie->setBuddy(leCategorie);

    leftLO->addWidget(lblID, 0, 0);
    leftLO->addWidget(leID, 0, 1);
    leftLO->addWidget(lblName, 1, 0);
    leftLO->addWidget(leName, 1, 1);
    leftLO->addWidget(lblCategorie, 2, 0);
    leftLO->addWidget(leCategorie, 2, 1);
    

    btnOK = new QPushButton(tr("OK"));
    btnOK->setObjectName("btnOK");
    btnOK->setDefault(true);

    btnAbort = new QPushButton(tr("Abort"));
    btnAbort->setObjectName("btnAbort");
    btnAbort->setCheckable(true);

    btnDelete = new QPushButton(tr("Delete"));
    btnDelete->setObjectName("btnDelete");
    btnDelete->setCheckable(true);

    connect(btnOK, SIGNAL(clicked(bool)), this, SLOT(accept()));

    connect(btnAbort, SIGNAL(clicked(bool)), this, SLOT(close()));

    connect(btnDelete, SIGNAL(clicked()), this, SLOT(deleteItem()));

    /// \Vertical Buttons on the right
    btnHBox = new QDialogButtonBox(Qt::Horizontal);
    btnHBox->addButton(btnOK, QDialogButtonBox::ActionRole);
    btnHBox->addButton(btnAbort, QDialogButtonBox::ActionRole);
    btnHBox->addButton(btnDelete, QDialogButtonBox::ActionRole);

    rightLO->addWidget(btnHBox);

    topLO->addLayout(this->leftLO);
    topLO->addLayout(this->rightLO);
    // last set Window title
    setLayout(topLO);
    setWindowTitle(title);
    }

    void DlgDataDetails::deleteItem()
    {
    // never reached here
    }

    DlgDataDetails::~DlgDataDetails(void)
    {
    }
    @
    My problem is following: According to the Qt-documentation "All classes that contain signals or slots must mention Q_OBJECT at the top of their declaration...", but when I have Q_OBJECT in my Headerfile line 15, I got following link-error:
    [quote] 1> Creating library M:\Eigene Dateien\project\build-vs9\DataController\Debug\DataController.lib and object M:\Eigene Dateien\project\build-vs9\DataController\Debug\DataController.exp
    1>DlgDataDetails.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall DlgDataDetails::metaObject(void)const " (?metaObject@DlgDataDetails@@UBEPBUQMetaObject@@XZ)
    1>DlgDataDetails.obj : error LNK2001: unresolved external symbol "public: virtual void * __thiscall DlgDataDetails::qt_metacast(char const *)" (?qt_metacast@DlgDataDetails@@UAEPAXPBD@Z)
    1>DlgDataDetails.obj : error LNK2001: unresolved external symbol "public: virtual int __thiscall DlgDataDetails::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@DlgDataDetails@@UAEHW4Call@QMetaObject@@HPAPAX@Z)
    1>DlgDataDetails.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const DlgDataDetails::staticMetaObject" (?staticMetaObject@DlgDataDetails@@2UQMetaObject@@B) [/quote]

    Otherwise my SLOT (deleteItem() --> source, line 49) is not recignized.
    So what shall I do? What is the problem here? Thanks in advise.

    Cheers Huck



  • Add Q_OBJECT and re-run qmake, rebuild your project.
    Are you using QtCreator? If not, make sure moc is called for every file containing Q_OBJECT.



  • Do you clean your cache ? Clean and build ?



  • No, I still use VS. The project is generated with cmake.
    How do I make sure that moc is started for each file that macro is used?

    I just tried that building & cleaning stuff:
    When I rebuild (clean&build; is the same as well) my solution, everything proceeds fine. But on execution i get this error: !http://img194.imageshack.us/img194/8773/errorr6034.png(Error R6034)!



  • If the linker errors are gone moc most probably is invoked correctly (you should see calls to moc.exe in your build log). The meta object compiler is responsible for generating and adding code to Q_OBJECT classes which is needed by Qt's introspection system.

    As for your second error see "here":http://goo.gl/AQvS0.

    bq. Rebuild your application with a manifest. Building an application with Visual Studio automatically puts the manifest into the resulting EXE or DLL file. If you are building at the command line, use the mt.exe tool to add the manifest as a resource.

    There is also an addin for "Visual Studio":http://qt.nokia.com/downloads/visual-studio-add-in. Or just use "QtCreator":http://qt.nokia.com/products/developer-tools as all the other cool kids out there ;-)



  • [quote author="Lukas Geyer" date="1311009096"]If the linker errors are gone ...[/quote]

    No, they aren't. They're only gone, when I REbuild my solution. But when I only build, I got the same Link2001 error again.

    [quote author="Lukas Geyer" date="1311009096"]Or just use "QtCreator":http://qt.nokia.com/products/developer-tools as all the other cool kids out there ;-)[/quote]
    I would like to, but I was not able to load my project in QtCreator. According to http://developer.qt.nokia.com/forums/viewthread/7419/P30 I should open CMakeList.txt with QtCreator: I have done this, I entered a build folder, my cmake path, and everything finished properly. Now I have in QtCreator that solution which includes a CMakeList.txt only?
    All the projects in my solution are missing.



  • This is strange.

    To be honest I'm not an expert in Qt with cmake. But I can tell you if the linker complains about missing symbols there are usually problems with Q_OBJECT header files not beeing mocced or linked.

    "Using CMake to Build Qt Projects":http://developer.qt.nokia.com/quarterly/view/using_cmake_to_build_qt_projects
    "Qt Creator: Setting Up a CMake Project":http://doc.qt.nokia.com/qtcreator-snapshot/creator-project-cmake.html



  • Clarification: I have an initial project source folder, which includes a CMakeList.txt. I opened this with CMake and generated a Visual Studio 2008 project ("build-vs"). Then I was developing some stuff in VS (based on that initial folder).
    Now, I would like to continue developing with QtCreator:
    --> 1: I can open the initial project folders CMakeList.txt file via QtCreator as mentioned above, but I had much more specific project regarding options when I generated those with CMake directly. Nevertheless, starting from that initial folder, I ought to include those stuff which I already had developed manually later on..
    --> 2: So I would prefer to open the other CMakeList.txt which is located in my build-vs folder; I was developing in there with VS. But when I open that CMakeList.txt with QtCreator just a plain text opens. No Qt's CMake Wizard as in the tutorial
    @

    This is the CMakeCache file.

    For build in directory: m:/Eigene Dateien/project/build-vs9

    It was generated by CMake: C:/Program Files/CMake 2.8/CMake 2.8/bin/cmake.exe

    You can edit this file to change values found and used by cmake.

    If you do not want to change any of the values, simply exit the editor.

    If you do want to change a value, simply edit, save, and exit the editor.

    The syntax for the file is as follows:

    KEY:TYPE=VALUE

    KEY is the name of a variable in the cache.

    TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.

    VALUE is the current value for the KEY.

    ########################

    EXTERNAL cache entries

    ########################
    #......and lots of stuff
    @
    I assume I cant open the CMakeList.txt from the VS folder, because it has VS specific stuff in it?
    I hope I got this across to you

    Cheers Huck



  • Ok, my problem is semi-solved!
    When I moc those headers manually, the link error is gone. You were right, it was a moc problem:
    @moc.exe <HaderWithQOBJECT>.h -o moc_<HaderWithQOBJECT>.cxx@
    Add exisiting Item--> moc_<HaderWithQOBJECT>.cxx to project ==> No link errror.

    It is annoying to run this manually for each header and everytime I change something. Isn't there some automation in VS for MOCs?

    Cheers Huck



  • If you use the MSVS plug-in it is all done automatically.

    [quote author="Lukas Geyer" date="1311009096"]There is also an addin for "Visual Studio":http://qt.nokia.com/downloads/visual-studio-add-in. Or just use "QtCreator":http://qt.nokia.com/products/developer-tools as all the other cool kids out there ;-)[/quote]



  • Not in my project.

    in that project I have headers (lets say ClassWithQObject.h) with Q_OBJECT set, which where already in that project. On each build, I can read
    @
    1> Generating...
    1> moc_ClassWithQObject.cxx
    1> Compiling...
    1> moc_ClassWithQObject.cxx
    1> ... etc...
    @
    But in those headers, which belong to classes I have created by myself, I only can read
    @
    1> Compiling...
    1> moc_ClassWithQObject.cxx
    1> ... etc...
    @
    without an explicit generation. (I have generated them with the batch-script see above in the thread).

    For instance I changed one of the return value (in a class I have generated by myself) from quint32 to void. The corresponding moc is not generated this time; instead the old moc_DlgDataDetails.cxx (with the old return value quint32 for that function) is used.
    @
    1>------ Build started: Project: MyProject, Configuration: Debug Win32 ------
    1>Compiling...
    1>moc_DlgDataDetails.cxx
    1>.\moc_DlgDataDetails.cxx(66) : error C2440: 'initializing' : cannot convert from 'void' to 'quint32'
    @

    And of course when I trigger the moc for that class explicit manually, the error is gone.

    I hope I could make everything clear. Yes, I have the Qt-Addon installed for VS 2008.

    Thanx for any help and hints..

    Huck



  • did you create the VS project with the VS plugin?
    if yes, try removing the header file from the project and add it again.



  • No I have generated the project with cmake for Visual Studio 2008.
    Then I opened it to develop further functions.
    The Qt-addon for VS is installed, BUT grey. I only can choose Launch Linguis and Creator, Open *.pro and Qt Options. All others were greyed, thus not choosable.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.