- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我目前正在研究Qt项目,并且对信号和插槽机制有些困惑。但是,我觉得我对QObject和用户界面形式之间的区别有了一定的了解。
用户界面形式(由.ui文件描述)被馈送到用户界面编译器(uic)中,并生成关联的头文件。该头文件不仅包含接口(interface)信息,还包含应格式化的QObject的实现细节。另一方面,QObject是许多Qt框架都建立在其上的基类。信号和插槽系统完全基于QObject。
扩展QObject类(或从派生类)时,实际上是在定义一个可以在其中产生信号和插槽的对象。要格式化该对象使其看起来像您刚刚在Qt Designer中设计的用户界面,请创建ui类的实例(通过uic生成的ui header )。您可以在此类上调用setup方法,并将其提供给您正在创建的新QObject。
这一切似乎都是有道理的。
但是,没有意义的是当您开始实际定义信号时。通过Qt Designer,我可以选择右键单击并选择一个“信号”。当我选择一个信号时(无论是鼠标单击按钮还是在进度栏中进行更改),最终都会将其添加到我的QObjects信号部分。我的问题是:为什么以及如何做? Qt Designer(一个为uic生成XML的程序)在Qt Designer中的 Action 与Qt Creator中的QObject耦合得如何?更具体地说,它如何知道将此插槽添加到哪个QObject?
这个问题可能还不清楚,所以我在这里举一个例子。
例如,我要创建某种新的交互式显示。我们称之为“MyScreen”。为了创建此界面,我可能会有3个文件:“myscreen.h”,“myscreen.cpp”和“myscreen.ui”。 “myscreen.h”负责声明QObjects属性和方法以及信号和插槽。 “myscreen.cpp”负责定义方法,信号和插槽。 “myscreen.ui”负责创建用于格式化MyScreen实例的用户界面布局。
但是由于我之前所说的ui仅用于生成 header ,为什么将它精确地耦合到“myscreen.cpp”?也就是说,我可以右键单击.ui布局,创建一个新的信号类型,然后将该信号类型添加到myscreen.h和myscreen.cpp中。这是怎么发生的?它如何耦合? Qt是否可以始终存在3个文件(xxx.h,xxx.cpp,xxx.ui)运行?
因此,希望能为您提供一些我感到困惑的背景。似乎没有一个写得很好的文件(至少我已经找到),该文件彻底描述了所有这些项目之间的潜在关系。
TLDR-.h和.cpp中的信号/插槽实际上如何链接到.ui文件中定义的元素?
最佳答案
My question is: why and how? How exactly are my actions in Qt Designer (a program that generates an XML for the uic) getting coupled to my QObject in Qt Creator? More specifically, how does it know which QObject to add this slot to?
Q_OBJECT
宏的文件时,都会触发Qt的
moc
工具在编译过程中运行(“触发”实际上并不是最准确的描述:更确切地说,当
qmake
运行以生成makefile时, ,当在 header 中检测到
moc
时,它会添加构建规则以运行
Q_OBJECT
,但这只是重点。详细信息超出了此答案的范围,但长话短说,它最终会生成您将在编译后看到的
moc_*.cpp
文件,其中包含一大堆已编译的元信息。此操作的重要部分是生成有关您声明的各种信号和插槽的运行时可访问信息。您将在下面看到这一点的重要性。
QObject
都有
a name。在运行时可以访问该名称。您在设计器中为窗口小部件指定的名称被设置为窗口小部件的对象名称。这很重要的原因也将在下面阐明。
QObject
具有分层结构;创建
QObject
时,可以设置其父代。表单上的所有小部件最终都将表单本身(例如,源自
QMainWindow
的类)作为其父级。
ui->setupUi(this)
调用。该功能的实现是由Qt的
uic
工具在编译过程中生成的,例如
ui_mainwindow.h
。该函数是您在设计器中设置的所有属性的实际设置,其中存储了.ui文件,包括小部件的对象名。现在,生成的
setupUI()
实现的最后一行是关键:
void setupUi(QMainWindow *MainWindow) {
...
// Object properties, including names, are set here. This is
// generated from the .ui file. For example:
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(110, 70, 75, 23));
...
// This is the important part for the signal/slot binding:
QMetaObject::connectSlotsByName(MainWindow);
}
connectSlotsByName
是所有这些小部件信号发生魔术的地方。
moc
打包到运行时可访问的字符串中,所以可以这样做。 on_<objectname>_<signalname>
模式匹配的插槽时,它将在对象层次结构中递归搜索名称为
QObject::connect(...)
的调用)。
QMetaObject::connectSlotsByName
在运行时找到它并建立连接。
on_lineEdit1_returnPressed()
和voila,它有效。您只需要小心,就像海德在评论中提醒我们的那样:如果您在此处出错,则不会收到编译时错误,您只会收到打印到stderr的运行时警告,而连接不会被创造;因此,如果您在此处进行任何更改,请务必注意控制台输出。 moc
在所有
QObject
上运行,并且
connectSlotsByName
始终可用。因此,您创建的任何对象层次结构,如果命名对象,然后使用适当的名称声明插槽,则可以调用
connectSlotsByName
自动建立连接;碰巧
uic
会在
setupUi
的末尾粘贴调用,因为这是放置它的方便位置。但是魔术不是特定于UI的,也不依赖
uic
,仅依赖于元信息。这是一种普遍可用的机制。非常干净。
QMetaObject::connectSlotsByName
的简单示例。
关于c++ - Qt信号/插槽实际上如何与.ui文件中的元素耦合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39198081/
插槽到底是个啥?5分钟搞定 Vue 插槽 插槽的基本使用 组件使用slot标签,显示组件标签的内容 Title aaa Vu
Closed. This question is not reproducible or was caused by typos。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-to
我有一个对象,它用一个对象发出信号: MyObj *obj = this->generateObj(); emit newObjSignal(obj); delete obj; 我有一个或多个人与此有
距离ETS的发布也有一段时间,也有不少小伙伴通过ETS制作出很多精美的页面,但在我查阅ETS的组件和API中发现,现有版本的ETS并没有插槽的功能。经过一段时间的探索终于找到曲线救国方式实现插槽
我无法找到有关使用资源管理器模板以编程方式向 WebApp 添加插槽的信息/指南。我的基本配置运行良好,创建了 WebApp 本身、SQL 服务器、SQL DB 等,但我也渴望完成插槽,以便我可以将它
我们的项目位于 sitecore 中,并使用 Azure - 应用服务进行部署。我们已经创建了暂存槽,除了应用程序设置和连接字符串之外,还希望使一些配置文件槽特定(交换时坚持槽)。 有没有办法让整个配
我使用 Azure 插槽功能来部署我的机器人: 部署到“暂存”槽 Azure 启动此实例 启动后,我会交换“生产”和“登台”时段 我想在进行插槽之前测试暂存实例,最好使用 Azure 门户中的 Web
我使用 Azure 插槽功能来部署我的机器人: 部署到“暂存”槽 Azure 启动此实例 启动后,我会交换“生产”和“登台”时段 我想在进行插槽之前测试暂存实例,最好使用 Azure 门户中的 Web
我的应用程序只能通过右键单击托盘图标并按“退出”来退出: class DialogUIAg(QDialog): ... self.quitAction = QAction("&Quit
我不太确定如何将其总结为一个谷歌问题,但也许详细解释它会给我更好的帮助。 我正在尝试找到与在 PHP 中的 python 中设置槽的等价物 python : class Node: slots
我浪费了几个小时试图找出这个错误,但我仍然不知道为什么会发生...所以我求助于你! 我将一个对象移动到一个线程中,该线程执行一些工作,完成后会发出一个信号以供 QMainWindow 捕获。就这么简单
我有一个自旋控件 block ,它可以更改数组的各个元素我不想使用单独的接收器槽函数,而是只想指定哪个控件在信号中发送消息 您可以使用 QSignalMapper 来做到这一点——但是是否可以像下面那
我想知道如何将一个单独的变量传递到一个插槽中。我似乎无法让它工作。有什么办法解决这个问题吗? 这是我的代码: QTimer * timer = new QTimer(); connect(timer,
我有一个基类,它定义了一个 Qt 插槽 class Base { public: Base() { connect(otherobject, SIGNAL(mySign
这是基类中声明的样子: protected: void indexAll(); void cleanAll(); 在派生类中,以下不编译: indexAll(); // OK con
比如我有一个函数 void A::fun() { do_1(); emit signal_1(); do_2(); emit signal_2(); do_3(
我希望能够将视频从连接到我的计算机的摄像头直接流式传输到我通过 PCIE 连接到我的计算机的 FPGA。 我不介意使用 javascript 或 C# 等高级语言来执行此操作(因为这些是我知道的具有视
Qt世界中,事件和信号/槽的区别是什么? 一个会取代另一个吗?事件是信号/槽的抽象吗? 最佳答案 Qt documentation可能解释得最好: In Qt, events are objects,
1. 监听属性值的变化 - watch 语法要求:watch里面的函数名必须跟date里面属性名一致 {{num}} 添加 var
在 Class Buttons 中,我有一个 btnRightClicked 信号和一个 mousePressEvent 插槽: void Buttons::mousePressEvent(QMous
我是一名优秀的程序员,十分优秀!