我可以将“this”传递给 Q_Slot 吗?

Posted

技术标签:

【中文标题】我可以将“this”传递给 Q_Slot 吗?【英文标题】:Can I pass "this" to a Q_Slot? 【发布时间】:2017-02-16 14:10:28 【问题描述】:

我有一个带有许多窗口(QWidgets)的应用程序。 不过,我没有保存打开的窗口列表,所以每次我想关闭一个窗口时,我都必须检索它。

特别是,这些窗口中的每一个在此处被称为 SubWindow。 每个 SubWindow 类都包含一个带有 MultiEditor *sEditors 的布局,它有一个带有关闭当前窗口的操作的菜单。 每个子窗口都是在主窗口中创建的。

我有两个计划。 1) 通过添加 SubWindow 构造函数,从自身内部销毁 SubWindow

connect(sEditors, SIGNAL(closeWindow()),
        this, closeWindow()));

2) 通过添加 SubWindow 构造函数,从 MainWindow 类中销毁 SubWindow

connect(sEditors, SIGNAL(closeWindow()),
        main, SLOT(closeWindow(this)));

关于 1),我不明白如何从内部关闭和销毁 QWidget(删除它; 似乎不起作用,但我可以再试一次)。

关于 2) 我的 SLOT(closeWindow(this)) 似乎没有被触发,所以我想知道是否可以将“this”作为参数传递。

【问题讨论】:

【参考方案1】:

广告 1) 您可以使用QObject::deleteLater()。这将在下一个事件循环周期中销毁对象,并且专门为此类情况创建

Ad 2) 您不能在信号槽连接中将实际参数作为参数传递。 但是,您可以使用插槽中的sender() 函数找出谁发出了信号。在您的情况下,这将是 sEditors 对象。

其他选项:

3) 您可以使用QSignalMapper 将信号从您的编辑器映射到子窗口。

4)(使用 Qt5 / C++11)您可以在子窗口中使用 lambda 连接:

connect(sEditors, SIGNAL(closeWindow()), [this] () this->closeWindow(););

【讨论】:

出于某种原因(我不知道),我的 deleteLater() 无法正常工作。我在 closeWindow() 中触发它并且我的 QWidget 仍然存在 - >它不会消失。即使我写 close() [或 this->close()] 或 hide() [this->hide()],QWidget 也不会消失 您似乎正在关闭/删除/隐藏错误的小部件。使用调试器验证 this 是否指向插槽中的正确对象【参考方案2】:

我可以将this 传递给 Qt 插槽吗?

槽是一个非静态方法,所以它已经可以访问this。您所指的thisQObject::connect 的第三个参数。在 Qt 4 语法中,您可以省略第三个参数 - 它默认为 this。不过,在 Qt 5 语法中,您必须明确说明。

我不明白如何从内部关闭和销毁 QWidget

要从其内部删除任何QObject,请使用QObject::deleteLater()。回想一下,QWidget 在LSP 中是一个QObject

我的 SLOT(closeWindow(this)) 似乎没有被触发

没有这样的插槽(给我们一个指向它的文档的链接:你不能),并且你的插槽签名也是无效的,因为插槽签名中括号内的唯一内容可以是类型,而 this 不是一个类型:SLOT(slotName(TYPE_LIST_HERE)),例如SLOT(mySlot(int,QString)).

要关闭小部件,请使用其close() 插槽:

connect(sEditors, SIGNAL(closeWindow()), this, SLOT(close());

然而,通过使用 Qt 4 connect 语法,您将在运行时检测到编码错误 - 如果您在运行时不注意调试输出,您就会错过它。因此最好使用新的 (Qt 5) connect 语法,并让编译器为您检测错误:

connect(sEditors, &MultiEditor::closeWindow, this, &QWidget::close); 

唉,没有必要将发送closeWindow 的对象紧密耦合到SubWindow - 至少不在SubWindow::SubWindow() 内。相反,您可以在创建编辑器的地方进行连接。

要在小部件关闭时删除它,只需在其上设置Qt::WA_DeleteOnClose 属性并让Qt 为您完成。无需显式调用deleteLater 等。

你可以把它全部分解成一个工厂方法:

template <class T> T* SubWindow::makeEditor() 
  auto sub = new Tthis;
  sub->setAttribute(Qt::WA_DeleteOnClose);
  connect(sEditor, &MultiEditor::closeWindow, sub, &QWidget::close);
  return sub;


MainWindow::MainWindow(/*...*/) : /*...*/ 
  makeEditor<EditorType1>();
  makeEditor<EditorType2>();
  /*...*/

【讨论】:

Qt5 语法非常有用,谢谢!由于某种原因(我不知道),我的 deleteLater() 不起作用。我在 closeWindow() 函数中触发它,我的 QWidget 仍然存在 - >它不会消失。即使我写 close() [或 this->close()] 或 hide() [this->hide()],QWidget 也不会消失,即使我写 connect(sEditors, &MultiEditor::closeWindow, this, &QWidget::close);

以上是关于我可以将“this”传递给 Q_Slot 吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以改变传递给 setState 函数的状态吗?

我可以将 std::string 传递给 DLL 吗?

如何将 $(this) 传递给选择器

我可以将 String[] 列表传递给 Freemarker 吗?

我可以将 ResolvableApiException 传递给新活动吗?

我可以将 const char* 数组传递给 execv 吗?