QT —— QWidget(1)
QT —— QWidget(1)
- QWidget是啥
- 通俗解释:QWidget 是什么?
- 1. QWidget 能干什么?
- 2. 举个栗子 🌰
- 3. QWidget 的特点
- 4. 和“控件”是什么关系?
- 5. 什么时候用 QWidget?
- 6. 总结
- QWidget 核心属性
- QWidget 常用属性说明
- 基础属性
- 交互属性
- 样式属性
- 尺寸控制
- 辅助功能
- 其他属性
- enable
- 方法说明
- 使用示例
- 注意事项
- geometry
- 方法说明
- 使用示例
- window frame
- 坐标和尺寸获取方法
- 客户区获取方法
- 设置方法
- 重要说明
我们从这章开始,我们介绍一下QT中一些常用控件,如果对之前的章节还不是很熟悉的可以点击这里:
https://blog.csdn.net/qq_67693066/category_12625974.html
QWidget是啥
通俗解释:QWidget 是什么?
QWidget 是 Qt 框架中的一个 基础类,用来创建 用户界面(UI)的“零件”。
你可以把它理解成 “UI 积木块”——几乎所有你能看到的窗口、按钮、文本框、下拉菜单等,都是基于 QWidget 构建的。
1. QWidget 能干什么?
- 创建窗口和控件:
- 比如:一个弹窗(
QDialog
)、一个按钮(QPushButton
)、一个输入框(QLineEdit
),本质上都是QWidget
的子类。
- 比如:一个弹窗(
- 管理布局和样式:
- 控制大小、位置、颜色、字体等。
- 处理用户交互:
- 响应点击、键盘输入、鼠标移动等事件。
2. 举个栗子 🌰
假设你要做一个简单的登录界面:
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建一个窗口(QWidget 是所有窗口和控件的基类)QWidget window;window.setWindowTitle("登录界面");window.resize(300, 200);// 在窗口上放一个按钮QPushButton button("登录", &window);button.move(100, 100);// 在窗口上放一个输入框QLineEdit usernameInput(&window);usernameInput.setPlaceholderText("请输入用户名");usernameInput.move(50, 50);window.show(); // 显示窗口return app.exec();
}
效果:
你会看到一个带输入框和按钮的窗口,这就是用 QWidget
及其子类拼出来的。
3. QWidget 的特点
特性 | 说明 |
---|---|
跨平台 | 基于 Qt,同一套代码能运行在 Windows、macOS、Linux 甚至嵌入式设备上。 |
可嵌套 | 可以把一个 QWidget(如按钮)放到另一个 QWidget(如窗口)上,形成父子关系。 |
支持样式定制 | 能用 CSS 类似的语法修改外观(比如圆角按钮、渐变背景)。 |
事件驱动 | 可以监听用户的鼠标、键盘操作(比如点击按钮触发函数)。 |
4. 和“控件”是什么关系?
- QWidget 是基类,提供最基础的功能(比如显示、隐藏、调整大小)。
- 控件(如
QPushButton
、QCheckBox
)是它的子类,增加了具体交互逻辑。- 类比:
QWidget
≈ “空白画布”QPushButton
≈ “画布上画了一个按钮”
- 类比:
5. 什么时候用 QWidget?
- 当你需要 自定义一个界面元素(比如设计一个圆形按钮),可以继承
QWidget
自己绘制。 - 但大多数时候,直接用现成的子类(如
QMainWindow
、QLabel
)就够了。
6. 总结
- QWidget 是 Qt 的 UI 基石,所有看得见的界面元素都是它或它的子类。
- 像乐高积木,通过组合各种
QWidget
派生出的控件,就能拼出完整的界面。 - 适合:开发桌面应用、嵌入式设备界面、工业控制面板等。
我们可以在QT Desginer中可以看到各种各样的控件:
在 Qt 中, 使用 QWidget 类表示 “控件”. 像按钮, 视图, 输入框, 滚动条等具体的控件类, 都是继承自QWidget.可以说, QWidget 中就包含了 Qt 整个控件体系中, 通用的部分。
QWidget 核心属性
我们选了一个控件,右下角的黄色区域就可以显示该控件的属性:
QWidget 常用属性说明
基础属性
属性 | 作用 |
---|---|
enabled | 设置控件是否可用: - true 表示可用- false 表示禁用 |
geometry | 设置位置和尺寸(x, y, width, height) 坐标以父元素为参考 |
windowTitle | 设置窗口标题 |
windowIcon | 设置窗口图标 |
windowOpacity | 设置窗口透明度(0.0-1.0) |
交互属性
属性 | 作用 |
---|---|
cursor | 鼠标悬停时的光标形状: - 箭头、沙漏、十字等 |
focusPolicy | 焦点获取方式: - NoFocus :不参与焦点管理- TabFocus :通过Tab键获取- ClickFocus :通过鼠标点击获取- StrongFocus :键盘+鼠标获取- WheelFocus :鼠标滚轮获取 |
contextMenuPolicy | 上下文菜单显示策略: - DefaultContextMenu :默认右键菜单- NoContextMenu :禁用菜单- CustomContextMenu :自定义菜单 |
acceptDrops | 是否接受拖放操作: - true :可接收拖放- false :不接收 |
样式属性
属性 | 作用 |
---|---|
font | 设置字体(家族、大小、粗体、斜体等) |
styleSheet | 使用CSS设置控件样式 |
palette | 调色板(设置颜色风格) |
layoutDirection | 布局方向: - LeftToRight :从左到右(默认)- RightToLeft :从右到左 |
尺寸控制
属性 | 作用 |
---|---|
minimumSize | 最小尺寸(width, height) |
maximumSize | 最大尺寸(width, height) |
sizePolicy | 在布局管理器中的缩放方式 |
sizeIncrement | 窗口拖动时的尺寸调整单位 |
baseSize | 窗口基础尺寸(配合sizeIncrement使用) |
辅助功能
属性 | 作用 |
---|---|
toolTip | 鼠标悬停时的提示信息 |
statusTip | 状态改变时的提示信息 |
whatsThis | 按Alt+F1显示帮助信息 |
accessibleName | 无障碍名称(供屏幕阅读器使用) |
accessibleDescription | 无障碍详细描述 |
其他属性
属性 | 作用 |
---|---|
mouseTracking | 是否跟踪鼠标移动事件 |
tabletTracking | 是否跟踪触摸屏事件(Qt 5.9+) |
autoFillBackground | 是否自动填充背景色 |
windowModality | 窗口模态行为设置 |
inputMethodHints | 输入框格式提示(如仅数字、仅日期等) |
enable
方法说明
方法 | 说明 | 参数 | 返回值 |
---|---|---|---|
isEnabled() | 获取控件的当前可用状态 | 无 | bool - true : 控件可用- false : 控件禁用 |
setEnabled(bool) | 设置控件的可用状态 | enable : bool- true : 启用控件- false : 禁用控件 | 无 |
使用示例
// 获取按钮当前状态
bool isActive = ui->pushButton->isEnabled(); // 禁用按钮
ui->pushButton->setEnabled(false);// 启用按钮
ui->pushButton->setEnabled(true);
我们可以写一段代码看一下:
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* btn = new QPushButton(this);btn->setText("这是个被禁⽤的按钮");btn->setEnabled(false);
}
注意事项
-
禁用状态下的控件:
- 显示为灰色(默认样式)
- 不响应任何用户交互事件
- 仍可通过程序代码修改其状态
-
父子控件关系:
- 父控件禁用时,所有子控件会自动禁用
- 单独启用子控件无效(需先启用父控件)
-
样式定制:
- 可通过
QSS
修改禁用状态的样式:
QPushButton:disabled {color: #999999;background-color: #dddddd; }
- 可通过
我们来写一个小栗子,创建两个按钮,其中一个按钮可以控制另一个按钮是否被启用:
我们先在ui界面创建两个按钮:
选中一个按钮之后,我们对它改个名字,方便我们辨识:
下面那个按钮也一样:
然后右击,分别为这两个按钮添加槽函数:
void Widget::on_pushButton_one_clicked()
{qDebug() << "this button has been clicked";
}void Widget::on_pushButton_two_clicked()
{bool flag = this->ui->pushButton_one->isEnabled();this->ui->pushButton_one->setEnabled(!flag);
}
geometry
位置和尺寸. 其实是四个属性的统称:
• x
横坐标
• y
纵坐标
• width
宽度
• height
高度
但是实际开发中, 我们并不会直接使用这几个属性, 而是通过⼀系列封装的方法来获取/修改。
对于 Qt 的坐标系, 不要忘记是⼀个 “左手坐标系”. 其中坐标系的原点是当前元素的父元素的左上角
方法说明
方法 | 说明 | 参数 | 返回值 |
---|---|---|---|
geometry() | 获取控件的位置和尺寸 | 无 | QRect 包含四个属性: - x :左上角X坐标- y :左上角Y坐标- width :控件宽度- height :控件高度 |
setGeometry(QRect) | 设置控件的位置和尺寸 | rect : QRect(包含x,y,width,height) | 无 |
setGeometry(int x, int y, int width, int height) | 设置控件的位置和尺寸 | x : 左上角X坐标y : 左上角Y坐标width : 控件宽度height : 控件高度 | 无 |
使用示例
// 获取当前几何属性
QRect rect = widget->geometry();
qDebug() << "Position:" << rect.x() << rect.y() << "Size:" << rect.width() << rect.height();// 通过QRect设置
widget->setGeometry(QRect(100, 50, 200, 150));// 通过单独参数设置
widget->setGeometry(100, 50, 200, 150);
代码示例: 控制按钮的位置
- 在界面中拖五个按钮.
五个按钮的 objectName 分别为 pushButton_target , pushButton_up ,
pushButton_down , pushButton_left , pushButton_right五个按钮的初始位置和大小都随意。
我们在ui界面上拖出五个按钮来:
然后分别生成这五个按钮的槽函数:
void Widget::on_target_clicked()
{}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());
}
window frame
我们每次运行出来的窗口都会有一个小白条:
其实在我们的Widget的外围还有一层细细的边框:
以上提到的这两部分都是操作系统给我们的Widget自动添加的,我们称之为window frame,我们上面提到的geometry是只针对Widget本身的,QT还针对的有window frame的方法:
坐标和尺寸获取方法
方法 | 说明 | 包含 Window Frame | 返回类型 | 等价关系 |
---|---|---|---|---|
x() | 获取控件左上角X坐标 | ✔️ | int | frameGeometry().x() |
y() | 获取控件左上角Y坐标 | ✔️ | int | frameGeometry().y() |
pos() | 获取控件位置 | ✔️ | QPoint | QPoint(x(), y()) |
frameSize() | 获取包含边框的尺寸 | ✔️ | QSize | frameGeometry().size() |
frameGeometry() | 获取完整外框矩形 | ✔️ | QRect | QRect(pos(), frameSize()) |
客户区获取方法
方法 | 说明 | 包含 Window Frame | 返回类型 | 等价关系 |
---|---|---|---|---|
width() | 获取客户区宽度 | ❌ | int | geometry().width() |
height() | 获取客户区高度 | ❌ | int | geometry().height() |
size() | 获取客户区尺寸 | ❌ | QSize | geometry().size() |
rect() | 获取客户区矩形(相对坐标) | ❌ | QRect | QRect(0, 0, width(), height()) |
geometry() | 获取客户区绝对矩形 | ❌ | QRect | QRect(客户区x, 客户区y, width(), height()) |
设置方法
方法 | 参数 | 包含 Window Frame | 说明 |
---|---|---|---|
setGeometry(QRect) | QRect | ❌ | 设置客户区位置和尺寸 |
setGeometry(x, y, w, h) | int, int, int, int | ❌ | 设置客户区位置和尺寸 |
重要说明
-
Window Frame 包含:
- 窗口边框
- 标题栏
- 系统菜单按钮等装饰部件
-
典型差异值:
QMainWindow window; window.setGeometry(100, 100, 400, 300);// 输出示例: geometry(): QRect(100,100 400x300) frameGeometry(): QRect(98,78 404x322)
我们可以来试试:
#include "widget.h"
#include <QDebug>#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();QRect rect1 = w.geometry();QRect rect2 = w.frameGeometry();qDebug() << rect1;qDebug() << rect2;return a.exec();
}
打印出来,可以看到细微差别: