【Qt】Qt 新建类时 Base class 怎么选?一篇文章帮你理清 QObject、QWidget、QMainWindow 等区别
在刚开始做 Qt 项目时,很多人第一次新建类都会被这个界面搞懵:
QObjectQWidgetQMainWindowQQuickItem<Custom>看上去都是“基类”,但问题是:它们到底有什么区别?我这个类到底该继承谁?
尤其是在模仿老师项目或者自己搭项目的时候,经常会遇到这种情况:
- 有的时候新建类选
QObject- 有的时候又选
QWidget- 主窗口又是
QMainWindow- 还有些类根本不显示界面
如果一开始没有把这个问题想清楚,后面写代码时就很容易乱。
所以这篇文章就专门来解决一个问题:Qt 新建类时,Base class 到底怎么选?
我不打算只讲概念,而是尽量从“这个类在项目里到底扮演什么角色”来讲清楚。
1. 先记住一个最核心的判断标准:这个类到底是“干活的”还是“显示界面的”?
很多初学者一看到基类,就想着“哪个功能更强就选哪个”。
其实不是这样。
在 Qt 里,选基类最重要的不是看谁“更高级”,而是看:
你这个类到底是拿来处理逻辑的,还是拿来显示界面的。
你可以先把 Qt 里的类粗略分成两大类:
第一类:不负责显示界面,只负责处理逻辑
比如:
- 错误处理类
- 网络通信类
- 数据管理类
- 配置读取类
- 定时任务类
- 控制器、管理器、服务类
这类类通常不需要在屏幕上显示出来,它们只是默默在后台“干活”。
这种情况下,通常优先考虑的就是:QObject
第二类:需要显示在界面上的类
比如:
- 一个按钮区域
- 一个设置页
- 一个自定义面板
- 一个弹窗
- 一个主窗口
这类类是用户能直接看到、点击和交互的。
这种情况下,通常就要从:
QWidgetQMainWindowQQuickItem
里面选。
所以最简单的一句话就是:
不显示界面,多半选 QObject;要显示界面,再看是普通界面还是主窗口。
这就是最底层的判断逻辑。
2. QObject:适合“后台逻辑类”,不负责显示界面
QObject 可以说是 Qt 里非常基础、非常常用的一个类。
它本身不是一个界面控件,也不会显示在窗口里,但它有很多 Qt 非常核心的能力,比如:
- 对象树和父子关系管理
- 信号与槽机制
- 事件机制
- 内存自动管理的一部分支持
所以在项目里,凡是那些不需要长在界面上、但又想利用 Qt 机制的类,很多都适合继承 QObject。
什么样的类适合选 QObject?
比如下面这些名字,一看就很适合 QObject:
ErrorHandlerFileManagerDatabaseManagerConfigReaderNetworkClientTaskController
你会发现,这些类有一个共同点:
它们不是拿来给用户看的,而是拿来给程序干活的。
就拿 ErrorHandler 来说,这个类从名字上就能看出来,它更像是一个“错误处理器”或者“异常处理模块”。
它的职责通常是:
- 接收错误信息
- 分类错误
- 记录日志
- 发出提示信号
- 通知其他模块处理
它本身不是一个按钮,不是一个窗口,也不是一个页面,所以这时候选 QObject 就非常合理。
为什么这种类不该选 QWidget?
因为 QWidget 是界面类。
如果你只是想写一个逻辑处理类,却继承了 QWidget,就相当于你给一个“后台工作人员”硬套了一个“窗口外壳”,这在设计上是不合适的。
说白了就是:这个类明明不需要显示,结果你却把它做成了一个界面类。
这样做的问题有两个:
第一,语义不清楚。
别人一看你继承 QWidget,会默认觉得这是个界面类。
第二,没必要增加界面类的负担。
逻辑类就应该尽量保持轻量,不要无缘无故背上界面的包袱。
一句话记忆 QObject
凡是“管理器、处理器、控制器、服务类、数据类”,大多数先考虑 QObject。
3. QWidget:适合“普通界面类”,它是你最常用的页面和组件基类
如果说 QObject 是“后台干活”的,那么 QWidget 就是“真正站到前台”的。
它表示的是一个可见的界面组件,也就是说,用户是可以在窗口里看到它的。
很多初学者做 Qt 项目时,实际接触最多的界面类,往往就是 QWidget。
QWidget 最适合做什么?
适合做这些“普通界面”:
- 一个设置页面
- 一个登录页面
- 一个信息展示面板
- 一个自定义小组件
- 一个弹出的普通窗口
- 一个嵌入到其他窗口中的界面区域
你可以把 QWidget 理解成:
“界面上的一块区域”或者“一个普通窗口单元”
它不一定是整个程序最外层的大窗口,它更多像是界面中的一个组成部分。
什么情况下该选 QWidget?
当你这个类满足下面这些特征时,通常就该考虑 QWidget:
- 这个类要显示在界面上
- 用户能看到它、点到它
- 它可能放按钮、标签、输入框、列表这些控件
- 它更像是一个“页面”或“模块”
比如:
LoginWidgetSettingPageUserInfoWidgetControlPanelResultWidget
从这些名字你就能感觉到,它们更像是界面的一部分,而不是纯逻辑类。
QWidget 和 QObject 的本质区别
最简单的区别就是:
QObject:有 Qt 机制,但不负责界面显示QWidget:既有 Qt 机制,又是一个可显示的界面对象
所以你可以把 QWidget 看成是“带界面能力的更具体的一类对象”。
一句话记忆 QWidget
只要这个类是“给用户看的一个普通页面或组件”,优先考虑 QWidget。
4. QMainWindow:适合“整个程序的主窗口”,不是普通页面都该用它
很多人刚学 Qt 时,会觉得 QMainWindow 好像比 QWidget 更厉害,于是新建界面就想直接选 QMainWindow。
这其实是一个很常见的误区。
QMainWindow 的确是一个窗口类,但它不是给你随便拿来做任何界面的。
它更适合用来表示:
整个应用程序最外层、最核心的主窗口。
什么叫主窗口?
比如一个桌面软件启动后,最外面的那个总界面,通常会有这些东西:
- 菜单栏
- 工具栏
- 状态栏
- 中央工作区
- 停靠窗口
这种结构就很符合 QMainWindow 的设计思路。
也就是说,QMainWindow 更适合那种“像一个完整软件壳子”的界面,而不是普通的小页面。
什么情况下该选 QMainWindow?
比如你要做:
- 程序启动后的主界面
- 整个系统的主操作台
- 带菜单栏和状态栏的软件主窗口
- 类似 IDE、管理系统、工具软件的主框架
这些都适合 QMainWindow。
为什么不能随便把页面都做成 QMainWindow?
因为 QMainWindow 的定位太“重”了。
它不是给你做每个子页面的。
如果你只是做一个设置页、一个登录页、一个功能模块页,却继承 QMainWindow,就会显得非常笨重,而且结构也不清晰。
你可以这样理解:
QMainWindow:像“整栋楼”QWidget:像“楼里的某个房间”
显然,不是每个房间都要建成一整栋楼。
一句话记忆 QMainWindow
整个程序最外层的主窗口,用 QMainWindow;普通页面别乱用。
结语:选基类,本质上是在选“这个类的身份”
很多人刚开始学 Qt,会把“继承谁”看成一个语法问题。
其实它更像是一个设计问题。
因为你选的不是一个单纯的名字,而是在决定:
这个类在项目里到底扮演什么身份。
- 它是后台逻辑人员,还是前台界面人员?
- 它是普通页面,还是整个程序的大框架?
- 它是 Qt Widgets 项目的一部分,还是 QML 体系的一部分?
一旦把“类的身份”想清楚了,基类的选择其实就没那么难了。
最后再用一句最接地气的话总结:
不显示界面,就先想 QObject;显示普通页面,就选 QWidget;整个软件主窗口,才选 QMainWindow。
这样基本就不会错得太离谱。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)