【QT控件】QWidget 常用核心属性介绍 -- 万字详解
目录
一、控件概述
二、QWidget 核心属性
2.1 核心属性概览
2.2 enabled
编辑
2.3 geometry
2.4 windowTitle
2.5 windowIcon
使用qrc文件管理资源
2.6 windowOpacity
2.7 cursor
2.8 font
编辑
2.9 toolTip
2.10 focusPolicy
2.11 styleSheet
QT专栏:QT_uyeonashi的博客-CSDN博客
一、控件概述
Widget 是 Qt 中的核心概念. 英文原义是 "小部件", 我们此处也把它翻译为 "控件" .
控件是构成一个图形化界面的基本要素.
像上述示例中的, 按钮, 列表视图, 树形视图, 单行输入框, 多行输入框, 滚动条, 下拉框等, 都可以称为 "控件".
Qt 作为一个成熟的 GUI 开发框架, 内置了大量的常用控件. 这一点在 Qt Designer 中就可以看到端倪.并且 Qt 也提供了 "自定义控件" 的能力, 可以让程序猿在现有控件不能满足需求的时候, 对现有控件做出扩展, 或者手搓出新的控件.
学习 Qt, 其中一个很重要的任务就是熟悉并掌握 Qt 内置的常用控件
二、QWidget 核心属性
在 Qt 中, 使用 QWidget 类表示 "控件". 像按钮, 视图, 输入框, 滚动条等具体的控件类, 都是继承自
QWidget.可以说, QWidget 中就包含了 Qt 整个控件体系中, 通用的部分.
在 Qt Designer 中, 随便拖一个控件过来, 选中该控件, 即可在右下方看到 QWidget 中的属性
这些属性既可以通过 QtDesigner 会直接修改, 也可以通过代码的方式修改.
这些属性的具体含义, 在 Qt Assistant 中均有详细介绍.
在 Qt Assistant 中搜索 QWidget, 即可找到对应的文档说明. (或者在 Qt Creator 代码中, 选中
QWidget, 按 F1 也可).
2.1 核心属性概览
下列表格列出了 QWidget 中的属性及其作用.
接下来介绍其中一些比较重要比较常用的属性
2.2 enabled
- 所谓 "禁用" 指的是该控件不能接收任何用户的输入事件, 并且外观上往往是灰色的.
- 如果一个 widget 被禁用, 则该 widget 的子元素也被禁用.
举个栗子:使用代码创建一个禁用状态的按钮
//widget.cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* btn = new QPushButton(this);btn->setText("这是个被禁用的按钮");btn->setEnabled(false);
}
栗子2: 通过按钮2 切换按钮1 的禁用状态
1) 使用 Qt Designer 拖两个按钮到 Widget 中.
两个按钮的 objectName 分别为 pushButton 和 pushButton_2
📚 QObject 的 objectName 属性介绍:
QObject 是 QWidget 的父类. 里面最主要的属性就是 objectName .
在一个 Qt 程序中, objectName 相当于对象的身份标识, 彼此之间不能重复.
在使用 Qt Designer 时, 尤其是界面上存在多个 widget 的时候, 可以通过 objectName 获取到指定的 widget 对象.
Qt Designer 生成的 ui 文件, 本身是 xml 格式的. qmake 会把这个 xml 文件转换成 C++ 的 .h文件(这个文件生成在 build 目录中), 构成一个 ui_widget 类.
每个 widget 的 objectName 最终就会成为 ui_widget 类的属性名字.
最终这个类的实例, 就是 Ui::Widget *ui , 因此就可以通过形如 ui->pushButton 或者 ui->pushButton_2 这样的代码获取到界面上的 widget 对象了.
class Ui_Widget
{
public:QPushButton *pushButton;QPushButton *pushButton_2;// ..................
}
2) 生成两个按钮的 slot 函数.
• 使用 isEnabled 获取当前按钮的可用状态.
• 使用 setEnabled 修改按钮的可用状态. 此处是直接针对原来的可用状态进行取反后设置.
void Widget::on_pushButton_clicked()
{qDebug() << "按下按钮";
}void Widget::on_pushButton_2_clicked()
{bool enable = ui->pushButton->isEnabled();if(enable)ui->pushButton->setEnabled(false);elseui->pushButton->setEnabled(true);
}
运行程序, 可以看到, 初始情况下, 上面的按钮是可用状态.
点击下方按钮, 即可使上方按钮被禁用; 再次点击下方按钮, 上方按钮就会解除禁用. (禁用状态的按钮为灰色, 且不可点击).
在 Qt Designer 中创建按钮的时候, 可以设置按钮的初始状态是 "可用" 还是 "禁用" .
如果把 enabled 这一列的对钩去掉, 则按钮的初始状态就是 "禁用" 状态.
2.3 geometry
位置和尺寸. 其实是四个属性的统称:
• x 横坐标 • y 纵坐标 • width 宽度 • height 高度
但是实际开发中, 我们并不会直接使用这几个属性, 而是通过一系列封装的方法来获取/修改.
对于 Qt 的坐标系, 不要忘记是一个 "左手坐标系". 其中坐标系的原点是当前元素的父元素的左上角.
举个栗子:控制按钮的位置
1) 在界面中拖五个按钮.
五个按钮的 objectName 分别为 pushButton_target , pushButton_up , pushButton_down , pushButton_left , pushButton_right五个按钮的初始位置和大小都随意.
2) 在 widget.cpp 中编写四个按钮的 slot 函数
void Widget::on_pushButton_up_clicked()
{QRect rect = ui->pushButton_target->geometry();rect.setY(rect.y() - 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_down_clicked()
{QRect rect = ui->pushButton_target->geometry();rect.setY(rect.y() + 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_left_clicked()
{QRect rect = ui->pushButton_target->geometry();rect.setX(rect.x() - 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_right_clicked()
{QRect rect = ui->pushButton_target->geometry();rect.setX(rect.x() + 5);ui->pushButton_target->setGeometry(rect);
}
运行程序, 可以看到, 按下下方的四个按钮, 就会控制 target 的左上角的位置. 对应的按钮整个尺寸也会发生改变.
上述代码中我们是直接设置的 QRect 中的 x, y . 实际上 QRect 内部是存储了左上和右下两个点的坐标, 再通过这两个点的坐标差值计算长宽.
单纯修改左上坐标就会引起整个矩形的长宽发生改变.
如果想让整个按钮都移动, 可以改成下列代码:
void Widget::on_pushButton_up_clicked()
{QRect rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5, rect.width(),rect.height());
}void Widget::on_pushButton_down_clicked()
{QRect rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5, rect.width(),rect.height());
}void Widget::on_pushButton_left_clicked()
{QRect rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(rect.x() - 5, rect.y(), rect.width(),rect.height());
}void Widget::on_pushButton_right_clicked()
{QRect rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(rect.x() + 5, rect.y(), rect.width(),rect.height());
}
上述代码使用 move 方法也是可以的.
栗子:一个表白程序
1) 往界面上拖拽两个按钮和一个 Label.
Label 的 objectName 为 pushButton_accept 和 pushButton_reject , label 的
objectName 为 label控件中文本如下图所示.
void Widget::on_pushButton_accept_clicked()
{ui->label->setText("来抱一下");
}void Widget::on_pushButton_reject_pressed()
{// 获取窗口的宽度和高度int width = this->geometry().width();int height = this->geometry().height();// 重新生成按钮的位置.int x = rand() % width;int y = rand() % height;// 设置新的位置ui->pushButton_reject->move(x, y);
}
运行程序, 可以看到, 当点击 "残忍拒绝" 时, 按钮就跑了.
上述代码使用的是 pressed, 鼠标按下事件. 如果使用 mouseMoveEvent, 会更狠一些, 只要鼠标移动过来, 按钮就跑了.
注意:娱乐即可,别当真
🏝 window frame 的影响
如果 widget 作为一个窗口 (带有标题栏, 最小化, 最大化, 关闭按钮), 那么在计算尺寸和坐标的
时候就有两种算法. 包含 window frame 和 不包含 window frame.
其中 x(), y(), frameGeometry(), pos(), move() 都是按照包含 window frame 的方式来计算的.
其中 geometry(), width(), height(), rect(), size() 则是按照不包含 window frame 的方式来计算的.
当然, 如果一个不是作为窗口的 widget , 上述两类方式得到的结果是一致的.
相关 API
举个栗子: 感受 geometry 和 frameGeometry 的区别.
1) 在界面上放置一个按钮.
2) 在按钮的 slot 函数中, 编写代码
void Widget::on_pushButton_clicked()
{QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << rect1;qDebug() << rect2;
}
3) 在构造函数中, 也添加同样的代码
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << rect1;qDebug() << rect2;
}
执行程序, 可以看到, 构造函数中, 打印出的 geometry 和 frameGeometry 是相同的.
但是在点击按钮时, 打印的 geometry 和 frameGeometry 则存在差异.
🏝 注意!
在构造方法中, Widget 刚刚创建出来, 还没有加入到对象树中. 此时也就不具备 Windowframe.
在按钮的 slot 函数中, 由于用户点击的时候, 对象树已经构造好了, 此时 Widget 已经具备了Window frame, 因此在位置和尺寸上均出现了差异.
如果把上述代码修改成打印 pushButton 的 geometry 和 frameGeometry , 结果就是完全相同的. 因为 pushButton 并非是一个窗口.
2.4 windowTitle
🍰 注意! 上述设置操作针对不同的 widget 可能会有不同的行为.
如果是顶层 widget (独立窗口), 这个操作才会有效.
如果是子 widget, 这个操作无任何效果.
举个栗子: 设置窗口标题
修改 widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 设置窗口标题this->setWindowTitle("这是标题");
}
2.5 windowIcon
同 windowTitle, 上述操作仅针对顶层 widget 有效.
举个栗子: 设置窗口图标
1) 先在 D 盘中放一个图片, 名字为 rose.jpg
2) 修改 widget.cpp
#include <QIcon>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建图标对象QIcon icon("d:/rose.jpg");// 设置图标this->setWindowIcon(icon);
}
注意: Windows 下路径的分隔符可以使用 / 也可以使用 \ . 但是如果在 字符串 中使用 \ , 需要写作转义字符的形式 \\ . 因此我们还是更推荐使用 / .
3) 运行程序, 可以看到窗口图标已经成为上述图片
于此同时, 程序在任务栏中的图表也发生改变.
✍ 实际开发中, 我们一般不会在代码中通过绝对路径引入图片. 因为我们无法保证程序发布后, 用户的电脑上也有同样的路径.
如果使用相对路径, 则需要确保代码中的相对路径写法和图片实际所在的路径匹配 (比如代码中写作 "./image/rose.jpg", 就需要在当前工作目录中创建 image 目录, 并把 rose.jpg 放进去).
绝对路径: 以盘符(windows)或者以 / (Linux) 开头的路径.
相对路径: 以 . (表示当前路径) 或者 以 .. (表示当前路径上级路径) 开头的路径. 其中 . 经常也会省略. 相对路径的前提是需要明确 "当前工作目录".
对于 Qt 程序来说, 当前工作目录可能是变化的. 比如通过 Qt Creator 运行的程序, 当前工作目录是项目的构建目录; 直接双击 exe 运行, 工作目录则是 exe 所在目录.
所谓构建目录, 是和 Qt 项目并列的, 专门用来放生成的临时文件和最终 exe 的目录.
使用qrc文件管理资源
代码示例: 获取当前的工作目录
1) 在界面上创建一个比较大的 label, 确保能把路径显示完整. objectName 使用默认的 label 即可.
2) 修改 widget.cpp
• 使用 QDir::currentPath() 即可获取到当前工作目录
#include <QDir>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 获取到当前工作目录QString currentDir = QDir::currentPath();// 设置工作目录到 label 中.ui->label->setText(currentDir);
}
3) 直接在 Qt Creator 中执行程序, 可以看到当前工作目录是项目的构建目录.
4) 进入上述构建目录, 把里面的 exe 拷贝到其他目录中, 比如 D: 中. 再次执行程序, 可以看到当前工作目录已经发生改变.
要想直接能双击 exe 运行, 需要先把 Qt 的路径添加到 path 环境变量中, 否则会提示找不到动态库.
这一点我们最开始搭建开发环境的时候已经操作过, 此处不再赘述.
注意, 上述 构建目录, 是随时可删除的. 比如点击菜单栏中的 "构建" -> "清理项目" , 就会把这个目录中的内容清空掉.
因此如果我们把图片文件放到构建目录中, 可能在不小心删除后就丢失了. 我们还是希望能够把图片和源代码放到一起, 并且使我们的程序无论拷贝到任何位置中都能正确使用图片.
Qt 使用 qrc 机制帮我们自动完成了上述工作, 更方便的来管理项目依赖的静态资源.
🎉 qrc 文件是一种XML格式的资源配置文件, 它用XML记录硬盘上的文件和对应的随意指定的资源名称. 应用程序通过资源名称来访问这些资源.
在Qt开发中, 可以通过将资源文件添加到项目中来方便地访问和管理这些资源. 这些资源文件可以位于qrc文件所在目录的同级或其子目录下.
在构建程序的过程中, Qt 会把资源文件的二进制数据转成 cpp 代码, 编译到 exe 中. 从而使依赖的资源变得 "路径无关".
这种资源管理机制并非 Qt 独有, 很多开发框架都有类似的机制. 例如 Android 的 Resources和 AssetManager 也是类似的效果.
代码示例: 通过 qrc 管理图片作为图标
1) 右键项目, 创建一个 Qt Resource File (qrc 文件), 文件名随意起(不要带中文), 此处叫做resource.qrc .
2) 在 qrc 编辑器中, 添加前缀.
此处我们前缀设置成 / 即可.
所谓的前缀, 可以理解成 "目录" . 这个前缀决定了后续我们如何在代码中访问资源.
3) 在 资源编辑器 中, 点击 add Files 添加资源文件. 此处我们需要添加的是 rose.jpg
注意: 添加的文件必须是在 qrc 文件的同级目录, 或者同级目录的子目录中. 因此我们需要把之前 D 盘中的 rose.jpg 复制到上述目录中.
添加完毕后, 可以在 资源编辑器 中看到添加好的文件
4) 在代码中使用 rose.jpg
编辑 widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 访问到 rose.jpg 资源QIcon icon(":/rose.jpg");// 设置图标this->setWindowIcon(icon);
}
注意上述路径的访问规则.
- 使用 : 作为开头, 表示从 qrc 中读取资源.
- / 是上面配置的前缀
- rose.jpg 是资源的名称
需要确保代码中编写的路径和添加到 qrc 中资源的路径匹配. 否则资源无法被访问 (同时也不会有报错提示).
5) 运行程序, 可以看到图标已经能正确设置.
接下来, 我们可以进入到项目的构建目录, 可以看到, 目录中多了一个 qrc_resource.cpp 文件. 直接打开这个文件, 可以看到类似如下代码:
static const unsigned char qt_resource_data[] = {// D:/project/ke/qt/DemoCode/DemoWindowIconQrc/rose.jpg0x0,0x0,0x33,0x2,0xff,0xd8,0xff,0xe0,0x0,0x10,0x4a,0x46,0x49,0x46,0x0,0x1,0x1,0x0,0x0,0x1,0x0,0x1,0x0,0x0,0xff,0xfe,0x0,0x3b,0x43,0x52,0x45,0x41,0x54,0x4f,0x52,0x3a,0x20,0x67,0x64,0x2d,0x6a,0x70,0x65,0x67,0x20,0x76,0x31,0x2e,0x30,0x20,0x28,0x75,0x73
,0x69,0x6e,0x67,0x20,0x49,0x4a,0x47,0x20,0x4a,0x50,0x45,0x47,0x20,0x76,0x36,0x32
,0x29,0x2c,0x20,0x71,0x75,0x61,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x39,0x35,0xa,0xff,0xdb,0x0,0x43,0x0,0x2,0x1,0x1,0x1,0x1,0x1,0x2,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x4,0x3,0x2,0x2,0x2,0x2,0x5,0x4,0x4,0x3,0x4,0x6,0x5,0x6,0x6,0x6,0x5,0x6,0x6,0x6,0x7,0x9,0x8,0x6,0x7,0x9,0x7,0x6,0x6,0x8,0xb,0x8,0x9,0xa,0xa,0xa,0xa,0xa,0x6,0x8,0xb,0xc,0xb,0xa,0xc,0x9,0xa,0xa,0xa,0xff,0xdb,0x0,0x43,0x1,0x2,0x2,0x2,0x2,0x2,0x2,
// .............
上述代码其实就是通过 unsigned char 数组, 把 rose.jpg 中的每个字节都记录下来. 这些代码会被编译到 exe 中. 后续无论 exe 被复制到哪个目录下, 都确保能够访问到该图片资源.
🌰 上述 qrc 这一套资源管理方案, 优点和缺点都很明显.
优点: 确保了图片, 字体, 声音等资源能够真正做到 "目录无关", 无论如何都不会出现资源丢失的情况.
缺点: 不适合管理体积大的资源. 如果资源比较大 (比如是几个 MB 的文件), 或者资源特别多,生成的最终的 exe 体积就会比较大, 程序运行消耗的内存也会增大, 程序编译的时间也会显著增加.
2.6 windowOpacity
代码示例: 调整窗口透明度
1) 在界面上拖放两个按钮, 分别用来增加不透明度和减少不透明度.
objectName 分别为 pushButton_add 和 pushButton_sub
2) 编写 wdiget.cpp, 编写两个按钮的 slot 函数
• 点击 pushButton_sub 会减少不透明度, 也就是窗口越来越透明.
• 点击 pushButton_add 会增加不透明度, 窗口会逐渐恢复.
void Widget::on_pushButton_add_clicked()
{float opacity = this->windowOpacity();if (opacity >= 1.0) return;qDebug() << opacity;opacity += 0.1;this->setWindowOpacity(opacity);
}void Widget::on_pushButton_sub_clicked()
{float opacity = this->windowOpacity();if (opacity <= 0.0) return;qDebug() << opacity;opacity -= 0.1;this->setWindowOpacity(opacity);
}
3) 执行程序, 可以看到, 点击了几下 - 之后, 就可以透过窗口看到后面的猫猫头了. 点击 + 又会逐渐恢复.
同时控制台中也可以看到 opacity 数值的变化
注意, C++ 中 float 类型遵守 IEEE 754 标准, 因此在进行运算的时候会有一定的精度误差. 因此 1 -0.1 的数值并非是 0.9 .
2.7 cursor
举个栗子:在 Qt Designer 中设置按钮的光标
1) 在界面中创建一个按钮.
2) 直接在右侧属性编辑区修改 cursor 属性为 "等待"
3) 运行程序, 鼠标悬停到按钮上, 即可看到光标的变化.
代码示例: 通过代码设置按钮的光标
1) 编写 widget.cpp
• 其中 Qt::WaitCursor 就是自带的沙漏形状的光标.
#include <QPushButton>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建按钮QPushButton* button = new QPushButton(this);button->resize(100, 50);button->move(100, 100);button->setText("这是一个按钮");// 设置按钮的 cursorbutton->setCursor(QCursor(Qt::WaitCursor));
}
系统内置的光标形状如下:
Ctrl + 左键 点击 Qt::WaitCursor 跳转到源码即可看到.
enum CursorShape {ArrowCursor,UpArrowCursor,CrossCursor,WaitCursor,IBeamCursor,SizeVerCursor,SizeHorCursor,SizeBDiagCursor,SizeFDiagCursor,SizeAllCursor,BlankCursor,SplitVCursor,SplitHCursor,PointingHandCursor,ForbiddenCursor,WhatsThisCursor,BusyCursor,OpenHandCursor,ClosedHandCursor,DragCopyCursor,DragMoveCursor,DragLinkCursor,LastCursor = DragLinkCursor,BitmapCursor = 24,CustomCursor = 25
}
2) 运行程序, 观察效果.
代码示例: 自定义鼠标光标
Qt 自带的光标形状有限. 我们也可以自己找个图片, 做成鼠标的光标. 比如我们有请滑稽老铁.
1) 创建 qrc 资源文件, 添加前缀 / , 并加入 huaji.png
2) 编写 widget.cpp
#include <QPixmap>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建一个位图对象, 加载自定义光标图片QPixmap pixmap(":/huaji.png");// 缩放图片为 64 * 64 的尺寸.pixmap = pixmap.scaled(64, 64);// 创建 QCursor 对象, 并指定 "热点" 为 (2, 2) 坐标位置.// 所谓 "热点" 就是鼠标点击时生效的位置.QCursor cursor(pixmap, 2, 2);// 设置光标this->setCursor(cursor);
}
3) 运行程序, 观察效果
2.8 font
关于 QFont
代码示例: 在 Qt Designer 中设置字体属性
1) 在界面上创建一个 label
2) 在右侧的属性编辑区, 设置该 label 的 font 相关属性
在这里调整上述属性, 可以实时的看到文字的变化.
3) 执行程序, 观察效果
代码示例: 在代码中设置字体属性
1) 在界面中创建 label, objectName 使用默认的 label 即可.
2) 修改 widget.cpp
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 设置 label 的文本内容ui->label->setText("这是一段文本");// 创建字体对象QFont font;// 设置字体家族font.setFamily("仿宋");// 设置字体大小font.setPointSize(20);// 设置字体加粗font.setBold(true);// 设置字体倾斜font.setItalic(true);// 设置字体下划线font.setUnderline(true);// 设置字体删除线font.setStrikeOut(true);// 设置字体对象到 label 上ui->label->setFont(font);
}
3) 运行程序, 观察效果
🎹 实际开发中, 字体属性如何选择, 是一个 "审美问题", 而不是 "技术问题". 往往需要有一定的艺术细菌.
幸运的是, 公司中往往有专业的 "美工" / "设计" 这样的岗位, 去做这方面的工作. 咱们程序员只
要按照人家给的设计稿, 把代码写出来即可. 不必过多考虑怎样搭配才好看的问题.
2.9 toolTip
toolTip 只是给用户看的. 在代码中一般不需要获取到 toolTip.
代码示例: 设置按钮的 toolTip
1) 在界面上拖放两个按钮. objectName 设置为 pushButton_yes 和 pushButton_no
2) 编写 widget.cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{ui->setupUi(this);ui->pushButton_yes->setToolTip("这个是 yes 按钮");ui->pushButton_yes->setToolTipDuration(3000);ui->pushButton_no->setToolTip("这个是 no 按钮");ui->pushButton_no->setToolTipDuration(10000);
}
3) 运行程序, 观察效果
可以看到鼠标停到按钮上之后, 就能弹出提示. 时间到后自行消失.
2.10 focusPolicy
设置控件获取到焦点的策略. 比如某个控件能否用鼠标选中或者能否通过 tab 键选中.
所谓 "焦点" , 指的就是能选中这个元素. 接下来的操作 (比如键盘操作), 就都是针对该焦点元素进行的了. 这个对于 输入框, 单选框, 复选框等控件非常有用的.
这个事情就和 war3 或者 sc2 中, 先选中单位, 再下达命令是一样的.
Qt::FocusPolicy 是一个枚举类型. 取值如下
• Qt::NoFocus :控件不会接收键盘焦点
• Qt::TabFocus :控件可以通过Tab键接收焦点
• Qt::ClickFocus :控件在鼠标点击时接收焦点
• Qt::StrongFocus :控件可以通过Tab键和鼠标点击接收焦点 (默认值)
• Qt::WheelFocus : 类似于 Qt::StrongFocus , 同时控件也通过鼠标滚轮获取到焦点 (新增的选项, 一般很少使用).
代码示例: 理解不同的 focusPolicy
1) 在界面上创建四个单行输入框 (Line Edit)
2) 修改四个输入框的 focusPolicy 属性为 Qt::StrongFocus (默认取值, 一般不用额外修改)
此时运行程序, 可以看到, 使用鼠标单击/tab, 就可以移动光标所在输入框. 从而接下来的输入就是针对这个获取焦点的输入框展开的了.
3) 修改第二个输入框的 focusPolicy 为 Qt::NoFocus , 则第二个输入框不会被 tab / 鼠标左键选中.
此时这个输入框也就无法输入内容了.
4) 修改第二个输入框 focusPolicy 为 Qt::TabFocus , 则只能通过 tab 选中, 无法通过鼠标选中.
5) 修改第二个输入框 focusPolicy 为 Qt::ClickFocus , 则只能通过 tab 选中, 无法通过鼠标选中.
2.11 styleSheet
通过 CSS 设置 widget 的样式.
🎨 CSS (Cascading Style Sheets 层叠样式表) 本身属于网页前端技术. 主要就是用来描述界面的样式.
所谓 "样式", 包括不限于 大小, 位置, 颜色, 间距, 字体, 背景, 边框等.
我们平时看到的丰富多彩的网页, 就都会用到大量的 CSS.
Qt 虽然是做 GUI 开发, 但实际上和 网页前端 有很多异曲同工之处. 因此 Qt 也引入了对于 CSS的支持.
CSS 中可以设置的样式属性非常多. 基于这些属性 Qt 只能支持其中一部分, 称为 QSS (Qt Style Sheet)
. 具体的支持情况可以参考 Qt 文档中 "Qt Style Sheets Reference" 章节.
此处只是进行一个简单的演示.
代码示例: 设置文本样式
1) 在界面上创建 label
2) 编辑右侧的 styleSheet 属性, 设置样式
此处的语法格式同 CSS, 使用键值对的方式设置样式. 其中键和值之间使用 : 分割. 键值对之间使用 ; 分割.
另外, Qt Designer 只能对样式的基本格式进行校验, 不能检测出哪些样式不被 Qt 支持. 比如textalign:
center 这样的文本居中操作, 就无法支持.
编辑完成样式之后, 可以看到在 Qt Designer 中能够实时预览出效果.
3) 运行程序, 可以看到实际效果和预览效果基本一致.
代码示例: 实现切换夜间模式.
1) 在界面上创建一个多行输入框 (Text Edit) 和两个按钮.
objectName 分别为 pushButton_light 和 pushButton_dark
2) 编写按钮的 slot 函数.
• #333 是深色, 但是没那么黑.
• #fff 是纯白色.
• #000 是纯黑色.
使用在在线调色板 或者画图板, 都可以看到数字对应的颜色.
void Widget::on_pushButton_dark_clicked()
{this->setStyleSheet("background-color: #333");ui->textEdit->setStyleSheet("background-color: #333; color: #fff;");ui->pushButton_light->setStyleSheet("color: #fff");ui->pushButton_dark->setStyleSheet("color: #fff");
}void Widget::on_pushButton_light_clicked()
{this->setStyleSheet("background-color: #f3f3f3");ui->textEdit->setStyleSheet("background-color: #fff; color: #000;");ui->pushButton_light->setStyleSheet("color: #000");ui->pushButton_dark->setStyleSheet("color: #000");
}
🎁 关于计算机中的颜色表示
计算机中使用 "像素" 表示屏幕上的一个基本单位(也就是一个发亮的光点).
每个光点都使用三个字节表示颜色, 分别是 R (red), G (green), B (blue) 一个字节表示 (取值范围是 0-255, 或者 0x00-0xFF).
混合三种不同颜色的数值比例, 就能搭配出千千万万的颜色出来.
• rgb(255, 0, 0) 或者 #FF0000 或者 #F00 表示纯红色.
• rgb(0, 255, 0) 或者 #00FF00 或者 #0F0 表示纯绿色.
• rgb(0, 0, 255) 或者 #0000FF 或者 #00F 表示纯蓝色.
• rgb(255, 255, 255) 或者 #FFFFFF 或者 #FFF 表示纯白色.
• rgb(0, 0, 0) 或者 #000000 或者 #000 表示纯黑色.
当然, 上述规则只是针对一般的程序而言是这么设定的. 实际的显示器, 可能有 8bit 色深或者10bit 色深等, 实际情况会更加复杂.
3) 运行程序, 点击 "日间模式", 就是浅色背景, 深色文字; 点击 "夜间模式", 就是深色背景, 浅色文字.
本篇完!
相关文章:

【QT控件】QWidget 常用核心属性介绍 -- 万字详解
目录 一、控件概述 二、QWidget 核心属性 2.1 核心属性概览 2.2 enabled 编辑 2.3 geometry 2.4 windowTitle 2.5 windowIcon 使用qrc文件管理资源 2.6 windowOpacity 2.7 cursor 2.8 font 编辑 2.9 toolTip 2.10 focusPolicy 2.11 styleSheet QT专栏&…...

uniapp-商城-77-shop(8.2-商品列表,地址信息添加,级联选择器picker)
地址信息,在我们支付订单上有这样一个接口,就是物流方式,一个自提,我们就显示商家地址。一个是外送,就是用户自己填写的地址。 这里先说说用户的地址添加。需要使用到的一些方式方法,主要有关于地址选择器,就是uni-data-picker级联选择。 该文介绍了电商应用中地址信息处…...
HTTPS加密通信详解及在Spring Boot中的实现
HTTPS(Hyper Text Transfer Protocol Secure)是HTTP的安全版本,通过SSL/TLS协议为通讯提供加密、身份验证和数据完整性保护。 一、HTTPS核心原理 1.加密流程概述 客户端发起HTTPS请求(连接到服务器443端口)服务器返…...
如何让 Git 停止跟踪文件?停止后又如何恢复跟踪?
在使用 Git 管理代码时,有时我们希望某些文件不再被 Git 跟踪(比如本地配置文件、临时文件等),但保留这些文件在本地;过了一段时间,可能又需要恢复跟踪这些文件。本文将用通俗易懂的语言,教你如…...

【第16届蓝桥杯 | 软件赛】CB组省赛第二场
个人主页:Guiat 归属专栏:算法竞赛 文章目录 A. 密密摆放(5分填空题)B. 脉冲强度之和(5分填空题)C. 25 之和D. 旗帜E. 数列差分F. 树上寻宝G. 翻转硬币H. 破解信息 正文 总共8道题。 A. 密密摆放࿰…...
SQL进阶之旅 Day 10:执行计划解读与优化
【SQL进阶之旅 Day 10】执行计划解读与优化 开篇 今天是我们的"SQL进阶之旅"系列的第10天,我们将深入探讨SQL执行计划的解读与优化技巧。随着数据库规模的增长和业务复杂度的提升,理解SQL语句在数据库引擎中的执行过程变得至关重要。 执行计…...

AR/MR实时光照阴影开发教程
一、效果演示 1、PICO4 Ultra MR 发光的球 2、AR实时光照 二、实现原理 PICO4 Ultra MR开发时,通过空间网格能力扫描周围环境,然后将扫描到的环境网格材质替换为一个透明材质并停止扫描;基于Google ARCore XR Plugin和ARFoundation进行安卓手…...
Visual studio 中.sln/.vcxproj/.vcxproj.filters和.vcxproj.user文件的作用
在 Visual Studio (尤其是 C 项目) 中,.sln、.vcxproj、.vcxproj.filters 和 .vcxproj.user 文件各自承担着不同的关键角色。理解它们的作用对于项目管理和协作至关重要。 核心原则: .vcxproj 和 .sln 是项目/解决方案的核心定义文件,必须纳…...

【汽车电子入门】一文了解LIN总线
前言:LIN(Local Interconnect Network)总线,也就是局域互联网的意思,它的出现晚于CAN总线,于20世纪90年代末被摩托罗拉、宝马、奥迪、戴姆勒、大众以及沃尔沃等多家公司联合开发,其目的是提供一…...
JVM学习(七)--JVM性能监控
目录 一、JVM性能监控 1、JVM监控及诊断工具-命令行篇 2、JVM监控及诊断工具-GUI篇 3、JVM运行时参数 一、JVM性能监控 1、JVM监控及诊断工具-命令行篇 面试题: 1、你使用过Java虚拟机性能监控和故障处理工具吗? 2、怎么打出线程栈信息。 3、怎么获取 Jav…...
关于 java:5. Java IO 与文件操作
一、File 类(读取文件属性) 1.1 java.io.File 类概述 File 是 Java IO 中的核心类,用于表示文件或目录的路径名。 它是一个抽象路径名,可以表示实际存在或不存在的文件/文件夹。 File 类提供了创建、删除、重命名、判断属性、获…...

【笔记】为 Python 项目安装图像处理与科学计算依赖(MINGW64 环境)
📝 为 Python 项目安装图像处理与科学计算依赖(MINGW64 环境) 🎯 安装目的说明 本次安装是为了在 MSYS2 的 MINGW64 工具链环境中,搭建一个完整的 Python 图像处理和科学计算开发环境。 主要目的是支持以下类型的 Pyth…...
【笔记】MLA矩阵吸收分析
文章目录 一、张量运算的计算量1. FLOPs定义2. 张量计算顺序对计算量的影响 二、MLA第一次矩阵吸收的计算量分析1. 原始注意力计算2. MLA源代码中的吸收方式3. 提前吸收4. 比较分析4.1 比较顺序1和顺序24.2 比较顺序2和顺序3 三、MLA第二次矩阵吸收的计算量分析1. 原始输出计算…...
600+纯CSS加载动画一键获取指南
CSS-Loaders.com 完整使用指南:600纯CSS加载动画库 🎯 什么是 CSS-Loaders.com? CSS-Loaders.com 是一个专门提供纯CSS加载动画的资源网站,拥有超过600个精美的单元素加载器。这个网站的最大特色是所有动画都只需要一个HTML元素…...
开源的JT1078转GB28181服务器
JT1078转GB28181流程 项目地址: JT1078转GB28181的流媒体服务器: https://github.com/lkmio/lkm JT1078转GB28181的信令服务器: https://github.com/lkmio/gb-cms 1. 创建GB28181 UA 调用接口: http://localhost:9000/api/v1/jt/device/add 请求体如下…...

智能守护电网安全:探秘输电线路测温装置的科技力量
在现代电力网络的庞大版图中,输电线路如同一条条 “电力血管”,日夜不息地输送着能量。然而,随着电网负荷不断增加,长期暴露在户外的线路,其线夹与导线在电流热效应影响下,极易出现温度异常。每年因线路过热…...
Java垃圾回收算法及GC触发条件
一、引言 在Java编程语言的发展历程中,内存管理一直是其核心特性之一。与C/C等需要手动管理内存的语言不同,Java通过自动垃圾回收(Garbage Collection,简称GC)机制,极大地减轻了开发人员的负担,…...

【Hot 100】118. 杨辉三角
目录 引言杨辉三角我的解题代码优化优化说明 🙋♂️ 作者:海码007📜 专栏:算法专栏💥 标题:【Hot 100】118. 杨辉三角❣️ 寄语:书到用时方恨少,事非经过不知难! 引言 …...

useMemo useCallback 自定义hook
useMemo & useCallback & 自定义hook useMemo 仅当依赖项发生变化的时候,才去重新计算;其他状态变化时则不去做不必要的计算。 useCallback 缓存函数。但是使用注意📢 ,useCallback没有特别明显的优化。 *合适的场景——父…...

ffmpeg 的视频格式转换 c# win10
1,下载ffmpeg ,并设置环境变量。 ffmpeghttps://www.gyan.dev/ffmpeg/builds/ 2.新建.net 9.0 winform using System; using System.Diagnostics; using System.Text; using System.Windows.Forms;namespace WinFormsApp11 {public partial class Fo…...

【irregular swap】An Examination of Fairness of AI Models for Deepfake Detection
文章目录 An Examination of Fairness of AI Models for Deepfake Detection背景points贡献深伪检测深伪检测审计评估检测器主要发现评估方法审计结果训练分布和方法偏差An Examination of Fairness of AI Models for Deepfake Detection 会议/期刊:IJCAI 2021 作者: 背景…...

【JAVA】注解+元注解+自定义注解(万字详解)
📚博客主页:代码探秘者 ✨专栏:《JavaSe》 其他更新ing… ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏作者水平有限,欢迎各位大佬指点&…...

【Doris基础】Apache Doris中的Version概念解析:深入理解数据版本管理机制
目录 引言 1 Version概念基础 1.1 什么是Version 1.2 Version的核心作用 1.3 Version相关核心概念 2 Version工作机制详解 2.1 Version在数据写入流程中的作用 2.2 Version在数据查询流程中的作用 2.3 Version的存储结构 3 Version的进阶特性 3.1 Version的合并与压…...
【Linux 基础知识系列】第一篇-Linux 简介与历史
一、什么是 Linux? Linux 是一种类 Unix 操作系统,它是由 Linus Torvalds 于 1991 年首次发布的。作为一个开源操作系统,Linux 的源代码可以被任何人自由使用、修改和分发。在现代计算环境中,Linux 凭借其强大的性能、高稳定性、…...

【图像处理基石】如何进行图像畸变校正?
图像畸变校正常用于计算机视觉、摄影测量学和机器人导航等领域,能够修正因镜头光学特性或传感器排列问题导致的图像失真。下面我将介绍几种常用的图像畸变校正算法,并提供Python实现和测试用例。 常用算法及Python实现 1. 径向畸变校正 径向畸变是最常…...
软件开发项目管理工具选型及禅道开源版安装
软件开发项目管理工具选型及禅道开源版安装 为啥选禅道 你以为我选禅道之前没有对比吗? 作为Java码农,首先想到的就是Jira,然而它太重了。。 我们用企微作为沟通工具,腾讯的TAPD的确好用,但是它不开源啊,…...
【架构艺术】平衡技术架构设计和预期的产品形态
近期笔者因为工作原因,开始启动team内部部分技术项目的重构。在事情启动的过程中,内部对于这件事情的定性和投入有一些争论,但最终还是敲定了下来。其中部分争论点主要在于产品形态,因为事情涉及到跨部门合作,所以产品…...

电力系统时间同步系统
电力系统中,电压、电流、功率变化等特征量测量都是时间相关函数[1],统一精准的时间源对于电网安全稳定运行至关重要,因此,电力系统运行规程[2]中明确要求继电保护装置、自动化装置、安全稳定控制系统、能量管理系统和生产信息管理…...

Vue使用toFixed保留两位小数的三种写法
第一种:直接写在js里面,这是最简单的 val.toFixed(2)第二种:在ElementUi表格中使用 第三种:在取值符号中使用 {{}} 定义一个方法 towNumber(val) { return val.toFixed(2) } 使用 {{ towNumber(row.equiV…...
华为云【Astro zero】如何做“设备编辑”页面
目录 一、整体原理概述(逻辑图+原理) 1. 页面组件组装(用户交互界面) 2. 数据模型(数据临时存储) 3. 页面事件(逻辑交互) 二、详细操作步骤(按功能模块分) ✅【1】页面创建与结构组装 ✅【2】定义自定义模型与字段(临时数据绑定) ✅【3】定义服务模型(与后…...