【Qt】常用控件(四)QWidget的windowOpacity,cursor,font属性
小编个人主页详情—请点击小编个人gitee代码仓库—请点击Qt系列专栏—请点击倘若命中无此运孤身亦可登昆仑送给屏幕面前的读者朋友们和小编自己!目录前言一、QWidget的windowOpacity属性理论讲解代码实现二、QWidget的cursor属性原理讲解代码实现三、QWidget的font属性原理讲解代码实现总结前言【Qt】常用控件三window frame窗口框架QWidget的windowTitlewindowIcon属性qrc机制——书接上文 详情请点击——本文由小编为大家介绍——【Qt】常用控件四QWidget的windowOpacitycursorfont属性一、QWidget的windowOpacity属性理论讲解那么要谈及QWidget的windowOpacity属性就要先来谈一下半透明效果早在很久之前微软推出了Windows Vista这个操作系统极具特色的就是用于给电脑设置毛玻璃效果即基于半透明再设置一些效果那么我们可以看到如上的小工具库就是半透明的效果显得十分的高级但是很不幸这种设计在当初的电脑cpu 2核内存1-2G的系统上跑容易导致系统比较卡所以当初也就没有流行起来后面微软推出了Windows7其中就有对Windows Vista的一些精简并且进行一定的优化使Windows7运行起来流畅并且也很高级大受欢迎那么QWidget中的windowOpacity属性和控件的不透明度有关与之相关的有两个API1windowOpacity()用于获取到控件的不透明数值返回值是一个float取值为0.0到1.0之间的数其中0.0表示全透明1.0表示完全不透明即我们可以看出数值越大越不透明2setWindowOpacity(float n)用于设置控件的不透明数值代码实现所以接下来我们就来实现一个GUI程序含有两个按钮用于调整控件Widget窗口的不透明度一个按钮用于加不透明度另一个按钮用于减不透明度所以此时我们来创建一个项目名为QWidget_8基类为QWidget派生类为Widget的项目那么我们点击ui文件然后进行Qt Designer界面接下来我们左侧拖拽两个按钮然后修改按钮显示的文本为另一个按钮修改显示的文本-选中 按钮那么在右侧将按钮的objectName修改成pushButton_add那么同理将 - 按钮的objectName修改成pushButton_sub接下来右击这两个按钮然后点击转到槽选择无参的clicked信号函数即可让Qt帮我们生成槽函数的声明和定义#ifndefWIDGET_H#defineWIDGET_H#includeQWidgetQT_BEGIN_NAMESPACEnamespaceUi{classWidget;}QT_END_NAMESPACEclassWidget:publicQWidget{Q_OBJECTpublic:Widget(QWidget*parentnullptr);~Widget();privateslots:voidon_pushButton_add_clicked();voidon_pushButton_sub_clicked();private:Ui::Widget*ui;};#endif// WIDGET_H#includewidget.h#includeui_widget.h#includeQDebugWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);}Widget::~Widget(){deleteui;}voidWidget::on_pushButton_add_clicked(){floatopacitythis-windowOpacity();if(opacity1.0)return;qDebug()opacity;opacity0.1;this-setWindowOpacity(opacity);}voidWidget::on_pushButton_sub_clicked(){floatopacitythis-windowOpacity();if(opacity0.0)return;qDebug()opacity;opacity-0.1;this-setWindowOpacity(opacity);}那么在增加不透明度的槽函数on_pushButton_add_clicked中我们首先使用windowOpacity获取当前窗口的不透明度opacity然后进行判断如果窗口的不透明度大于等于1.0说明此时窗口已经完全不透明了那么此时我们也就没有必要调用setWindowOpacity去增加窗口的不透明度了因为窗口的不透明度对应的数值最大就为1.0所以此时我们直接返回即可否则就说明此时窗口的不透明度小于1.0那么接下来我们就打印日志然后对不透明度capcity加0.1然后调用setWindowOpacity将不透明度capcity设置进Widget属性中去增加窗口的不透明度那么在减少不透明度的槽函数on_pushButton_sub_clicked也是同样的道理首先使用windowOpacity获取当前窗口的不透明度opacity然后进行判断如果窗口的不透明度小于等于0.0说明此时窗口已经完全透明了那么此时我们也就没有必要调用setWindowOpacity去减少窗口的不透明度了因为窗口的不透明度对应的数值最小就为0.0所以此时我们直接返回即可否则就说明此时窗口的不透明度大于等于0.0那么接下来我们就打印日志然后对不透明度capcity减0.1然后调用setWindowOpacity将不透明度capcity设置进Widget属性中去减少窗口的不透明度运行结果如下所以此时运行结果如上我们点击 - 按钮可以将Widget界面的不透明度减少0.1那么随着小编的不断按下 - 按钮此时Widget界面的不透明度就减少为0.0即此时已经完全不透明换句话来说也就是完全透明了那么如上图小编再继续点击 - 按钮的时候此时就无法进行点击了而是点击到了代码编辑区即如果 Widget 窗口界面的不透明度变为0.0那么此时的Widget界面就是真的透明了即鼠标无法点击到Widget窗口了同理此时我们再去按 按钮也无法增加不透明度了那么这时候我们可以点击下方的任务栏然后右击Widget程序点击关闭窗口即可其中在这个过程中有两个值得我们注意的问题如下虽然我们当初是按照0.1进行加减的窗口的不透明度opacity但是对于日志打印出来的float类型的不透明度opacity的变化却不是精确的那么这是由于什么缘故呢其实是由于不透明度opacity这个变量的类型是float类型关于float浮点数的讲解 第四点浮点型在内存中的存储详情请点击——所以我们知道了IEEE 754标准规定浮点数要使用二进制的科学计数法来进行表示所以由于float和double这样的浮点数的长度都都十分有限的进而导致浮点数float和double对于小数无法精确表示所以自然的对于小数的加减也无法做到精确的进行加减所以这里虽然我们当初是按照0.1进行加减的窗口的不透明度opacity也不是精确的所以对于日志打印出来的float类型的不透明度opacity的变化却不是精确的所以对于浮点数这样的数据类型自然的它就有优缺点了1它的优点是运算速度快占用空间小因为CPU在进行制造的时候针对这种运算专门做了优化2它的缺点是对于有些小数无法精确表示所以平时写代码的时候不要直接将浮点数进行比较例如下面这种情况#includeiostreamusingnamespacestd;intmain(){if(0.10.20.3)couttrueendl;elsecoutfalseendl;return0;}运行结果如下所以对于0.1 0.2 0.3输出的结果居然是false所以平时写代码千万不要将两个浮点数使用进行比较那么正确的写法应该是进行作差判定差的绝对值小于误差范围#includeiostreamusingnamespacestd;intmain(){if(fabs((0.10.2)-0.3)1e-6)couttrueendl;elsecoutfalseendl;return0;}那么如上图我们将((0.10.2) - 0.3)计算后的值使用fabs取绝对值这里为什么不使用abs取绝对值呢因为abs取绝对值是给整数使用的而这里的((0.10.2) - 0.3)计算后的结果是一个浮点数对于浮点数取绝对值要使用fabs进行取绝对值那么使用fabs绝对值之后的结果应该小于一个数这个数我们我们认为是1e-61e-6也是浮点数比较里所允许的最大误差1e-6也就科学计数法表示0.000001百万分之一即两个浮点数相减取绝对值误差只要小于这里的百万分之一我们就认为两个浮点数相等运行结果如下所以对于后续实际开发中尤其是涉及到一些需要精确计算的场景比如算钱那么我么一定要慎重使用float和double我们可以考虑转到整数进行计算即将元换算到分进行整数的计算即可那么第二个问题实际上在进行使用setWindowOpacity设置Widget控件的windowOpacity属性的时候以 按钮对应的槽函数为例我们使用了if语句进行判断不透明度opacity如果大于等于0那么我们就直接返回其实对于这个if语句的判断我们可以不写因为setWindowOpacity内部是进行了判定如果超过1.0的不透明度是设置不进去的那么我们是可以来验证一下的#includewidget.h#includeui_widget.h#includeQDebugWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);}Widget::~Widget(){deleteui;}voidWidget::on_pushButton_add_clicked(){floatopacitythis-windowOpacity();// if(opacity 1.0)// return;qDebug()opacity;opacity0.1;this-setWindowOpacity(opacity);}voidWidget::on_pushButton_sub_clicked(){floatopacitythis-windowOpacity();if(opacity0.0)return;qDebug()opacity;opacity-0.1;this-setWindowOpacity(opacity);}所以如上我们将 按钮对应的槽函数中将if语句的判断注释掉运行结果如下如上无论小编点击多少次 按钮那么由于setWindowOpacity内部进行了判断所以大于1.0的不透明度是设置不进去的所以也就代表着即使我们在setWindowOpacity外部不进行判断也是没问题的那么此时问题来了为什么我们还要在setWindowOpacity外部再次进行判断呢其实在《代码大全》这本书中就进行了详尽的解释术语叫做防御性编程那么小编类比一下防御性驾驶如果我们系好安全带在马路上开车行驶突然对向车道有一辆车撞向我们我们来不及反应被撞了结果是安全带系好了安全气囊正常弹出我们没有什么事情那么在这个过程中我们有没有犯错我们没有犯错我们不仅没有犯错你还系好了安全带所以即使对方车辆撞向你我们也不至于被撞的从车窗飞出去因为我们系好了安全带并且安全气囊弹出我们是安全的那么对方有没有犯错很明显对方都撞我们了对方肯定犯错了所以我们系安全带的行为就叫做防御性驾驶即使别人犯错了对我们自身不会造成很大的伤害同样的防御性编程也是同样的道理那么在实际开发中我们写代码的时候往往是把一个大的项目拆分成几个模块然后由不同的人负责完成模块之间要进行交互那么模块A提供API(函数类)给模块B使用同理模块B也要提供API(函数类)给模块A进行使用所以双方就会进行相互调用那么我们使用别人提供的API进行调用的时候是否要对传入的参数进行检查呢例如参数是一个指针类型那么在调用API的时候我们是否知道我们要传入的这个指针是否是nullptr呢不知道那么我们是否可以确定提供API的一方在函数内部对指针为nullptr的情况进行了判断呢不知道按道理来讲对方应该在函数内部对指针进行判空可是别忘了是人总是会犯错误的对方由于疏忽在函数内部忘记了对指针进行判空如果此时我们在调用函数指针不对指针进行判空那么如果指针为空直接传入进去就会有问题所以此时该如何做呢代码大全给出的结论是要进行双重判定(double check)那么我们使用双重判定我们在函数调用之前就进行判断指针是否为空对方在函数内部对指针是否为空进行判断所以也就意味任何一方出现错误都不会产生严重的后果如果我们不进行遵守那么有可能年终奖会被一键带走的喔那么实际上这种双重判定是比较冗余的那么如果确定程序由我独立开发并且程序逻辑比较简单不容易出错那么这种情况下我们就可以不采用双重判定灵活一点我们仅仅在函数内部进行判定即可二、QWidget的cursor属性原理讲解QWidget的cursor属性是和光标的形状有关每一个控件都有属于自己的cursor属性当鼠标悬停在该控件上的时候就会显示出对应的光标的形状与之相关的有三个API1cursor()获取到当前控件的cursor属性此时就会返回QCursor对象2setCursor(const QCursor cursor)用于设置控件上光标的形状3QGuiApplication::setOverrideCursor(const QCursor cursor)用于设置全局的光标形状这里的全局是程序内的全局不是系统级别的全局那么对整个程序中所有的控件都会有效并且优先级高于控件自己的cursor属性也就是说即使控件通过setCursor设置了自己的cursor属性但是如果使用了setOverrideCursor设置了程序的光标形状那么此时当鼠标悬停在该控件上的时候就会显示setOverrideCursor的设置的光标形状那么此时我们总的来看对于cursor和setCursor这两个API是控件级别的即同一个界面中不同的控件可以设置成不同的光标而对于setOverrideCursor这个API来讲是程序级别的我们实际使用场景中使用的较少我们也就不再讲解感兴趣的读者友友可以自行验证那么这里我们主要讲解前两个控件级别的API即cursor和setCursor代码实现那么此时我们创建一个项目名为QWidget_9基类为QWidget派生类为Widget的项目那么关于控件光标的设置有两种方法第一种是图形化的方式第二种是代码的方式所以接下来我们先讲解图形化的方式那么首先我们点击ui文件然后拖拽Push Button按钮到界面上修改按钮显示的文本为按钮接下来我们要实现的是当光标放在Widget这个控件上显示的是仍然是箭头保持不变那么当光标放在按钮上的时候光标的形状变成十字也就类似于枪战游戏的准星所以此时我们鼠标点击按钮然后右下角的属性中找到cursor然后点击右侧的下拉框选中十字即可此时我们也就实现了对按钮控件光标形状的设置运行结果如下那么程序运行当我们将光标放到Widget控件上的时候光标仍然是箭头那么当我们将光标放到按钮上的时候光标此时就会变成十字接下来我们将按钮对应的光标形状调整回箭头然后使用代码的方式实现那么在使用代码方式实现之前我们首先需要认识一下Qt内置的光标形状对应的代码如上就是小编查找Qt的官方帮助文档的光标和代码之间的对照图那么如上我们要进行使用的是红框对应的十字那么十字对应的代码是Qt::CrossCursor那么我们要实现的是当光标放在Widget控件上的时候是十字当光标放在按钮上的时候仍然保持箭头由于在图形化那里我们已经将按钮调整回了箭头所以在代码实现这里我们不需要对按钮进行设置仅需要设置Widget控件的光标cursor属性为十字即可#includewidget.h#includeui_widget.h#includeQCursorWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);QCursorcursor(Qt::CrossCursor);this-setCursor(cursor);}Widget::~Widget(){deleteui;}所以我们在Widget的构造函数中定义QCursor对象cursor然后将Qt::CrossCursor进行传参this指针指向的是Widget对象w所以我们这里使用this指针调用setCursor将cursor设置进行即可所以此时就实现了当光标放在Widget控件上的时候光标形状为十字当光标放在按钮上的时候光标形状为箭头运行结果如下所以如上当程序运行的时候我们将光标放在Widget控件上的时候光标形状为十字当光标放在按钮上的时候光标形状为箭头其实我们还有一种方法可以查看Qt中内置的光标对应的代码那么就是按住ctrl鼠标点击这里的CrossCursor如上可是这种方式查看的光标代码没有对照的光标进行查看较为不便我们还是更推荐在Qt的官方文档中搜索CrossCursor进行查看其实我们来看上述Qt中内置的光标形状相对来讲较为古老有年代感那么对于我们现在来讲如果我们想要将自定义的图片设置成光标那么是否可以呢https://www.iconfont.cn/可以Qt允许我们通过自定义的图片来设置光标的形状那么接下来我们创建一个项目名为QWidget_10基类为QWidget派生类为Widget的项目所以此时我们就要来准备一个图片了那么这里小编给大家推荐一个找图标的网站叫做阿里巴巴矢量图标库链接如上大家想要使用什么图标去这个网站上进行搜索即可这个阿里巴巴矢量图标库是开源的即可以供我们免费下载那么这里小编已经准备好了一个生气的图标由于路径中不能带中文所以我们将生气修改为angry即可那么同样的我们需要将这个图片导入到项目中以qrc的形式进行管理那么关于如何导入小编在后面的蓝字链接对应的文章已经进行了详尽的讲解这里就不再赘述了第四点qrc机制的讲解详情请点击——所以此时在界面中观察到如上形式代表我们已经导入成功了那么接下来我们就要在代码中访问到这个图片然后基于这个图片构造光标对象并设置进Widget控件中#includewidget.h#includeui_widget.hWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);QPixmappixmap(:/angry.png);QCursorcursor(pixmap);this-setCursor(cursor);}Widget::~Widget(){deleteui;}那么我们该如何访问到一个qrc中的图片呢我们通常使用QPixmap进行访问那么定义QPixmap对象然后传入图片路径即可由于是qrc文件中的路径所以我们使用 : 作为前缀然后跟上路径即前缀图片文件名合起来就是:/angry.png所以此时如上我们使用QPixmap访问到qrc文件中angry.png图片之后接下来我们就使用pixmap这个图片对象去构造QCursor光标对象cursor然后将光标对象通过setCursor设置进Widget控件中即可运行结果如下嘶~小编这个Widget上的光标对应的图片给我的感觉是有点大呀那么我们是否可以通过函数对这个图片进行缩放呀可以的那么通过QPixmax的成员函数scaled即可#includewidget.h#includeui_widget.hWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);QPixmappixmap(:/angry.png);pixmappixmap.scaled(1000,1000);QCursorcursor(pixmap);this-setCursor(cursor);}Widget::~Widget(){deleteui;}那么通过调用QPixmap对象pixmap中的scaled(width, height)即可对光标图片进行缩放参数为像素那么第一个参数为宽度第二个参数为高度所以此时我们先传入1000,1000看看效果那么值得注意的是scaled缩放的不是图片对象本身而是缩放的图片对象拷贝的副本所以我们将缩放后的图片副本赋值给原来的图片对象即可运行结果如下嘶~小编小编看来这好像更大了是的#includewidget.h#includeui_widget.hWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);QPixmappixmap(:/angry.png);pixmappixmap.scaled(50,50);QCursorcursor(pixmap);this-setCursor(cursor);}Widget::~Widget(){deleteui;}所以我们调整小一点那么传参50,50其实就足够了运行结果如下那么我们观察代码中我们知道我们有了光标之后是要进行点击的那么QCursor cursor(pixmap)这种方式进行传参默认情况下鼠标点击时相当于图片的左上角在进行点击所以我们想要点击的位置更加适中一点那么我们在QCursor cursor(pixmap)构造光标对象的时候继续在参数中传参一个热点坐标即可#includewidget.h#includeui_widget.hWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);QPixmappixmap(:/angry.png);pixmappixmap.scaled(50,50);QCursorcursor(pixmap,25,25);this-setCursor(cursor);}Widget::~Widget(){deleteui;}所以此时如上图片的尺寸为50 x 50那么我们想让光标对应的热点适中那么我们就传入一个25, 25即可即这个25, 25就是热点所在的位置以图片左上角0, 0为原点找到25, 25这个位置作为鼠标真正点击的位置运行结果如下所以运行结果如上那么其实我们是没办法看出什么效果的因为在Widget窗口上小编没有设置任何用于点击的子控件所以感兴趣的读者友友可以自行设置一个按钮点击试试看三、QWidget的font属性原理讲解QWidget的font属性和当前控件的字体有关与之关联的有两个API1font()用于获取当前控件的字体信息会返回一个QFont对象2setFont(const QFont font)用于设置当前控件的字体信息那么其实我们更为通俗的用法是设置一个QFont对象然后调用QFont的方法进行对QFont对象的字体信息进行设置然后再调用setFont将QFont对象设置进控件的字体信息中所以此时我们就该讲解QFont类的常用方法了与之关联的有7个API1family字体家族也就是这个字体是使用哪种字体比如微软雅黑仿宋楷体等调用接口setFamily进行设置2pointSize字体大小单位是像素px调用接口setPointSize进行设置3weight字体粗细通过数值的方式表示粗细程度[0, 99]数值是0到99数值越大字体越粗当然对于使用数值我们其实不好把握所以在实际中我们对于weight不怎么使用调用接口setWeight进行设置那么对于加粗我们通常使用bold4bold字体是否加粗如果设置为true那么表示加粗相当于weight设置为75如果设置为false那么表示不加粗维持weight默认的50调用接口setBold进行设置5italic字体是否倾斜如果设置为true那么表示倾斜如果设置为false那么表示不倾斜调用接口setItalic进行设置6underline字体是否有下划线如果设置为true那么表示设置下划线如果设置为false那么表示不设置下划线调用接口setUnderline进行设置7strikeOut字体是否有删除线如果设置为true那么表示设置删除线如果设置为false那么表示不设置删除线调用接口setStrikeOut进行设置那么如上这些属性我相信大家已经很了解了所以小编就不再逐一介绍了那么关于具体属性如何进行设置那么在实际开发中往往由美工来进行确定那么我们如果想要看一下别人如何进行设置的例如网页中那么该如何做呢所以我们打开哔哩哔哩然后鼠标左击网页点击检查然后我们点击左侧边栏的右上角也就是上面小编使用红色框框出来的位置所以此时鼠标悬停在王者荣耀听安上面那么此时我们就可以看到相关的字体信息所以此时我们如果想要自己设置类似的风格的字体的话就可以参考一下代码实现所以如果我们想要设置一个控件的字体那么同样的有两种方式第一种是图形化界面的方式第二种是代码的方式所以下面我们先来介绍一下图形化的方式所以此时我们创建一个项目名为QWidget_11基类为QWidget派生类为Widget的项目那么我们从左侧拖拽一个Label标签控件然后设置文本内容为这是一段文本那么在右侧的属性中我们就可以找到font然后展开就可以对Label标签控件显示的文本进行设置了运行结果如下那么我们选择仿宋字体然后字体大小设置为30接下来依次设置粗体斜体下划线删除线之后运行代码即可将我们调整的字体进行显示那么其实我们可以看出Qt Designer可以对界面上控件属性的设置支持实时预览当我们修改了什么属性之后就可以立即显示出来这个设计很优秀但是通过属性编辑这样的方式虽然可以快速方便的修改文字的相关属性但是还不够灵活如果想到达到在程序运行的过程中修改文字的相关属性这时候就需要通过代码来进行操作了所以接下来我们来演示一下通过代码来修改文字的相关属性那么此时我们创建一个项目名为QWidget_12基类为QWidget派生类为Widget的项目#includewidget.h#includeui_widget.h#includeQLabelWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);QLabel*labelnewQLabel(this);label-move(200,200);label-setText(这是一段文本);QFont font;font.setFamily(仿宋);font.setPointSize(30);font.setBold(true);font.setItalic(true);font.setUnderline(true);font.setStrikeOut(true);label-setFont(font);}Widget::~Widget(){deleteui;}那么接下来我们在构造函数中创建Label对象label并且指定父对象为Widget对象w也就是传入this挂接到对象树上那么我们设置标签的位置并且设置标签要显示的文本那么接下来我们就创建QFont字体对象font然后依次调用对应的接口设置仿宋字体然后设置字体大小设置为30接下来依次设置粗体斜体下划线删除线接下来我们调用setFont将QFont的字体对象font设置进QLabel标签label中即可运行结果如下那么此时如上标签显示的文本就是我们预想的字体格式了同样的我们上述代码可以在构造函数中写那么是否可以写到其它的成员函数中呢是可以的因此代码的方式设置字体更为灵活所以此时我们就可以设置几个按钮按钮的点击信号关联槽函数那么槽函数的作用分别有调整字体调整字体大小调整字体是否加粗调整字体是否有下划线调整字体是否有删除线等作用那么此时程序运行起来之后就可以点击不同作用的按钮对字体进行一个更灵活的调整总结以上就是今天的博客内容啦,希望对读者朋友们有帮助水滴石穿坚持就是胜利读者朋友们可以点个关注点赞收藏加关注找到小编不迷路