【问题标题】:Qt C++ connect QPushButton clickQt C++ 连接 QPushButton 点击
【发布时间】:2023-03-25 18:40:01
【问题描述】:

我刚刚开始使用 QtGUI 进行开发,并且查看了一些教程和文档,根据我所阅读的内容,这应该可以工作。

#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");
}

但是 test() 永远不会被调用。另外,lpTestBtn 不为空,并且被正确找到。

我尝试了以下更改

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

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

我知道我可以做 QtProject::on_TestBtn_clicked();但我想使用 CONNECT、SIGNAL 和 SLOT 让它工作。

【问题讨论】:

  • 运行程序时是否收到连接警告或类似情况?它看起来不像“void test()”被声明为 w.window() 中的一个插槽 - 它只是一个本地函数......

标签: c++ qt qtgui qtcore qt-signals


【解决方案1】:

您代码中的测试函数不是插槽,也不属于您似乎使用过的 Q(Core)Application 类。

最好的办法是将测试函数中的那一行移动到使用 lambda 语法的连接处。这将需要 C++11 支持,但现在这很常见。

您将使用the new shiny signal-slot syntax。这将使您在未来免于为运行时问题而头疼,因为它们会出现在编译时

因此,你会这样写:

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

构建并运行

qmake && make && ./main

还请注意,为 QPushButton 对象创建全局指针是个坏主意。它不仅会泄漏内存,而且您还可能遇到其他问题。

【讨论】:

  • @user2920222:另外,在主窗口之外创建 gui 元素也是个坏主意。 QtProject 对于主窗口来说也是个坏名字。
【解决方案2】:

1) QApplication 中没有test() 插槽。您需要创建自己的类,继承 QApplication,并给该类一个 test() 插槽。您所做的是创建一个常规函数,这无济于事。

2)你没有检查connect的返回值,这意味着你没有看到它给你一个错误,这可能会给你一些线索。

【讨论】:

  • You need to make your own class -> 你可以,但你不需要。恕我直言,为此继承 QApplication 是个坏主意。这可能是 OP 误解了正在做的事情。在正常的运行时场景中,人们不需要检查 connect 的返回值。它通常只用于调试,尽管即使那样也没有那么多,因为控制台上通常会有一个明确的警告。
【解决方案3】:

您可以将信号连接到派生自QObject 的类中的槽,因此元编译器可以推断槽调用。但是您的 test() 是全局函数。您必须将槽函数放在派生自 QObject 并支持 Q_OBJECT 宏的类中,或者像 Laszlo Papp 所示定义一个 lambda 函数(支持 C++11)。

例子:

// 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();
}

【讨论】:

  • 1) 我想知道测试槽的实现在哪里。 2)不知道你为什么把原来的测试方法留在里面。这段代码编译不出来,而且还有一个未使用的测试函数,如果用好的编译器把警告变成错误,那就是另一个错误了。
  • @LaszloPapp ad 1) 我建议 testwrapper.cpp ad 2) 我确信在这种情况下,您自己的大多数项目也不会编译
  • 1) 所以 main.cpp 用于声明,而 testwrapper.cpp 用于定义?听起来很奇怪。我宁愿做 tw.h 和 tw.cpp ,但我认为这里不需要单独的源文件。 2)我所有的项目目前都在编译,谢谢。 :) 你仍然有多余的void test();。 3) 我不知道你为什么需要... 上课。
  • @LaszloPapp 我已经添加了代码应该放入的指示
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多