11

我知道要在类中使用 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 中的信号和插槽方面哪里出了问题。

4

4 回答 4

10

Qt4...

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

因此,您不能使用放置在QObject儿童之外的插槽。

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

class MyClass : public QObject
{
   Q_OBJECT

   ...

   public slots:
     void saveText();

};

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

于 2013-05-24T12:08:37.837 回答
3

我这里只是举个例子。

主.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);
}
于 2017-03-06T06:42:27.643 回答
1
QObject::connect(&saveButton, &QPushButton::clicked, [](){saveText();});  // qt5.9.6

或如masoud的回答中所述

QObject::connect(&saveButton, &QPushButton::clicked, saveText);  // qt5.9.6
于 2019-01-17T08:33:21.363 回答
0

可以将信号连接到 main 函数内部的函数。这已经在 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();
}
于 2021-01-12T23:03:09.670 回答