type
Page
slug
Qt
status
Published
date
summary
tags
知识
category
技术分享
icon
password
写UI的两种方法
Qt Designer
- 可视化编辑.ui文件
- 本质上是XML
- 便于分开前后端的编写
- ui与业务逻辑解耦
- 编译时需要先用uic工具转换为c++文件,多一个步骤
- 静态页面,不适用于动态操作
C++动态创建
- 手动实例化对象,设置布局
- 灵活性强
- 代码量大
- 所敲非所得,不能随时监控布局,需要脑补
折中方案
- 用Designer写静态框架,即程序运行中基本不变的内容
- 动态处理的内容用C++处理
窗口类型
模态窗口
- 有上下文关联的
- 有层级限制的,操作一个窗口前必须完成上一个窗口的交互
非模态窗口
- 相互独立
设计范式
万物皆对象
元对象系统
- Qt的面向对象与一般的C++ OOP不同,它定义了一套元对象系统 (Meta-Object System)。
- 所有对象均继承
QObject类。
- 通过
moc(元对象编译器)这个工具,在编译前给代码里塞进去了很多本来没有的功能,比如: - 信号与槽(Signals & Slots)
- 运行时类型信息:比C++自带的RTTI(运行时类型识别,Runtime Type Information)信息更丰富。
-
typeid操作符:typeid主要是让你在运行时知道一个对象的“类型名”,比如std::cout << typeid(*myObject).name();。它只能告诉你:“这个是个QPushButton“。 dynamic_cast:在做多态转换时用。比如有个QWidget指针,想安全地把它向下转型成QPushButton指针,如果转型不成功,它就返回nullptr。- 只能获取表面信息,无法获取内部方法和参数。
- 可以获取类名
- 可以获取所有父类,查询继承链
qobject_cast<Type*>():Qt版本的dynamic_cast,效率更高,对QObject体系更安全- 动态方法调用:
QMetaObject::invokeMethod() - 可以让你在运行时根据函数名,去调用任何信号、槽、或者Qt Property系统的读写方法
- 更强大的属性系统
- 可以通过一个字符串来获取或设置一个对象的属性值。
- 支持翻译
QObject::tr()方法能根据当前的语言环境,在运行时查找正确的翻译字符串- 与Qt Designer这样的工具联动
- 加载带
Q_OBJECT宏的类 - 把它的属性显示在属性编辑器里
- 把它的信号和槽列出来放在信号槽编辑器里让你连接
RTTI
元对象系统
信号和槽
核心就是“事件驱动”和“组件解耦”。
- 信号:触发的事件
- 槽:调用的方法
- 组件只管喊:一个按钮,被点击了,它只管用“喊话筒”(Signal)向全世界广播:“我被点了!”。根本不关心谁在听,谁会理它。
- 听众自己连:你写的其他代码,如果对这个“被点了”事件感兴趣,就自己长个“顺风耳”(Slot),然后用
connect函数把这个耳朵和那个喊话筒连起来。
通过connect函数链接
特点
- 解耦
- 类型安全
- 在编译阶段就能帮你检查信号的参数类型和槽的参数类型是否匹配
- 调用效率高,在底层直接调用函数指针
“模型-视图”架构(Model/View)
当要处理大量数据展示的时候,比如列表、表格、树状图,Qt强烈推荐你用这个范式。
- 模型(Model):就是纯粹的数据。它就是个数据仓库,负责存储、管理数据,提供访问接口。
- 视图(View):负责怎么把数据显示出来,画给用户看。
- 如表格的视图
QTableView,列表的视图QListView,树状的视图QTreeView,甚至你自己画的图QGraphicsView。 - 它根本不关心数据从哪儿来,数据怎么存的,它只知道按照自己的风格,问模型要数据来画。
- 用户在视图上点点画画的事件(比如选中一行,拖动列),它也只管发出信号,让别人去处理。
- 代理(Delegate):负责怎么把模型里的“原始数据”转换成视图能够理解并显示出来的数据。同时,它还负责视图上的用户交互如何改动模型里的数据。(兼容Controller的工作)
- 比如一个数字5,代理可以把它转成前面带个“¥”符号的字符串“¥5.00”。
- 比如用户直接双击表格改了一个单元格的文本,代理负责把这个文本塞回到模型里。
QML+C++:MVVM架构
- View:QML
- 声明式UI:QML 是个声明式语言,描述你想要什么而不是一步步将它画出来。只关心结果不关心过程。
- 只管UI实现。
- 支持数据绑定。
- 动画效果和图形能力强。
- 内嵌JavaScript引擎,可以直接运行JS语句
- ViewModel:C++ QObject
Q_PROPERTY宏:这个就是给 QML 准备的“数据绑定插头”,是 ViewModel 向 View 提供状态数据的基础。- 当你用
Q_PROPERTY在 C++ 类里声明一个属性时,QML 就能直接访问(读写)这个属性,还能通过NOTIFY信号监听这个属性的变化。 - 这就是 QML 里面
text: myViewModel.userName能自动更新的根本原因。 Q_INVOKABLE方法:这个就是行为指令的传送门,是 ViewModel 向 View 提供行为(命令)的基础。- 任何用
Q_INVOKABLE标记的 C++ 函数,都能被 QML 像调用脚本函数一样直接调用。
- 高性能、高颜值、易维护,跨平台。
布局管理器
自动排布各种控件。
QHBoxLayout(水平布局)
QVBoxLayout(垂直布局)
QGridLayout(网格布局)
QFormLayout(表单布局)
QStackedLayout(堆叠布局)







