从 Qt 中的信号调用成员函数的问题

Posted

技术标签:

【中文标题】从 Qt 中的信号调用成员函数的问题【英文标题】:Problem Calling member function from a signal in Qt 【发布时间】:2020-02-09 21:29:06 【问题描述】:

所以,我正在使用 Qt4 作为 GUI 框架在 C++ 中制作一个简单的计算器应用程序。 我以前使用过 Qt,但这次我使用的是 C++ 而不是 python。

现在我的项目中有三个文件,

ma​​in.cpp (调用和运行主 GUI 类的简单套件) window.cpp (包含实现 GUI 类和其他例程的文件套件。) header.h window.cpp 文件的模板。)

主要的 GUI 实现类称为 Ui_MainWindow

现在,这个类有一个名为handleButton的成员函数

我想做的是在clicked 事件发生时调用这个handlebutton 函数。 所以,我应该做的是将事件连接到插槽 (handlebutton) ,对吗??

按钮的名称是pushButton,如上所述,handlebutton 是一个成员函数 班级Ui_MainWindow

这里是后面应该实现的 sn-p:

QObject::connect( pushButton , SIGNAL (clicked()), this , handleButton );

那么,当这个点击事件发生时this->handleButton应该被调用,对吧??

但我收到一个错误:

error: no matching function for call to ‘QObject::connect(QPushButton*&, const char [11], Ui_MainWindow*, void (&)())
QObject::connect( pushButton , SIGNAL (clicked()), this , handleButton );

我尝试将成员 func 设为静态并尝试了所有我能想到的方法,但它似乎对我不起作用。

请指导我如何解决此问题。

文件:window.cpp

#include <iostream>
#include <window.h>

void Ui_MainWindow::handleButton ( void ) 
    std::cout << "Hi this is  MEeeeee!.\n";
    return;


void Ui_MainWindow::setupUi(QMainWindow *MainWindow) 
        if (MainWindow->objectName().isEmpty())
            MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
        MainWindow->resize(423, 410);
        MainWindow->setMaximumSize(QSize(700, 600));
        centralwidget = new QWidget(MainWindow);
        centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
        gridLayout_2 = new QGridLayout(centralwidget);
        gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2"));
        label_2 = new QLabel(centralwidget);
        label_2->setObjectName(QString::fromUtf8("label_2"));
        label_2->setMaximumSize(QSize(16777215, 41));
        QFont font;
        font.setPointSize(20);
        label_2->setFont(font);
        label_2->setAlignment(Qt::AlignCenter);

        gridLayout_2->addWidget(label_2, 0, 0, 1, 1);

        label = new QLabel(centralwidget);
        label->setObjectName(QString::fromUtf8("label"));
        QFont font1;
        font1.setFamily(QString::fromUtf8("Roboto"));
        font1.setPointSize(22);
        label->setFont(font1);
        label->setLayoutDirection(Qt::RightToLeft);
        label->setStyleSheet(QString::fromUtf8("background-color: rgb(179, 179, 179);\n""border-radius:4px;\n""padding:20px;"));
        label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);

        gridLayout_2->addWidget(label, 1, 0, 1, 1);

        horizontalLayout = new QHBoxLayout();
        horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
        gridLayout = new QGridLayout();
        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
        pushButton = new QPushButton(centralwidget);
        pushButton->setObjectName(QString::fromUtf8("pushButton"));
        pushButton->setMinimumSize(QSize(0, 60));
        pushButton->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton, 0, 0, 1, 1);

        pushButton_2 = new QPushButton(centralwidget);
        pushButton_2->setObjectName(QString::fromUtf8("pushButton_2"));
        pushButton_2->setMinimumSize(QSize(0, 60));
        pushButton_2->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_2, 0, 1, 1, 1);

        pushButton_3 = new QPushButton(centralwidget);
        pushButton_3->setObjectName(QString::fromUtf8("pushButton_3"));
        pushButton_3->setMinimumSize(QSize(0, 60));
        pushButton_3->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_3, 0, 2, 1, 1);

        pushButton_4 = new QPushButton(centralwidget);
        pushButton_4->setObjectName(QString::fromUtf8("pushButton_4"));
        pushButton_4->setMinimumSize(QSize(0, 60));
        pushButton_4->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_4, 1, 0, 1, 1);

        pushButton_5 = new QPushButton(centralwidget);
        pushButton_5->setObjectName(QString::fromUtf8("pushButton_5"));
        pushButton_5->setMinimumSize(QSize(0, 60));
        pushButton_5->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_5, 1, 1, 1, 1);

        pushButton_6 = new QPushButton(centralwidget);
        pushButton_6->setObjectName(QString::fromUtf8("pushButton_6"));
        pushButton_6->setMinimumSize(QSize(0, 60));
        pushButton_6->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_6, 1, 2, 1, 1);

        pushButton_7 = new QPushButton(centralwidget);
        pushButton_7->setObjectName(QString::fromUtf8("pushButton_7"));
        pushButton_7->setMinimumSize(QSize(0, 60));
        pushButton_7->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_7, 2, 0, 1, 1);

        pushButton_8 = new QPushButton(centralwidget);
        pushButton_8->setObjectName(QString::fromUtf8("pushButton_8"));
        pushButton_8->setMinimumSize(QSize(0, 60));
        pushButton_8->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_8, 2, 1, 1, 1);

        pushButton_9 = new QPushButton(centralwidget);
        pushButton_9->setObjectName(QString::fromUtf8("pushButton_9"));
        pushButton_9->setMinimumSize(QSize(0, 60));
        pushButton_9->setMaximumSize(QSize(60, 60));

        gridLayout->addWidget(pushButton_9, 2, 2, 1, 1);


        horizontalLayout->addLayout(gridLayout);

        verticalLayout = new QVBoxLayout();
        verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
        verticalLayout->setContentsMargins(0, -1, -1, -1);
        pushButton_15 = new QPushButton(centralwidget);
        pushButton_15->setObjectName(QString::fromUtf8("pushButton_15"));
        pushButton_15->setMinimumSize(QSize(0, 127));
        pushButton_15->setMaximumSize(QSize(60, 152));

        verticalLayout->addWidget(pushButton_15);

        pushButton_10 = new QPushButton(centralwidget);
        pushButton_10->setObjectName(QString::fromUtf8("pushButton_10"));
        pushButton_10->setMinimumSize(QSize(0, 60));
        pushButton_10->setMaximumSize(QSize(60, 60));

        verticalLayout->addWidget(pushButton_10);


        horizontalLayout->addLayout(verticalLayout);

        verticalLayout_3 = new QVBoxLayout();
        verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3"));
        pushButton_12 = new QPushButton(centralwidget);
        pushButton_12->setObjectName(QString::fromUtf8("pushButton_12"));
        pushButton_12->setMinimumSize(QSize(0, 60));
        pushButton_12->setMaximumSize(QSize(60, 60));

        verticalLayout_3->addWidget(pushButton_12);

        pushButton_11 = new QPushButton(centralwidget);
        pushButton_11->setObjectName(QString::fromUtf8("pushButton_11"));
        pushButton_11->setMinimumSize(QSize(0, 60));
        pushButton_11->setMaximumSize(QSize(60, 60));

        verticalLayout_3->addWidget(pushButton_11);

        pushButton_14 = new QPushButton(centralwidget);
        pushButton_14->setObjectName(QString::fromUtf8("pushButton_14"));
        pushButton_14->setMinimumSize(QSize(0, 60));
        pushButton_14->setMaximumSize(QSize(60, 60));

        verticalLayout_3->addWidget(pushButton_14);


        horizontalLayout->addLayout(verticalLayout_3);

        verticalLayout_2 = new QVBoxLayout();
        verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
        pushButton_17 = new QPushButton(centralwidget);
        pushButton_17->setObjectName(QString::fromUtf8("pushButton_17"));
        pushButton_17->setMinimumSize(QSize(0, 127));
        pushButton_17->setMaximumSize(QSize(60, 152));

        verticalLayout_2->addWidget(pushButton_17);

        pushButton_13 = new QPushButton(centralwidget);
        pushButton_13->setObjectName(QString::fromUtf8("pushButton_13"));
        pushButton_13->setMinimumSize(QSize(0, 60));
        pushButton_13->setMaximumSize(QSize(60, 60));

        verticalLayout_2->addWidget(pushButton_13);


        horizontalLayout->addLayout(verticalLayout_2);


        gridLayout_2->addLayout(horizontalLayout, 2, 0, 1, 1);

        MainWindow->setCentralWidget(centralwidget);

        retranslateUi(MainWindow);

        QObject::connect( pushButton , SIGNAL (clicked()), this , handleButton );

        //this->handleButton(); 
       // setupU

void Ui_MainWindow::retranslateUi(QMainWindow *MainWindow)

        MainWindow->setWindowTitle(QApplication::translate("MainWindow", "DD | Calc", 0, QApplication::UnicodeUTF8));
        label_2->setText(QApplication::translate("MainWindow", "DD - Calc", 0, QApplication::UnicodeUTF8));
        label->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8));
        pushButton->setText(QApplication::translate("MainWindow", "1", 0, QApplication::UnicodeUTF8));
        pushButton_2->setText(QApplication::translate("MainWindow", "2", 0, QApplication::UnicodeUTF8));
        pushButton_3->setText(QApplication::translate("MainWindow", "3", 0, QApplication::UnicodeUTF8));
        pushButton_4->setText(QApplication::translate("MainWindow", "4", 0, QApplication::UnicodeUTF8));
        pushButton_5->setText(QApplication::translate("MainWindow", "5", 0, QApplication::UnicodeUTF8));
        pushButton_6->setText(QApplication::translate("MainWindow", "6", 0, QApplication::UnicodeUTF8));
        pushButton_7->setText(QApplication::translate("MainWindow", "7", 0, QApplication::UnicodeUTF8));
        pushButton_8->setText(QApplication::translate("MainWindow", "8", 0, QApplication::UnicodeUTF8));
        pushButton_9->setText(QApplication::translate("MainWindow", "9", 0, QApplication::UnicodeUTF8));
        pushButton_15->setText(QApplication::translate("MainWindow", "=", 0, QApplication::UnicodeUTF8));
        pushButton_10->setText(QApplication::translate("MainWindow", "0", 0, QApplication::UnicodeUTF8));
        pushButton_12->setText(QApplication::translate("MainWindow", "-", 0, QApplication::UnicodeUTF8));
        pushButton_11->setText(QApplication::translate("MainWindow", "+", 0, QApplication::UnicodeUTF8));
        pushButton_14->setText(QApplication::translate("MainWindow", "/", 0, QApplication::UnicodeUTF8));
        pushButton_17->setText(QApplication::translate("MainWindow", "C", 0, QApplication::UnicodeUTF8));
        pushButton_13->setText(QApplication::translate("MainWindow", "x", 0, QApplication::UnicodeUTF8));
     // retranslateUi

文件:window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QGridLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QMainWindow>
#include <QtGui/QPushButton>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>
#include <iostream>

QT_BEGIN_NAMESPACE

class Ui_MainWindow


private slots:
    void handleButton();

public:

    QWidget *centralwidget;
    QGridLayout *gridLayout_2;
    QLabel *label_2;
    QLabel *label;
    QHBoxLayout *horizontalLayout;
    QGridLayout *gridLayout;
    QPushButton *pushButton;
    QPushButton *pushButton_2;
    QPushButton *pushButton_3;
    QPushButton *pushButton_4;
    QPushButton *pushButton_5;
    QPushButton *pushButton_6;
    QPushButton *pushButton_7;
    QPushButton *pushButton_8;
    QPushButton *pushButton_9;
    QVBoxLayout *verticalLayout;
    QPushButton *pushButton_15;
    QPushButton *pushButton_10;
    QVBoxLayout *verticalLayout_3;
    QPushButton *pushButton_12;
    QPushButton *pushButton_11;
    QPushButton *pushButton_14;
    QVBoxLayout *verticalLayout_2;
    QPushButton *pushButton_17;
    QPushButton *pushButton_13;

    void setupUi(QMainWindow *MainWindow);
    void retranslateUi(QMainWindow *MainWindow);
;




// namespace Ui 
//     class MainWindow: public Ui_MainWindow ;
//  // namespace Ui


QT_END_NAMESPACE

#endif // WINDOW_H

文件:ma​​in.cpp

#include <QApplication>
#include <QtCore/QVariant>
#include <iostream>
#include <window.h>

int main(int argc, char **argv)

 QApplication app (argc, argv);

 QMainWindow window;

 Ui_MainWindow win;

 win.setupUi(&window);

 window.show();

 return app.exec();

【问题讨论】:

【参考方案1】:

连接的正确语法是这样的:

QObject::connect( pushButton , SIGNAL (clicked()), this , SLOT(handleButton()));

或新的函数指针语法(在 Qt5 中):

QObject::connect( pushButton , &QPushButton::clicked, this , Ui_MainWindow::handleButton);

但是你在那里做错了,你不应该修改类 UI_FormName,因为当你在 Designer 中修改 .ui 文件时,该文件很可能会重新生成,请查看文档 here 以了解如何您可以在代码中使用uic 生成的代码。

LE:谢谢@MathiasSchmid 我没有注意到缺少宏,Q_OBJECT 宏需要添加到您的类的私有部分中才能使信号和插槽工作。

【讨论】:

我试过这个:QObject::connect( pushButton , &amp;QPushButton::clicked(), this , Ui_MainWindow::handleButton); 但我得到了这个错误:error: cannot call member function ‘void QAbstractButton::clicked(bool)’ without object QObject::connect( pushButton , &amp;QPushButton::clicked(), this , Ui_MainWindow::handleButton); 类定义 Ui_MainWindow 中缺少 Q_OBJECT 宏。并且UI_MainWindow 必须派生自QObject 或从QObject 派生的另一个类,然后它才能工作。 好的,所以我从 QObject 派生了类 Ui 类,并且代码确实可以编译,但现在我在运行时遇到错误:Object::connect: No such slot QObject::handleButton() 您需要Q_OBJECT 宏来在运行时解析信号槽连接。只需将 Q_OBJECT 作为 Ui_MainWindow 类定义的第一行。 更多关于 QOBJECT 宏的英特尔 here.

以上是关于从 Qt 中的信号调用成员函数的问题的主要内容,如果未能解决你的问题,请参考以下文章

QT 信号和槽函数签名

类型擦除成员函数指针的“正确”方法是啥?

从 C++ 中的多个线程调用 Qt 中小部件类的信号函数是不是安全?

QT学习小结之信号与槽

在Linux下使用QT开发,为啥总提示成员函数没有定义呢?

Qt中的QSettings这个类有.value这个成员函数吗?