【问题标题】:Qt Signals and Slots ConfusionQt 信号和插槽混淆
【发布时间】:2014-01-17 21:31:53
【问题描述】:

我一直在阅读有关 Qt 信号和插槽的信息,我正在尝试让它工作,但直到现在都没有成功。我希望有人能指出我正确的方向。
我有两个文件,homeCommand.cppmessagelogcommand.cpp。我在messagelogcommand.cpp 中有一个QPlainTextEdit 对象,我想从homeCommand.cpp 更新它。
如何使用信号和插槽做到这一点?正在调用我的信号,因为我的 QDebug 每秒打印一次,但是小部件没有更新。

这就是我想要做的:

在 MessageLogCommand.h 中

class MessageLogCommand : public QWidget
{
    Q_OBJECT
public:
    explicit MessageLogCommand(QWidget *parent = 0);

    QLabel *homeLabel;
    QPlainTextEdit *messageLog;

public Q_SLOTS:
    void updateWidgets(const QString &text);

};

homeCommand.h

class homeCommand : public QWidget
{
    Q_OBJECT

Q_SIGNALS:
    void textChanged(const QString &text);

public:
    explicit homeCommand(QWidget *parent = 0);

public slots:
    void run(void);
    void getHealthStatusPacket(void);

homeCommand.cpp

homeCommand::homeCommand(QWidget *parent) : QWidget(parent)
{
    ...
    //Timer
    QTimer *timer = new QTimer(this);
    timer->setSingleShot(false);
    connect(timer, SIGNAL(timeout()), this, SLOT(run()));
    timer->start(1000);

    setLayout(layout);
}

void homeCommand::run(void)
{
    getHealthStatusPacket();
}

void homeCommand::getHealthStatusPacket(void)
{
    ...
    Q_EMIT textChanged("ZOMG");
}

在 MessageLogCommand.cpp 中

 MessageLogCommand::MessageLogCommand(QWidget *parent) : QWidget(parent)
 {

    QGridLayout *layout = new QGridLayout;
    QWidget::setFixedHeight(600);

    //Sub-system Label
    homeLabel = new QLabel("GSS Message Log");
    QFont subsystemFont = homeLabel->font();
    subsystemFont.setPointSize(12);
    subsystemFont.setBold(true);
    homeLabel->setFont(subsystemFont);
    layout->addWidget(homeLabel, 0, 0);

    //Event Log
    messageLog = new QPlainTextEdit();
    messageLog->setFixedHeight(500);
    messageLog->setFixedWidth(600);
    layout->addWidget(messageLog, 2,0);

    setLayout(layout);
}

void MessageLogCommand::updateWidgets(const QString &text)
{
    qDebug() << "Here";
    messageLog->appendPlainText(text);
}

在 main.cpp 中

MessageLogCommand s;
homeCommand m;

QObject::connect(&m, SIGNAL(textChanged(QString)), &s, SLOT(updateWidgets(QString)));

【问题讨论】:

  • 我认为任何人都可以提供帮助,您需要在 code 块中提供您拥有的代码
  • 向我们展示更多。也许没有必要使用信号&槽

标签: c++ qt signals-slots


【解决方案1】:

一个非常基本的例子是:

class MainClass:public QObject    //class must be derived from QObject!
{
   Q_OBJECT    //this macro must be in the class definition
               //so the moc compiler can generate the necessary glue code

   public:
       void doSomething() {
           ...
           Q_EMIT textChanged(someText);
       }

   Q_SIGNALS:
       void textChanged(const QString &text);
};

class SubClass:public QObject
{
   Q_OBJECT

   public Q_SLOTS:
       void onTextChanged(const QString &text) {    //do not inline
           //do something
       }
};

int main()
{
    QApplication a;

    MainClass m;
    SubClass s;
    QObject::connect(&m, SIGNAL(textChanged(QString)),
                     &s, SLOT(onTextChanged(QString)));  //const and & are removed from
                                                         //the arguments

    return a.exec();    //run the event loop
}

所以,有两件事很重要: 1、信号和槽必须在QObject派生的类中声明 2. 包含信号和槽声明的类必须在类声明中添加Q_OBJECT宏

为简单起见:始终在头文件中声明包含信号或槽的类(切勿在 .cpp 文件中)。

【讨论】:

  • 我试过这个。它可以编译,并且我知道正在调用“onTextChanged”函数,因为每次调用它时都会打印出一条 qDebug() 消息。出于某种原因,我的小部件没有更新。它只是保持空白。我什至试图只输入一个硬编码的字符串,但它永远不会出现。想法是为什么会这样?
  • 您能否让我们更深入地了解您的代码,包括类声明?
【解决方案2】:

信号和槽的一个很好的起点是:http://woboq.com/blog/how-qt-signals-slots-work.html,但官方 Qt 文档也是这样做的:http://qt-project.org/doc/qt-4.8/signalsandslots.html

基本上会发生什么:你声明了一些特殊的方法(信号和槽),在编译阶段 Qt 生成额外的 CPP 文件来处理你的方法(moc)然后所有的东西都被编译并链接在一起,最后当 Qt 或其他人发出信号,它将转到相应的插槽。

【讨论】:

  • 我已经阅读了这个文档,但仍然没有完全理解,我用我正在尝试做的事情更新了我的原始帖子......
【解决方案3】:

我试着解释一下。

在 main.h 你应该声明一个信号:

signals:
     void textChanged(const QString& text);

在 messagelog.h 中你应该声明一个插槽:

public slots:
     void updateWidgets(const QString& text);

在 main.cpp 你应该发出这个信号:

void TheMethod() {
    emit this->textChanged("Your text/value");
}

在 messagelog.cpp 你应该得到这个值:

// Note: Normalized signal/slot signatures drop the consts and references.
connect(&a, SIGNAL(textChanged(QString)), this, SLOT(updateWidgets(QString)));

void updateWidgets(const QString& text) {
   messageLog = new QPlainTextEdit();
   messageLog->setFixedHeight(500);
   messageLog->setFixedWidth(600);
   messageLog->setPlainText(text)
   layout->addWidget(messageLog, 2,0);
}

我认为它应该有效。

更新: 完整示例:https://dl.dropboxusercontent.com/u/29647980/test.zip

【讨论】:

  • 我不确定它是否正确。距离我最后一次用 C++ 和 Qt 编程已经很久了。
  • 是的。例如,您应该在构造函数中执行此操作。
  • 代码符合并运行,但我的 updateWidgets() 从未被触发。我放了一个 printf() 语句,没有任何东西被打印出来。
  • @user2494298 connect中不用写main::textChanged(),作用域来自对象textChanged(const QString&amp;)就好了。
  • 因为我上面的代码有些错误我写了一个例子,你可以在这里下载dl.dropboxusercontent.com/u/29647980/test.zip 写完整的代码比写部分更容易。 :)
猜你喜欢
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
  • 2012-10-15
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多