connect()中如何获取SLOT的成员对象?
How to get the member object for SLOT in connect()?
我几天前开始学习 Qt (5.5),最近在使用 connect 函数时遇到了一些问题,特别是 SLOT 参数。我从调用 connect 函数的同一个 class 调用一个成员函数,但是当触发 SLOT 函数时,它就像在创建一个新的 class 对象一样。当我将所有内容都保持在相同 class 时,它最初起作用了,但是当我尝试实现层次结构时,这个问题突然出现了。我写了一个简短的程序来演示我的问题。
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,所以我对什么是 "proper" 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
当我 运行 程序处于调试模式并按下按钮时,它输出 "Button worked" 表示 link 函数成功,但随后输出 "Linking failed"表示创建了一个新对象而不是使用旧对象。我对 C++ 的了解是零散的,因为我只学到了我需要的东西,昨天我花了几个小时试图解决这个问题,所以请原谅我,如果这个修复非常简单,但我已经精疲力竭了。
问题出在这一行:
TopWidget tWidget(this);
您正在堆栈上分配 tWidget
,它在 MainWindow
构造函数的末尾被销毁。
替换为:
TopWidget * tWidget = new TopWidget(this);
另外,你应该用这个替换你的连接线
connect(Button, &QPushButton::clicked, this, &TopWidget::testConnect);
看来即使在 TopWidget
被销毁后,您的插槽也会被调用。 Qt 通常会在发送方或接收方被破坏时断开连接,但当您连接到 lambda 时它无法断开连接。
最后,你在做一些奇怪的事情。你的 TopWidget
class 除了创建另一个小部件并在其插槽上接收信号之外还有什么用途?您永远不会将 TopWidget
添加到任何布局,而只是它的子布局。 TopWidget
从未显示,因此它应该只派生自 QObject
。
我几天前开始学习 Qt (5.5),最近在使用 connect 函数时遇到了一些问题,特别是 SLOT 参数。我从调用 connect 函数的同一个 class 调用一个成员函数,但是当触发 SLOT 函数时,它就像在创建一个新的 class 对象一样。当我将所有内容都保持在相同 class 时,它最初起作用了,但是当我尝试实现层次结构时,这个问题突然出现了。我写了一个简短的程序来演示我的问题。
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,所以我对什么是 "proper" 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
当我 运行 程序处于调试模式并按下按钮时,它输出 "Button worked" 表示 link 函数成功,但随后输出 "Linking failed"表示创建了一个新对象而不是使用旧对象。我对 C++ 的了解是零散的,因为我只学到了我需要的东西,昨天我花了几个小时试图解决这个问题,所以请原谅我,如果这个修复非常简单,但我已经精疲力竭了。
问题出在这一行:
TopWidget tWidget(this);
您正在堆栈上分配 tWidget
,它在 MainWindow
构造函数的末尾被销毁。
替换为:
TopWidget * tWidget = new TopWidget(this);
另外,你应该用这个替换你的连接线
connect(Button, &QPushButton::clicked, this, &TopWidget::testConnect);
看来即使在 TopWidget
被销毁后,您的插槽也会被调用。 Qt 通常会在发送方或接收方被破坏时断开连接,但当您连接到 lambda 时它无法断开连接。
最后,你在做一些奇怪的事情。你的 TopWidget
class 除了创建另一个小部件并在其插槽上接收信号之外还有什么用途?您永远不会将 TopWidget
添加到任何布局,而只是它的子布局。 TopWidget
从未显示,因此它应该只派生自 QObject
。