在上一篇文章中,我们已经掌握了 QWidget 的基础属性,比如控制控件启用禁用的
enabled、管理位置尺寸的geometry,还有给窗口加 “名字” 和 “头像” 的windowTitle与windowIcon。但 Qt 界面开发的精髓远不止于此 —— 用户鼠标悬停时的光标变化、文本显示的字体样式、操作提示的 toolTip、控件焦点的获取规则,以及让界面颜值飙升的样式表,这些细节才是让程序从 “能用” 到 “好用又好看” 的关键。今天这篇《Qt 常用控件之 QWidget(下)》,就带大家深入这些核心属性,用代码实战打通 Qt 界面开发的 “任督二脉”!
在正式开始前,先快速回顾一下 QWidget 的定位 —— 它是所有 Qt 可视化控件的 “老祖宗”,无论是按钮、输入框还是复杂的表格,都直接或间接继承自它。上一篇我们讲了 5 个基础属性,今天要解锁的是 5 个更偏向 “交互体验” 和 “视觉样式” 的核心属性:
这些属性看似独立,却能相互配合打造出专业级的交互效果。接下来,我们逐个拆解,用代码实战让每个知识点都落地。
当用户把鼠标移到不同控件上时,光标形状的变化能直观告诉用户 “这里能做什么”—— 比如悬停在按钮上显示 “手型”,悬停在输入框显示 “竖线”,悬停在加载中的区域显示 “沙漏”。cursor属性就是 Qt 中控制光标形状的核心,支持系统内置光标和自定义图片光标两种模式。
API | 说明 |
|---|---|
cursor() | 获取当前控件的光标对象,返回 QCursor |
setCursor(const QCursor& cursor) | 给单个控件设置光标(仅在鼠标悬停该控件时生效) |
QGuiApplication::setOverrideCursor(const QCursor& cursor) | 设置全局光标(对整个程序所有控件生效,优先级高于 setCursor) |
Qt 内置了 20 多种常用光标形状,比如箭头、沙漏、手型、十字等,我们可以直接通过Qt::CursorShape枚举调用。比如给按钮设置 “等待光标”(沙漏形状),代码如下:
按钮的objectName保持默认(pushButton),文本设为 “悬停我看光标变化”。
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QCursor> // 需包含QCursor头文件
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 1. 获取界面上的按钮(也可以用new动态创建)
QPushButton* btn = ui->pushButton;
// 2. 设置光标为“等待形状”(沙漏)
// Qt::WaitCursor是系统内置的光标枚举值
btn->setCursor(QCursor(Qt::WaitCursor));
// 拓展:如果想设置全局光标(比如加载时)
// QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
// 注意:全局光标使用后需手动恢复,否则会一直生效
// QGuiApplication::restoreOverrideCursor();
}
Widget::~Widget()
{
delete ui;
} 当鼠标悬停在按钮上时,光标会从默认的箭头变成 “沙漏”形状;移开按钮后,光标恢复默认形状。如果使用了setOverrideCursor,整个程序的光标都会变成沙漏,直到调用restoreOverrideCursor恢复。
系统内置光标不够个性?Qt 支持用任意图片作为光标,比如用 “滑稽表情包” 做光标。实现步骤如下:
.png;/,并将anno.png添加到资源中(确保图片在项目目录下)。
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//访问到图片文件
QPixmap pixmap(":/anno.png");
pixmap.scaled(10, 10); //缩放图片
//构造光标对象
QCursor cursor(pixmap, 10, 10);
//把光标设置进去
this->setCursor(cursor);
}
Widget::~Widget()
{
delete ui;
} Qt 内置的Qt::CursorShape枚举包含多种常用光标,这里列出高频使用的几种:
枚举值 | 光标形状 | 适用场景 |
|---|---|---|
Qt::ArrowCursor | 默认箭头 | 普通界面区域 |
Qt::WaitCursor | 沙漏 / 转圈 | 加载中、耗时操作 |
Qt::PointingHandCursor | 手型 | 按钮、链接(提示可点击) |
Qt::IBeamCursor | 竖线 | 输入框(提示可输入) |
Qt::CrossCursor | 十字 | 绘图、选择区域 |
Qt::SizeAllCursor | 四向箭头 | 窗口可拖动调整大小 |
在代码中按住Ctrl键点击枚举值(如Qt::WaitCursor),可以跳转到 Qt 源码查看所有内置光标。
文本是界面中传递信息的核心元素,字体的选择直接影响用户的阅读体验 —— 比如标题用粗体大号字体,正文用清晰的常规字体。font属性通过QFont类管理文本样式,支持字体家族、大小、粗细、倾斜、下划线等多种设置。
API | 说明 |
|---|---|
font() | 获取控件当前的字体对象,返回 QFont |
setFont(const QFont& font) | 给控件设置字体 |
QFont类包含多个控制文本样式的属性,常用的如下:
QFont 属性 | 说明 | 示例 |
|---|---|---|
family | 字体家族(如 “微软雅黑”“楷体”) | font.setFamily("微软雅黑") |
pointSize | 字体大小(单位:磅) | font.setPointSize(14) |
bold | 是否加粗(true/false) | font.setBold(true) |
italic | 是否倾斜(true/false) | font.setItalic(true) |
underline | 是否加下划线(true/false) | font.setUnderline(true) |
strikeOut | 是否加删除线(true/false) | font.setStrikeOut(true) |
weight | 字体粗细(0-99,75=bold,50 = 正常) | font.setWeight(80) |
对于静态界面,直接在 Qt Designer 中设置字体更高效:
QLabel(文本显示控件),文本设为 这是一段文本!”;
QLabel,在右侧 “属性编辑器” 中找到font属性,点击右侧的 “...” 按钮;


代码设置字体的优势在于可以根据业务逻辑动态调整(比如夜间模式切换字体颜色)。示例如下:
#include "widget.h"
#include "ui_widget.h"
#include <QLabel>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLabel* label = new QLabel(this);
label->setText("这是一段文本");
//创建字体对象
QFont font;
font.setFamily("仿宋");
font.setPixelSize(30);
font.setBold(true);
font.setItalic(true);
font.setUnderline(true);
font.setStrikeOut(true);
//把font对象设置到label中
label->setFont(font);
}
Widget::~Widget()
{
delete ui;
}运行效果:

pointSize是 “磅”(1 磅≈0.35 毫米),pixelSize是像素,推荐用pointSize,因为它在不同分辨率屏幕上显示更一致;Widget设置字体,子控件会继承父控件的字体属性(除非单独设置)。 当用户对某个控件的功能不确定时,鼠标悬停时显示的提示信息(toolTip)能快速解答疑惑 —— 比如按钮上只放了图标,toolTip 可以说明 “点击下载文件”。toolTip属性支持设置提示文本和显示时长,是提升用户体验的 “小而美” 功能。
API | 说明 |
|---|---|
setToolTip(const QString& text) | 设置控件的提示文本 |
setToolTipDuration(int msec) | 设置提示的显示时长(单位:毫秒),默认 - 1(一直显示直到鼠标移开) |
toolTip() | 获取控件的提示文本(很少用,提示主要给用户看) |
我们实现一个场景:两个按钮分别对应 “确认” 和 “取消” 操作,鼠标悬停时显示提示,且 “确认” 按钮的提示显示 3 秒,“取消” 按钮的提示一直显示。
拖入两个按钮,objectName分别为pushButton_yes(文本 “Yes”)和pushButton_no(文本 “No”)。
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置这两个按钮的toolTips
ui->pushButton_yes->setToolTip("这是一个yes按钮");
ui->pushButton_yes->setToolTipDuration(3000);
ui->pushButton_no->setToolTip("这是一个no按钮");
ui->pushButton_no->setToolTipDuration(7000);
}
Widget::~Widget()
{
delete ui;
}toolTip的文本可以用 HTML 标签(如<b>加粗、<br>换行),让提示更易读;
除了toolTip,QWidget 还支持另外两种提示:
statusTip:鼠标悬停时在窗口状态栏显示的提示(需要窗口有状态栏,如 QMainWindow);
// 设置statusTip
ui->pushButton_confirm->setStatusTip("正在准备保存数据...");whatThis:按下Alt+F1后鼠标点击控件显示的详细帮助(弹出窗口);
// 设置whatThis
ui->pushButton_confirm->setWhatsThis(
"确认按钮:\n"
"功能:保存当前页面的所有修改到数据库\n"
"注意:保存后无法撤销,请确认数据无误后点击"
); 这两种提示在复杂软件中很有用,但日常开发中toolTip最常用。
“焦点” 是 GUI 中的核心概念 —— 拥有焦点的控件会接收键盘输入(比如输入框有焦点时,按键盘能输入文字;按钮有焦点时,按 Enter 能触发点击)。focusPolicy属性控制控件如何获取焦点,避免出现 “按键盘没反应” 的尴尬场景。
术语 | 说明 |
|---|---|
焦点(Focus) | 控件的 “激活状态”,拥有焦点的控件会优先接收键盘事件 |
focusPolicy | 控件获取焦点的策略,是Qt::FocusPolicy枚举类型 |
核心 API:
API | 说明 |
|---|---|
focusPolicy() | 获取控件的焦点策略,返回Qt::FocusPolicy |
setFocusPolicy(Qt::FocusPolicy policy) | 设置控件的焦点策略 |
Qt::FocusPolicy包含 5 种策略,覆盖了大部分交互场景:
枚举值 | 含义 | 适用场景 |
|---|---|---|
Qt::NoFocus | 不接收焦点 | 纯显示控件(如 QLabel)、装饰性控件 |
Qt::TabFocus | 仅通过 Tab 键获取焦点 | 不希望鼠标点击干扰的控件(如某些工具条按钮) |
Qt::ClickFocus | 仅通过鼠标点击获取焦点 | 避免键盘误触的控件(如弹出窗口的按钮) |
Qt::StrongFocus | 通过 Tab 键或鼠标点击获取焦点(默认) | 输入框(QLineEdit)、单选框(QRadioButton)等交互控件 |
Qt::WheelFocus | 同 StrongFocus,额外支持鼠标滚轮获取焦点 | 滚动条、滑块等需要滚轮操作的控件(很少用) |
我们用 4 个单行输入框(QLineEdit)演示不同焦点策略的效果,帮助大家直观理解。
拖入 4 个QLineEdit,objectName分别为lineEdit_1到lineEdit_4,依次设置它们的focusPolicy:
lineEdit_1:Qt::StrongFocus(默认);lineEdit_2:Qt::NoFocus;lineEdit_3:Qt::TabFocus;lineEdit_4:Qt::ClickFocus。
如果不想在 Designer 中手动设置,也可以用代码批量设置:
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置4个输入框的焦点策略
ui->lineEdit_1->setFocusPolicy(Qt::StrongFocus); // Tab+点击
ui->lineEdit_2->setFocusPolicy(Qt::NoFocus); // 不接收焦点
ui->lineEdit_3->setFocusPolicy(Qt::TabFocus); // 仅Tab
ui->lineEdit_4->setFocusPolicy(Qt::ClickFocus); // 仅点击
// 给输入框设置提示文本
ui->lineEdit_1->setPlaceholderText("StrongFocus(Tab+点击)");
ui->lineEdit_2->setPlaceholderText("NoFocus(无法获取焦点)");
ui->lineEdit_3->setPlaceholderText("TabFocus(仅Tab)");
ui->lineEdit_4->setPlaceholderText("ClickFocus(仅点击)");
}
Widget::~Widget()
{
delete ui;
}
输入控件必须有焦点:QLineEdit、QTextEdit 等输入类控件,默认focusPolicy是StrongFocus,不要轻易改成NoFocus,否则用户无法输入;
焦点顺序:按 Tab 键切换焦点的顺序,默认是控件在 Designer 中的创建顺序,可以通过setTabOrder手动调整;
// 设置Tab顺序:lineEdit_1 → lineEdit_3 → lineEdit_4 → lineEdit_1
this->setTabOrder(ui->lineEdit_1, ui->lineEdit_3);
this->setTabOrder(ui->lineEdit_3, ui->lineEdit_4);
this->setTabOrder(ui->lineEdit_4, ui->lineEdit_1);动态设置焦点:用setFocus()方法可以强制给控件设置焦点(前提是focusPolicy允许);
// 程序启动时,让lineEdit_1获取焦点
ui->lineEdit_1->setFocus(); 如果说前面的属性是 “基础护肤”,那styleSheet(简称 QSS)就是 “高级化妆”—— 它借鉴了网页开发的 CSS 语法,支持给控件设置背景色、边框、圆角、渐变等样式,让 Qt 界面从 “朴素” 变 “精致”。
QPushButton表示所有按钮,#pushButton_confirm表示指定objectName的按钮);background-color设置背景色,border-radius设置圆角)。选择器类型 | 语法 | 说明 | 示例 |
|---|---|---|---|
类选择器 | QWidget | 匹配所有该类及子类的控件 | QPushButton { color: red; }(所有按钮文字红色) |
ID 选择器 | #objectName | 匹配指定objectName的控件 | #pushButton_confirm { background: blue; }(指定按钮背景蓝色) |
后代选择器 | 父控件 子控件 | 匹配父控件下的子控件 | QWidget QLineEdit { border: 1px solid gray; }(窗口下的输入框有灰色边框) |
状态选择器 | 控件:状态 | 匹配处于指定状态的控件 | QPushButton:hover { background: yellow; }(鼠标悬停的按钮背景黄色) |
属性 | 说明 | 示例 |
|---|---|---|
background-color | 背景色(支持十六进制、RGB、颜色名) | background-color: #FF0000;(红色) |
color | 文本颜色 | color: white;(白色文本) |
border | 边框(宽度、样式、颜色) | border: 2px solid black;(2px 黑色实线边框) |
border-radius | 圆角半径(实现圆角控件) | border-radius: 8px;(8px 圆角) |
font-family | 字体家族 | font-family: "微软雅黑"; |
font-size | 字体大小 | font-size: 14px; |
padding | 内边距(控件内容与边框的距离) | padding: 5px;(上下左右内边距 5px) |
margin | 外边距(控件与其他控件的距离) | margin: 10px;(上下左右外边距 10px) |
我们先从简单的按钮美化入手,实现 “默认灰色、悬停蓝色、点击红色” 的交互效果。
拖入一个按钮,objectName为pushButton_style,文本设为 “QSS 样式演示”。
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 1. 编写QSS样式字符串
QString btnStyle = R"(
/* 默认状态 */
QPushButton {
background-color: #E0E0E0; /* 浅灰色背景 */
color: #333333; /* 深灰色文本 */
border: none; /* 取消默认边框 */
border-radius: 8px; /* 8px圆角 */
font-family: "微软雅黑"; /* 字体 */
font-size: 14px; /* 字体大小 */
padding: 8px 16px; /* 内边距:上下8px,左右16px */
}
/* 鼠标悬停状态 */
QPushButton:hover {
background-color: #2196F3; /* 蓝色背景 */
color: white; /* 白色文本 */
}
/* 鼠标点击状态 */
QPushButton:pressed {
background-color: #F44336; /* 红色背景 */
padding: 9px 15px 7px 17px; /* 点击时轻微偏移,模拟按压效果 */
}
/* 禁用状态(可选) */
QPushButton:disabled {
background-color: #F5F5F5; /* 更浅的灰色 */
color: #BDBDBD; /* 灰色文本 */
}
)";
// 2. 给按钮应用QSS
ui->pushButton_style->setStyleSheet(btnStyle);
// 拓展:给整个窗口设置背景色
this->setStyleSheet("background-color: #FAFAFA;");
}
Widget::~Widget()
{
delete ui;
}


setEnabled(false)):按钮变浅灰,文本变灰,无法交互。用 QSS 实现模式切换是开发中的常见需求,我们通过两个按钮控制窗口在 “日间模式”(浅色背景、深色文本)和 “夜间模式”(深色背景、浅色文本)之间切换。
TextEdit(多行输入框,objectName为plainTextEdit),用于显示文本;objectName分别为pushButton_light(文本 “日间模式”)和pushButton_dark(文本 “夜间模式”)。
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_light_clicked()
{
//设置窗口的样式
this->setStyleSheet("background-color:rgb(240, 240, 240);");
//设置输入框的样式
ui->plainTextEdit->setStyleSheet("background-color:white; color:black");
//设置按钮的样式
ui->pushButton_light->setStyleSheet("color:black");
ui->pushButton_dark->setStyleSheet("color:black");
}
void Widget::on_pushButton_dark_clicked()
{
//设置窗口的样式
this->setStyleSheet("background-color:black;");
//设置输入框的样式
ui->plainTextEdit->setStyleSheet("background-color:black; color:white");
//设置按钮的样式
ui->pushButton_light->setStyleSheet("color:white");
ui->pushButton_dark->setStyleSheet("color:white");
}

使用 R"(...)" 包裹 QSS 字符串:C++11 及以上支持原始字符串字面量,避免转义字符(如"不需要写成\");
分层管理 QSS:复杂界面可以将 QSS 按控件类型拆分(如btnStyle、editStyle),或放到单独的.qss文件中,用QFile读取后应用;
// 从文件读取QSS
QFile qssFile(":/style.qss");
if (qssFile.open(QFile::ReadOnly)) {
QString qss = QLatin1String(qssFile.readAll());
this->setStyleSheet(qss);
qssFile.close();
}调试 QSS:Qt Designer 的 “编辑样式表” 对话框支持实时预览,可先在 Designer 中调试样式,再复制到代码中;
优先级:如果一个控件同时被多个 QSS 选择器匹配,ID 选择器优先级最高,其次是状态选择器,最后是类选择器。
Qt 界面开发的核心思路是 “先功能后样式”—— 先通过基础属性实现控件的交互逻辑,再用
styleSheet美化外观。后续文章中,我们会基于 QWidget 的基础,讲解按钮类(QPushButton、QRadioButton)、显示类(QLabel、QProgressBar)等具体控件的用法,逐步构建完整的 Qt 界面开发知识体系。 如果你在学习过程中有任何问题,或者有想看的 Qt 知识点,欢迎在评论区留言交流!觉得有用的话,别忘了点赞 + 收藏,关注我,持续更新 Qt 开发干货~