13b3ebbe14
把川大 wiki「02.Qt方向」课程代码整理为 CMake 管理的可编译运行项目。
Part1 C/C++ 强化 (p01/, 144 目标, host gcc/g++ 构建, 全绿):
- 修复全部编译失败:补 <cstring>/<fstream>/<iomanip>/<vector> 等缺失头
(common_fix + infer_stl_includes 自动检测注入)、修正 pause() 壳注入
(改检测已转换后的 pause 调用)、namespace 提升出函数体、const 成员函数
正确性、dedupe 不再破坏函数重载集、K&R 隐式 int / 动态异常规范等
C++17 移除特性的可编译等价改写。
- 目录采用深缩写 p01/ch04/s03/ (原 part1_cpp/ch04_class_object/03_ctor_dtor)。
Part3 Qt 桌面 (p03/, 29 目标, 隔离 Qt 5.14.2 构建, 全绿):
- gen_part3.py: Qt 外壳模板 (main+QApplication+show, QTimer 自动退出便于
offscreen 验证)、AUTOMOC + .moc include、rewrite_* 处理散文混入/重载/
资源依赖、生成占位 png/gif + .qrc + rundata 样例数据。
- 修正 QLable 笔误、全角分号、.→->、Windows 路径、QApplication 阻塞事件
循环改为 QCoreApplication 等。
任务1 概念/版本验证:
- tools/std_probe.py: 跨 -std= 编译探针 (--pedantic-errors 让已废除特性硬失败)。
- tools/demo_versions/: K&R 隐式 int、三目左值、void* 转换、enum 赋整、
const 经指针、动态异常规范 共 6 个跨版本演示。
- docs/VERSION_NOTES.md: 每条「原文说法→C17/C++17 是否成立→何版本成立→已验证」。
文档: 顶层 README、docs/SOURCE_PAGES.md (页面→目录映射)、
docs/ERRATA.md (Part1 修正)、docs/ERRATA_part3.md (Part3 修正)。
另修复 tools/run.sh / run_qt.sh 的 ${1:?...} 引号语法 bug。
隔离 Qt 验证: ldd 0 系统 Qt 引用; 173/173 目标全绿; p03 offscreen 运行通过。
1 line
12 KiB
JSON
1 line
12 KiB
JSON
{"id":"58954529","type":"page","status":"current","title":"5 QMainWindow","version":{"by":{"type":"known","username":"ethanliu","userKey":"2c90931b6cfb654f016d5c69becc0001","profilePicture":{"path":"/images/icons/profilepics/default.svg","width":48,"height":48,"isDefault":true},"displayName":"刘浩","_links":{"self":"https://wiki.suncaper.net/rest/api/user?key=2c90931b6cfb654f016d5c69becc0001"},"_expandable":{"status":""}},"when":"2022-07-09T01:51:25.000Z","message":"","number":1,"minorEdit":false,"hidden":false,"_links":{"self":"https://wiki.suncaper.net/rest/experimental/content/58954529/version/1"},"_expandable":{"content":"/rest/api/content/58954529"}},"body":{"storage":{"value":"<p>QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等。<br /><ac:image ac:height=\"338\" ac:width=\"554\"><ri:attachment ri:filename=\"worddav9b42e5e98bb8f7387dffe165721c8ca7.png\" /></ac:image></p><h1><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"c128408e-648f-4d9b-ad62-209de5e5e4ba\"><ac:parameter ac:name=\"\">_Toc466556778</ac:parameter></ac:structured-macro><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"840b3a66-1880-472e-98e3-a56f9c559d7d\"><ac:parameter ac:name=\"\">_Toc471842005</ac:parameter></ac:structured-macro>5.1 菜单栏</h1><p>一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。</p><ul><li>创建菜单栏,通过QMainWindow类的menubar()函数获取主窗口菜单栏指针</li></ul><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"b4863e90-8a1a-4cbf-8475-1adbd516ff9d\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[QMenuBar *menuBar() const]]></ac:plain-text-body></ac:structured-macro><p><br /></p><ul><li>创建菜单,调用QMenu的成员函数addMenu来添加菜单</li></ul><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"199403aa-ccfc-41e7-89dd-ce1382a64ae3\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[QAction* addMenu(QMenu * menu)\nQMenu* addMenu(const QString & title)\nQMenu* addMenu(const QIcon & icon, const QString & title)]]></ac:plain-text-body></ac:structured-macro><p><br /></p><ul><li>创建菜单项,调用QMenu的成员函数addAction来添加菜单项</li></ul><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"bc2e0cd8-910c-41b0-afb9-34a56f42f24f\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[QAction* activeAction() const\nQAction* addAction(const QString & text)\nQAction* addAction(const QIcon & icon, const QString & text)\nQAction* addAction(const QString & text, const QObject * receiver,\nconst char * member, const QKeySequence & shortcut = 0)\nQAction* addAction(const QIcon & icon, const QString & text,\nconst QObject * receiver, const char * member,\nconst QKeySequence & shortcut = 0)]]></ac:plain-text-body></ac:structured-macro><p><br />Qt 并没有专门的菜单项类,只是使用一个QAction类,抽象出公共的动作。当我们把QAction对象添加到菜单,就显示成一个菜单项,添加到工具栏,就显示成一个工具按钮。用户可以通过点击菜单项、点击工具栏按钮、点击快捷键来激活这个动作。</p><h1><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"03bf87f9-6591-432c-b269-29a513cdf6e5\"><ac:parameter ac:name=\"\">_Toc466556779</ac:parameter></ac:structured-macro><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"93db63da-7629-4f03-9870-a6599a98d270\"><ac:parameter ac:name=\"\">_Toc471842006</ac:parameter></ac:structured-macro>5.2 工具栏</h1><p>主窗口的工具栏上可以有多个工具条,通常采用一个菜单对应一个工具条的的方式,也可根据需要进行工具条的划分。</p><ul><li><ul><li>直接调用QMainWindow类的addToolBar()函数获取主窗口的工具条对象,每增加一个工具条都需要调用一次该函数。</li><li>插入属于工具条的动作,即在工具条上添加操作。</li></ul></li></ul><p>通过QToolBar类的addAction函数添加。</p><ul><li><ul><li>工具条是一个可移动的窗口,它的停靠区域由QToolBar的allowAreas决定,包括:<ul><li>Qt::LeftToolBarArea 停靠在左侧</li><li>Qt::RightToolBarArea 停靠在右侧</li><li>Qt::TopToolBarArea 停靠在顶部</li><li>Qt::BottomToolBarArea 停靠在底部</li><li>Qt::AllToolBarAreas 以上四个位置都可停靠</li></ul></li></ul></li></ul><p><span style=\"color: rgb(255,0,0);\"><strong>使用setAllowedAreas()函数指定停靠区域:</strong></span><br />setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea)<br /><span style=\"color: rgb(255,0,0);\"><strong>使用setMoveable()函数设定工具栏的可移动性:</strong></span><br />setMoveable(false)//工具条不可移动, 只能停靠在初始化的位置上</p><h1><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"a3787113-9691-413e-8e09-336dc782fd0c\"><ac:parameter ac:name=\"\">_Toc466556780</ac:parameter></ac:structured-macro><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"44455282-64e7-46f5-8330-c7971beb7225\"><ac:parameter ac:name=\"\">_Toc471842007</ac:parameter></ac:structured-macro>5.3 状态栏</h1><ul><li><ul><li>派生自QWidget类,使用方法与QWidget类似,QStatusBar类常用成员函数:</li><li>状态栏也只能最多有一个</li></ul></li></ul><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"c244a5c3-f16a-4ba1-8355-8aa4544a167e\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[//添加小部件\nvoid addWidget(QWidget * widget, int stretch = 0)\n//插入小部件\nintinsertWidget(int index, QWidget * widget, int stretch = 0)\n//删除小部件\nvoid removeWidget(QWidget * widget)]]></ac:plain-text-body></ac:structured-macro><p><br /></p><h1><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"608891e8-20e4-4b2c-adbd-e18116b3e261\"><ac:parameter ac:name=\"\">_Toc471842008</ac:parameter></ac:structured-macro>5.4 铆接部件</h1><p>铆接部件 QDockWidget,也称浮动窗口,可以有多个。</p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"2b147fa9-dab1-4e8e-ad3d-0b09a619919d\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[QDockWidget * dock = new QDockWidget(\"标题\",this);\n addDockWidget(Qt::LeftDockWidgetArea,dock);\ndock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::TopDockWidgetArea); 设置区域范围\n\n]]></ac:plain-text-body></ac:structured-macro><p><br /></p><h1><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"807c9042-90f9-4d77-9600-b2f946a149df\"><ac:parameter ac:name=\"\">_Toc471842009</ac:parameter></ac:structured-macro>5.5 核心部件(中心部件)</h1><p>除了以上几个部件,中心显示的部件都可以作为核心部件,例如一个记事本文件,可以利用QTextEdit做核心部件</p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"5aad65bd-0588-4fe6-84f5-c2ab1cda99f6\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[QTextEdit * edit = new QTextEdit(this);\nsetCentralWidget(edit);]]></ac:plain-text-body></ac:structured-macro><p><br /></p><h1><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"50866164-c7ad-43a6-bcb8-ef130db2a765\"><ac:parameter ac:name=\"\">_Toc466556781</ac:parameter></ac:structured-macro><ac:structured-macro ac:name=\"anchor\" ac:schema-version=\"1\" ac:macro-id=\"947c7e1c-e28e-4cf6-a5d9-1258030d3e93\"><ac:parameter ac:name=\"\">_Toc471842010</ac:parameter></ac:structured-macro>5.6 资源文件</h1><p>Qt 资源系统是一个跨平台的资源机制,用于将程序运行时所需要的资源以二进制的形式存储于可执行文件内部。如果你的程序需要加载特定的资源(图标、文本翻译等),那么,将其放置在资源文件中,就再也不需要担心这些文件的丢失。也就是说,如果你将资源以资源文件形式存储,它是会编译到可执行文件内部。<br />使用 Qt Creator 可以很方便地创建资源文件。我们可以在工程上点右键,选择"添加新文件…",可以在 Qt 分类下找到"Qt 资源文件":<br /><ac:image ac:height=\"363\" ac:width=\"554\"><ri:attachment ri:filename=\"worddav3b0a1c80e37ec398ff648ce0d49483ed.png\" /></ac:image><br />点击"选择…"按钮,打开"新建 Qt 资源文件"对话框。在这里我们输入资源文件的名字和路径:<br /><ac:image ac:height=\"390\" ac:width=\"500\"><ri:attachment ri:filename=\"worddav73de1fec3944b04ddc4660fde30dbfba.png\" /></ac:image><br />点击下一步,选择所需要的版本控制系统,然后直接选择完成。我们可以在 Qt Creator 的左侧文件列表中看到"资源文件"一项,也就是我们新创建的资源文件:<br /><ac:image ac:height=\"372\" ac:width=\"554\"><ri:attachment ri:filename=\"worddavee749b00269024f61bf453911badb027.png\" /></ac:image><br />右侧的编辑区有个"添加",我们首先需要添加前缀,比如我们将前缀取名为 images。然后选中这个前缀,继续点击添加文件,可以找到我们所需添加的文件。这里,我们选择 document-open.png 文件。当我们完成操作之后,Qt Creator 应该是这样子的:<br /><ac:image ac:height=\"372\" ac:width=\"554\"><ri:attachment ri:filename=\"worddavee749b00269024f61bf453911badb027.png\" /></ac:image><br />接下来,我们还可以添加另外的前缀或者另外的文件。这取决于你的需要。当我们添加完成之后,我们可以像前面一章讲解的那样,通过使用 : 开头的路径来找到这个文件。比如,我们的前缀是 /images,文件是 document-open.png,那么就可以使用:/images/document-open.png找到这个文件。<br />这么做带来的一个问题是,如果以后我们要更改文件名,比如将 docuemnt-open.png 改成 docopen.png,那么,所有使用了这个名字的路径都需要修改。所以,更好的办法是,我们给这个文件去一个"别名",以后就以这个别名来引用这个文件。具体做法是,选中这个文件,添加别名信息:<br /><ac:image ac:height=\"373\" ac:width=\"554\"><ri:attachment ri:filename=\"worddavb6104d0fb8ff6f98444cbde67b63060e.png\" /></ac:image><br />这样,我们可以直接使用:/images/doc-open引用到这个资源,无需关心图片的真实文件名。<br />如果我们使用文本编辑器打开 res.qrc 文件,就会看到一下内容:</p><ac:structured-macro ac:name=\"code\" ac:schema-version=\"1\" ac:macro-id=\"4c580f72-8f90-485c-8246-122666613f00\"><ac:parameter ac:name=\"language\">cpp</ac:parameter><ac:plain-text-body><![CDATA[<RCC>\n<qresource prefix=\"/images\">\n<file alias=\"doc-open\">document-open.png</file>\n</qresource>\n<qresource prefix=\"/images/fr\" lang=\"fr\">\n<file alias=\"doc-open\">document-open-fr.png</file>\n</qresource>\n</RCC>]]></ac:plain-text-body></ac:structured-macro><p><br />我们可以对比一下,看看 Qt Creator 帮我们生成的是怎样的 qrc 文件。当我们编译工程之后,我们可以在构建目录中找到 qrc_res.cpp 文件,这就是 Qt 将我们的资源编译成了 C++ 代码。</p><div style=\"left: -11.0px;top: 4513.0px;\"><div class=\"gtx-trans-icon\"><br /></div></div>","representation":"storage","_expandable":{"content":"/rest/api/content/58954529"}},"_expandable":{"editor":"","view":"","export_view":"","styled_view":"","anonymous_export_view":""}},"extensions":{"position":29},"_links":{"webui":"/display/2CT/5+QMainWindow","edit":"/pages/resumedraft.action?draftId=58954529","tinyui":"/x/IZODAw","collection":"/rest/api/content","base":"https://wiki.suncaper.net","context":"","self":"https://wiki.suncaper.net/rest/api/content/58954529"},"_expandable":{"container":"/rest/api/space/2CT","metadata":"","operations":"","children":"/rest/api/content/58954529/child","restrictions":"/rest/api/content/58954529/restriction/byOperation","history":"/rest/api/content/58954529/history","ancestors":"","descendants":"/rest/api/content/58954529/descendant","space":"/rest/api/space/2CT"}} |