【问题标题】:Unable to connect signal to a function inside main()无法将信号连接到 main() 中的函数
【发布时间】:2013-05-24 12:05:10
【问题描述】:

我知道要在类中使用 Qt 的信号和槽机制,该类必须包含 Q_OBJECT 宏,但我试图在 main() 中使用信号和槽,而不使用任何类。

到目前为止,这是我的代码:

#include <QApplication>
#include <QWidget>
#include <QTextEdit>
#include <QtGui>

void saveText();

int main(int argv, char **args)
 {
    QApplication app(argv, args);
    QTextEdit textEdit;
    QPushButton saveButton("Save!");
    QPushButton exitButton("Exit!");
    QObject::connect(&exitButton,SIGNAL(clicked()),qApp,SLOT(quit()));
    QObject::connect(&saveButton,SIGNAL(clicked()),qApp,SLOT(saveText()));

    QVBoxLayout vlyt;
    vlyt.addWidget(&textEdit);
    vlyt.addWidget(&exitButton);
    vlyt.addWidget(&saveButton);

    QWidget mainWindow;
    mainWindow.setLayout(&vlyt);
    mainWindow.show();

    return app.exec();
}

void saveText()
{
    exit(0);
}

这是生成的 GUI 窗口:

从上面的代码中,退出按钮连接到quit(),这是一个Qt函数,点击它就可以工作。分配给函数saveText() 的保存按钮配置为退出,但不退出。

请告诉我我在理解 Qt 中的信号和槽方面哪里出了问题。

【问题讨论】:

  • connect(&saveButton, &QPushButton::clicked, [](){saveText();}); // qt5.9.6

标签: c++ qt user-interface qt4


【解决方案1】:

Qt4...

从 QObject 或其子类之一继承的所有类(例如, QWidget) 可以包含信号和槽。1

因此,您不能使用位于QObject children 之外的插槽。

您可以将信号连接到派生自QObject 的类中的插槽。将您的插槽放在一个单独的 .h/.cpp 文件中的类中:

class MyClass : public QObject
{
   Q_OBJECT

   ...

   public slots:
     void saveText();

};

根据 Qt5:New Signal Slot Syntax in Qt 5。您可以连接到这些类型的全局函数。 (感谢@thuga 的 cmets

【讨论】:

  • 那么为什么退出按钮可以工作?类中的 quit() 函数是否继承自 QObject ?
  • quit()qApp 中的一个槽,qApp 是一个派生自QObject 的对象。
  • 你可以在 Qt5 中做这样的事情
  • @MM。 Here 上面写着The new syntax can even connect to functions, not just QObjects。也可以看this问题。
  • @thuga,非常感谢!希望您通过编辑我的代码来演示它来给出答案,但无论如何,这些链接很有帮助
【解决方案2】:

我只是在这里举个例子。

ma​​in.cpp:

#include <QCoreApplication>
#include <iostream>
#include <QObject>
#include "siggen.h"

void handler(int val){
  std::cout << "got signal: " << val << std::endl;
}

int main(int argc, char *argv[])
{
  SigGen siggen;
  QObject::connect(&siggen, &SigGen::sgAction, handler);
  siggen.action();

  QCoreApplication a(argc, argv);
  std::cout << "main prog start" << std::endl;

  return a.exec();
}

siggen.h:

#ifndef SIGGEN_H
#define SIGGEN_H

#include <QObject>

class SigGen : public QObject
{
  Q_OBJECT

public:
  explicit SigGen(QObject *parent = 0);
  void action(void);

signals:
  void sgAction(int value);
};

#endif // SIGGEN_H

siggen.cpp:

#include "siggen.h"

SigGen::SigGen(QObject *parent) : QObject(parent)
{}

void SigGen::action()
{
  emit sgAction(42);
}

【讨论】:

    【解决方案3】:
    QObject::connect(&saveButton, &QPushButton::clicked, [](){saveText();});  // qt5.9.6
    

    或如masoud's answer中所述

    QObject::connect(&saveButton, &QPushButton::clicked, saveText);  // qt5.9.6
    

    【讨论】:

    • 这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
    • “这没有提供问题的答案。” - 什么问题?
    • 您的答案很简短,应该是评论,而不是答案。请参考 StackOverflow 的指南。
    • @AashishJ “你的答案很短,应该是评论” - 答案很短并不意味着它应该是评论,这显然是一种尝试回答这个问题,它是否正确不是 LQP 审查队列的工作,这就是 up/downvoting 的目的。
    【解决方案4】:

    可以将信号连接到主函数内部的函数。 这已经在 Qt5.15 中进行了测试。这是一个简单的例子,QPushButton 'Clicked' 信号用于触发一个函数(这里我使用了 lamda,但也可以使用常规函数)。

    int main(int argc, char *argv[])
    {
        // Created QApplication
        QApplication a(argc, argv);
        
        // Created the splashscreen(which is QObject)
        QPixmap pixmap(":/images/Sample.png");
        QSplashScreen splash(pixmap);
    
        // Created the pushbutton and added to splashscreen
        QPushButton b(&splash);
        b.setGeometry(50,50, 100, 50);
        b.setText("FPS");
        
        // variable to be modified inside a lamda function
        int i = 0;
        
        // Connection for button clicked signal executes lamda function
        QObject::connect(&b, &QPushButton::clicked, 
        [i = static_cast<const int&>(i), &splash = static_cast<QSplashScreen&>(splash)]()mutable 
        {i = i+1; splash.showMessage("clicked: "+ QString::number(i));});
        
        // Adding properties and displaying the splashscreen
        splash.setGeometry(0,0, 1920, 1080);
        splash.setEnabled(true);
        splash.show();
        
        a.processEvents();  
        return a.exec();
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多