4

I have just started developing using QtGUI and I have checked out some tutorials and documentation, and by what I've read this should work.

#define CONNECT QObject::connect

void test();
QPushButton *lpTestBtn;
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   QtProject w;
   w.show();

   lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
   CONNECT(lpTestBtn, SIGNAL(clicked()),qApp,SLOT(test()));

   return a.exec();
}

void test()
{
    lpTestBtn->setText("Hi");
}

But test() never gets called. Also, lpTestBtn is not null and is found correctly.

I have tried the following changes

CONNECT(lpTestBtn, SIGNAL(clicked()),qApp->activeWindow(),SLOT(test()));

CONNECT(lpTestBtn, SIGNAL(clicked()),w.window(),SLOT(test()));

I know I can just do QtProject::on_TestBtn_clicked(); but I'd like to get it working using CONNECT,SIGNAL and SLOT.

László Papp
  • 51,870
  • 39
  • 111
  • 135
user2920222
  • 197
  • 1
  • 2
  • 8
  • Do you get a connection warning or anything like this when you run the program? It does not look like "void test()" is declared as a slot in w.window() - its just a local function... – code_fodder May 24 '14 at 13:53

3 Answers3

4

The test function in your code is not a slot, nor does it belong to the Q(Core)Application class as you seem to have used it.

The best would be is to move that one line in the test function to the connection with the lambda syntax. This will require C++11 support, but that is in quite common use these days.

You would use the new shiny signal-slot syntax. This would spare you some headache for runtime issues in the future because they would appear at compilation-time.

Therefore, you would write something like this:

main.cpp

#include <QMainWindow>
#include <QApplication>
#include <QPushButton>

int main(int argc, char **argv)
{
   QApplication a(argc, argv);
   // Replace it with "QtProject".
   QMainWindow w;
   w.show();

   QPushButton * lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
   QObject::connect(lpTestBtn, &QPushButton::clicked, [=]() {
        lpTestBtn->setText("Hi");
   });

   return a.exec();
}

main.pro

TEMPLATE = app
TARGET = main
QT += widgets
CONFIG += c++11
SOURCES += main.cpp

Build and Run

qmake && make && ./main

Please also note that it is bad idea to create a global pointer for a QPushButton object. It not only leaks the memory, but you could have other issues, too.

László Papp
  • 51,870
  • 39
  • 111
  • 135
  • @user2920222: Also, it is a bad idea to create the gui elements outside your main window. QtProject is also bad name for the mainwindow. – László Papp May 24 '14 at 20:00
2

1) QApplication doesn't have a test() slot in it. You need to make your own class, inheriting QApplication, and give that class a test() slot. What you've done is create a regular function, which won't help.

2) You didn't check the return value of connect, which means you didn't see that it was giving you an error, which would probably have given you some clues.

Michael Kohne
  • 11,888
  • 3
  • 47
  • 79
  • `You need to make your own class` -> You can, but you do not need to. Inheriting QApplication for this is a bad idea IMHO. It is probably the OP misunderstood what was being done. People do not need to check the return value of connect in normal runtime scenario. It is usually only done for debugging, although not that much even then because there is usually a clear warning on the console. – László Papp May 24 '14 at 19:55
1

You can connect signals to the slots which are in classes derived from QObject so meta compiler can deduce slot calls. But your test() is global function. You have to put your slot function inside a class that derives from QObject and supports Q_OBJECT macro or define a lambda function ( with C++11 support) as Laszlo Papp showed.

Example:

// testwrapper.h
class TestWrapper : public QObject
{
   Q_OBJECT

   //...

   public slots:
     void test();

};


// main.cpp
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   QtProject w;
   w.show();

   QPushButton * lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
   TestWrapper tw;
   CONNECT( lpTestBtn, SIGNAL( clicked()),tw,SLOT( test()));

   return a.exec();
}
4pie0
  • 29,204
  • 9
  • 82
  • 118
  • 1) I wonder where the implementation is for the test slot. 2) I wonder why you left the original test method in. This code would not compile, and it would also have an unused test function, which is another error if warnings are turned into errors with a good compiler. – László Papp May 24 '14 at 19:59
  • @LaszloPapp ad 1) I suggest testwrapper.cpp ad 2) I am sure that in such case most of your own projects would not compile too – 4pie0 May 24 '14 at 20:10
  • 1) so main.cpp for the declaration, but testwrapper.cpp for the definition? Sounds strange. I would rather do tw.h and tw.cpp then instead, but I think there is no need for a separate source file here. 2) All my projects compile currently, thanks. :) You still have the superfluous `void test();` though. 3) I am not sure why you need `...` in the class here. – László Papp May 24 '14 at 20:16
  • @LaszloPapp I have added indications where the code should be put into – 4pie0 May 24 '14 at 20:19