几天前,我开始学习Qt(5.5),最近我在使用connect函数(特别是SLOT参数)时陷入了困境。我从与调用connect函数相同的类中调用成员函数,但是当SLOT函数被触发时,它的行为就像在创建一个新的类对象。当我将所有内容都放在同一个类中时,它开始起作用,但是当我尝试实现层次结构时,此问题突然出现。我写了一个简短的程序来演示我的问题。

Main.cpp

#include <QApplication>

#include "MainWindow.h"

int main(int argc, char* argv[])
{
  QApplication app(argc, argv);

  MainWindow QtWindow;

  QtWindow.show();

  return app.exec();
}


MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWidget>
#include <QGridLayout>

#include "TopWidget.h"

class MainWindow : public QMainWindow
{
  Q_OBJECT
  public:
    MainWindow(QMainWindow *parent = 0);
  private:
    QWidget *mainWidget;
    QGridLayout *mainLayout;
};

#endif // MAINWINDOW_H


MainWindow.cpp

#include "MainWindow.h"

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent){

  mainWidget = new QWidget(this);
  mainLayout = new QGridLayout(mainWidget);
  setCentralWidget(mainWidget);

  TopWidget tWidget(this);

  mainLayout->addWidget(tWidget.topWidget, 0, 0);
}


TopWidget.h

#ifndef TOPWIDGET_H
#define TOPWIDGET_H

#include <stdlib.h>

#include <QWidget>
#include <QPushButton>
#include <QGridLayout>

#include <QDebug>
#include <QErrorMessage>

class TopWidget : public QWidget
{
  Q_OBJECT
  public:
    TopWidget(QWidget *parent);
    QWidget *topWidget;
  private:
    QGridLayout *wLayout;
    QPushButton *Button;

    int memVar1;
    int memVar2;
  private slots:
    void testConnect();
    //void SlotWithParams(int a, int b);
};

#endif // TOPWIDGET_H


TopWidget.cpp

#include "TopWidget.h"

TopWidget::TopWidget(QWidget *parent) : QWidget(parent){
  topWidget = new QWidget(parent);
  wLayout = new QGridLayout(topWidget);

  memVar1 = 123;
  memVar2 = 321;

  Button = new QPushButton("Click Me", topWidget);
  connect(Button, &QPushButton::clicked, [=](){ TopWidget::testConnect(); });
}

void TopWidget::testConnect(){
  qDebug("Button worked");
  if(memVar1 != 123 || memVar2 != 321){
    qDebug("Linking failed");
  }else{
    qDebug("Linking success");
  }
}


自从我刚开始使用Qt以来,我对什么是“正确的” Qt代码以及应该避免的内容并不满意,因此也欢迎您朝着这个方向提出建议。如果重要的话,下面是qmake文件。

CONFIG += c++11
CONFIG += debug
CONFIG += console

QT += widgets
QT += testlib

SOURCES += main.cpp
SOURCES += MainWindow.cpp
SOURCES += TopWidget.cpp
HEADERS += MainWindow.h
HEADERS += TopWidget.h

Release:DESTDIR = bin/Release
Release:OBJECTS_DIR = obj/Release
Release:MOC_DIR = extra/Release
Release:RCC_DIR = extra/Release
Release:UI_DIR = extra/Release

Debug:DESTDIR = bin/Debug
Debug:OBJECTS_DIR = obj/Debug
Debug:MOC_DIR = extra/Debug
Debug:RCC_DIR = extra/Debug
Debug:UI_DIR = extra/Debug


当我在调试模式下运行程序并按下按钮时,它会输出“按钮已工作”,表明函数链接成功,但是随后输出“链接失败”,表明创建了新对象,而不是使用旧对象。我对C ++的知识是零星的,因为我只了解需要的东西,而且昨天我花了几个小时尝试解决此问题,因此,如果修复非常简单,请原谅我,但是我对此已经精疲力尽。

最佳答案

问题来自此行:

TopWidget tWidget(this);


您正在堆栈上分配tWidget,并且它仅在MainWindow构造函数的末尾被销毁。

替换为:

TopWidget * tWidget = new TopWidget(this);


另外,您应该用这一根替换您的连接线

connect(Button, &QPushButton::clicked, this, &TopWidget::testConnect);


看来即使TopWidget被销毁,您的插槽也会被调用。 Qt通常在发送方或接收方被破坏时会断开连接,但是当您连接到Lambda时,Qt无法这样做。

最后,您正在做一些奇怪的事情。除了创建另一个窗口小部件并在其插槽上接收信号之外,您的TopWidget类的目的是什么?您绝不会将TopWidget添加到任何布局,而只能添加其子级。 TopWidget从未显示,因此应该仅从QObject派生。

10-08 08:19