【Qt常用控件】WindowTitle 与 WindowIcon:窗口标题和图标 上一章节我们讲完了 Window Frame 对geometry的影响本章节我们继续来认识QWidget的另外两个核心属性——WindowTitle窗口标题和WindowIcon窗口图标。这俩属性用法上有不少共通之处也有一些容易踩坑的地方咱们一并聊清楚。一、WindowTitle窗口标题1.1 它是干嘛的这个东西我们前面其实也举过例子了。通过WindowTitle这个属性可以来设置窗口的标题一方面我们可以直接通过windowTitle()来获取当前窗口标题是什么另一方面也可以通过setWindowTitle()来修改窗口标题参数就是我们前面交代过的QString1.2 只对顶层窗口有效重点这里大家要注意窗口标题这件事情不是你给所有的Widget设置都有效。当前我们的windowTitle属性以及这两个方法它是从属于QWidget的。而QWidget是一个非常广泛的概念——你一个按钮是一个QWidget一个输入框也是一个QWidget同时你这个窗口也是一个QWidget。但是windowTitle属性只能针对顶层窗口这样的QWidget才有效。如果你给窗口里面的一个什么按钮、或者输入框设置windowTitle它是不具备任何效果的。这点非常关键谁才是那个窗口我们才能给谁去设置。二、代码实操给窗口和按钮分别设置标题从这里开始是实操部分。以下实操需要你亲自动手完成——创建项目、写代码、运行验证。【实操 1】验证 WindowTitle 只对顶层窗口生效目标给顶层窗口设置标题生效再给按钮设置标题不生效也不报错观察现象。第一步创建项目操作新建项目QWidget_6基类选QWidget一路下一步完成。第二步编写代码代码参考#includewidget.h#includeui_widget.h#includeQPushButton// 别忘了包含头文件Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 1. 给顶层窗口this设置标题 —— this 可以省略这里写出来更清晰this-setWindowTitle(这是窗口标题);// 2. 再创建一个按钮给按钮也设置一下 windowTitleQPushButton*buttonnewQPushButton(this);button-setText(按钮);// 给按钮设置窗口标题 —— 这一步是不科学的写法用来演示现象button-setWindowTitle(这是通过按钮设置窗口标题);}第三步运行验证验证流程运行程序观察窗口标题栏——应该显示这是窗口标题按钮上的文本显示为按钮说明按钮相关代码确实执行到了但是——给按钮设置的windowTitle没有任何效果窗口标题也没有被影响结论按钮文本都变成按钮两个字了说明给按钮设置windowTitle这一行代码确实执行到了但这一行代码的执行对窗口标题没有任何影响。主要就是——谁是那个窗口我们才能给谁去设置这点非常关键。三、静默失败为什么不科学不过这里有一个不太好的小问题你虽然给按钮这个不该设置windowTitle的地方设置了它并没有报错也没有任何错误提示只不过是什么都没有发生。3.1 静默失败的隐患这种没有报错的设定其实是不太科学的。为什么说不科学呢假设在实际开发中我们确实就想修改窗口标题但是界面比较复杂你可能搞错了——误以为某一个控件就是那个窗口就给它设置了。结果设置之后没生效你也没太注意程序又没有任何报错你以为功能实现了其实这个问题就已经埋藏下来了。3.2 报错是一件好事所以我们更希望当我们写出这种不科学的代码时它能给一些显式的报错提示。其实啊像我们以前刚开始初学编程的时候可能对新手朋友来说报错是一个非常让人头疼的问题——我一写一行代码结果出了两三个报错这个就真的特别特别恼火。但是当你代码写得多了当你具有一定的开发经验尤其是当你为你代码中的 bug 买过单之后那这个时候你就会知道——这个报错其实是一件多么好的事情。报错它确实出错了但是它出错之后就能够让我们及时地发现问题、及时地改正问题避免这个问题被拖延之后产生出一些更严重的后果——变相地帮我们保住了年终奖啊所以这一点整体来说还是我们更期望能看到的。3.3 开发建议对关键操作做校验因此同学们我们后续自己在编写代码的时候一定要确保——代码能够对一些关键性质的用户操作逻辑进行校验。如果出现一些出错的操作或者本来就不科学、不应该发生的情况一定要能够及时给出提示避免出现这种将错就错的情况。报错本质上是提前暴露问题的有效机制可以避免隐性 bug 累积引发更严重的线上问题降低后续排查与修复成本。这一点希望大家重点理解。四、WindowIcon窗口图标4.1 图标显示在哪儿接下来我们介绍下一个属性——WindowIcon它表示一个窗口的图标。这个图标是啥呢大家仔细观察一下当前运行的这些程序它们的窗口都是带有一个小图标的。可以看到两个地方窗口最左上角标题栏左边那一小块任务栏你运行一个程序任务栏这里也会显示出对应的图标不同的程序图标不一样——Chrome 浏览器是一个圆圈画图板是另外一个图标。4.2 Qt 默认图标比较丑那么我们之前所写的这些 Qt 程序它那个图标长啥样呢找个前面的项目运行一下就能看到——这个默认的图标看起来好像就比较丑并不好看。所以我们就可以使用windowIcon这样的属性来修改这个图标把它改成一个你觉得比较美观的图标。4.3 相关 APIAPI返回值说明windowIcon()QIcon获取当前窗口图标返回一个QIcon对象setWindowIcon()void设置窗口图标传入一个QIcon对象前面这个windowIcon()获取操作其实我们很少会用到——一般不会去获取图标也不会中途更改图标。setWindowIcon()才是我们主要使用的方式你这个程序提前把 logo 做好、把图标做好程序启动时就给它设置过去这样整个程序看起来就会比较好看。4.4 QIcon 是什么windowIcon()返回的是一个QIcon对象。这个东西我们前面没遇到过但同学们应该不难理解——在 Qt 中它的面向对象做得就很好。Qt 中把各种相关概念都封装成了类。这个QIcon它就表示一个图标。具体怎么用写代码一看就了解了。4.5 同样只对顶层窗口生效大家也要注意这个 API 和我们刚才说的那个WindowTitle一样——都只是针对当前的这个顶层窗口才能使用。类似于WindowTitle只能针对顶层窗口使用。你要是针对窗口内的一个普通控件来使用它是没有效果的。五、QIcon 创建规范重点写代码之前这里有一个小细节大家要注意咱们用的这个QIcon它就不能够再在堆上去new出这个对象了咱们还是尽量直接在栈上创建。5.1 为什么 QIcon 在栈上创建我们前面推荐使用堆上创建对象主要是为了——通过Qt 对象树来释放对象确保控件的生命周期足够但是对于QIcon来说它是不一样的第一QIcon自身是一个比较小的对象。我们创建出对象之后目的就是为了把它设置到某个QWidget里面。这个时候你这个QIcon对象本身释放不释放它不影响图标最终的显示。像之前我们搞的什么QPushButton如果它提前释放了最后界面上就显示不出来。但是QIcon不存在这个问题——你只要设置过去之后原来的对象就算释放了那最终这个图标也是有效的。第二QIcon并不支持对象树机制。也就是说你无法给它指定一个父对象自然也就没法让 Qt 通过对象树机制对它进行释放。所以这里我们直接把它创建在栈上就行了函数一结束自己就释放OK。5.2 头文件包含规则创建好QIcon对象之后可能会提示不完整类型——说明它不认识QIcon。这个事情也好办包含一个对应的头文件#include QIcon就行。在 Qt 中封装的这些类都会有一个同名的头文件。你哪个类找不到定义那就包含哪个类对应的头文件就行了。这一点很方便规则都是一致的不需要额外去查什么文档。后面同学们做程序设计的时候也可以参考这种设计风格。六、代码实操设置窗口图标以下实操需要你亲自动手完成。本实操只是把图标设上去关于用绝对路径加载图片不科学的问题我们留到下一篇博客专门讲——这里先看到效果即可。【实操 2】给顶层窗口设置图标目标准备一张图片用QIconsetWindowIcon把窗口默认图标替换成自定义图片。第一步准备图片操作提前准备好一张图片比如一坨小粑粑baba.png或者你喜欢的唱跳rap篮球图片都行“你们乐意设置啥就设置啥”把图片放在一个好找的路径下比如直接放在E:盘下面文件名叫baba.png注意文件名和文件路径不要带中文这点要求我们前面也说过。这里先用绝对路径下一篇我们会专门讲为什么绝对路径不科学。第二步创建项目操作新建项目QWidget_7基类选QWidget完成。第三步编写代码代码参考#includewidget.h#includeui_widget.h#includeQIcon// 用到 QIcon别忘包含头文件Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 1. QIcon 在栈上创建不要 new构造时传入图片路径// 路径用正斜杠作为分隔符避免反斜杠的转义问题QIconicon(E:/baba.png);// 2. 把图标设置到顶层窗口this-setWindowIcon(icon);}开发小贴士路径写法优先使用正斜杠/简单直接反斜杠在 C 中是转义字符如果写成D:\rose.jpg\r就被当成回车符了光标回到行首路径就错了图片加载不出来如果非要用反斜杠就写双反斜杠D:\\rose.jpg转义一下C11 还提供了RawString语法R(D:\rose.jpg)里面的字符全部不转义。但既然有正斜杠咱就没必要写那么麻烦了第四步运行验证验证流程运行程序观察窗口最左上角的图标——应该变成了你设置的那张图片观察任务栏对应程序位置——图标也应该是你设置的那张图片如果图标仍然是默认的没变化也没报错——说明图片路径写错了Qt 不会报错只会回退到默认图标这点要主动校验七、本篇小结属性作用适用范围关键 APIWindowTitle设置/获取窗口标题仅顶层窗口windowTitle()/setWindowTitle()WindowIcon设置/获取窗口图标仅顶层窗口windowIcon()/setWindowIcon()我们改上图标标题甚至可以玩点更有趣的比如说是你通过按钮链接信号槽来动态改变两个核心要点这两个属性都只对顶层窗口生效给普通子控件设置既无效果也无报错——这种静默失败不科学咱们自己写代码时要主动对关键操作做校验QIcon是个小对象、不支持对象树直接在栈上创建即可不要new那么问题来了——我们刚才用绝对路径D:/rose.jpg加载图片这种写法科学吗程序发布到用户电脑上还能用吗下一篇我们就来好好聊聊文件路径的处理方案以及 Qt 提供的终极解法——QRC 资源机制。