[Solved] QApp.exec() runs class slot for every Button.



  • Hello. I'm writing an app with Qt 5.3.2 on VS 2013. Generally speaking the problem is that after launching program clicked() signal is called for every button that i create.

    I've found out that signal is emmited by exec() function. Here is my Call Stack
    @> qt_saper.exe!Board::QButton_Click() Line 12 C++
    qt_saper.exe!Board::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * a) Line 72 C++
    Qt5Cored.dll!QMetaObject::activate(QObject * sender, int signalOffset, int local_signal_index, void * * argv) Line 3683 C++
    Qt5Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 3548 C++
    Qt5Widgetsd.dll!QAbstractButton::clicked(bool t1) Line 298 C++
    Qt5Widgetsd.dll!QAbstractButtonPrivate::emitClicked() Line 544 C++
    Qt5Widgetsd.dll!QAbstractButtonPrivate::click() Line 536 C++
    Qt5Widgetsd.dll!QAbstractButton::timerEvent(QTimerEvent * e) Line 1287 C++
    Qt5Cored.dll!QObject::event(QEvent * e) Line 1223 C++
    Qt5Widgetsd.dll!QWidget::event(QEvent * event) Line 8371 C++
    Qt5Widgetsd.dll!QAbstractButton::event(QEvent * e) Line 1098 C++
    Qt5Widgetsd.dll!QPushButton::event(QEvent * e) Line 682 C++
    Qt5Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3499 C++
    Qt5Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3464 C++
    Qt5Cored.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event) Line 935 C++
    Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 237 C++
    Qt5Cored.dll!QEventDispatcherWin32Private::sendTimerEvent(int timerId) Line 624 C++
    Qt5Cored.dll!qt_internal_proc(HWND
    * hwnd, unsigned int message, unsigned int64 wp, int64 lp) Line 425 C++
    [External Code]
    Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 795 C++
    qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 80 C++
    Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 137 C++
    Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 212 C++
    Qt5Cored.dll!QCoreApplication::exec() Line 1188 C++
    Qt5Guid.dll!QGuiApplication::exec() Line 1484 C++
    Qt5Widgetsd.dll!QApplication::exec() Line 2745 C++
    qt_saper.exe!main(int argc, char * * argv) Line 28 C++
    qt_saper.exe!WinMain(HINSTANCE
    * instance, HINSTANCE
    * prevInstance, char * __formal, int cmdShow) Line 131 C++
    [External Code]@

    And here are fragments of code:

    Creating QApplication: (main.cpp)
    @Game *game2 = new Game();
    QApplication *a = new QApplication(argc, argv);
    game2->play();
    return a->exec();@

    Game::play(): (nothing special)
    @board = new Board();
    board->show();@

    Slot declaration (Board.h):
    @class Board : public QObject
    {
    Q_OBJECT
    private:
    ...
    public slots:
    void QButton_Click();@

    And Slot code and board::show():
    @void Board::QButton_Click()
    {
    QWidget *widget = new QWidget();
    widget->show();
    }
    void Board::show()
    {
    QWidget *widget = new QWidget();
    QGridLayout *layout = new QGridLayout();

    int i = 0;
    for (vector <Field*>::iterator it = fields.begin(); it != fields.end(); ++it)
    {
    QPushButton *but=new QPushButton();
    (*it)->show(but);
    layout->addWidget(but, i, i);
    QObject::connect(but, SIGNAL(clicked()), this, SLOT(QButton_Click()));

    i++;
    }
    widget->setLayout(layout);
    widget->show();

    }@

    To sum up: when I launch app 15 new widgets are generated. I've tried moving Qapp code to Game and Board but this doesn't help (as I thought before).


  • Moderators

    Hi, welcome to devnet.

    @
    Game *game2 = new Game();
    QApplication *a = new QApplication(argc, argv);
    game2->play();
    return a->exec();
    @
    This leaks memory. You also don't need any dynamic instance of QApplication. Simply do:
    @
    QApplication a(argc, argv);
    Game game2; //don't create QObjects before QApplication
    game2.play();
    return a.exec();
    @

    This also leaks memory as you don't give any parent to the widget and don't store the pointer anywhere:
    @
    void Board::QButton_Click()
    {
    QWidget *widget = new QWidget();
    widget->show();
    }
    @

    This is a memory leak too:
    @
    board = new Board();
    board->show();
    @

    And this one too:
    @
    void Board::show()
    {
    QWidget *widget = new QWidget();
    ...
    widget->show();
    }
    @

    Also, don't new objects in the show() method. This is called multiple times, e.g. when you minimize an app and get back again and some other occasions. The app can also receive spurious show events from OS. It is NOT called once. Don't ever assume that. If you need to create some resources do that in the constructor of the class, not in the show() method.

    What is class Field and what (*it)->show(but); does? It seems to be the only method that interacts with the button, at least in the code fragment you posted, so it is probably related to your problem.



  • Solved :) I'll mark in a minute. The problem was my misunderstanding of animateClick function (I know this is very stupid :))

    Thanks for pointing out memory leaks. I'll change it soon. About Board::show(): it was supposted to be my own function not connected with Qt. After your suggestion I will just change the name.


Log in to reply
 

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