类
用途
常用操作或信号
QLabel
显示文字、图片
setText()、setPixmap()
QPushButton
按钮
clicked()
QLineEdit
单行输入框
text()、textChanged()
QTextEdit
多行文本编辑
setPlainText()、toPlainText()
QCheckBox
勾选开关
isChecked()、toggled(bool)
QComboBox
下拉选择
addItem()、currentIndexChanged()
QSlider
拖动调节数值
setRange()、valueChanged(int)
QSpinBox
输入整数
setRange()、value()
QStackedWidget
多个页面切换,同一时间显示一个
setCurrentIndex()
QListWidget
简单列表
addItem()、currentRowChanged()
QDialog
设置、确认等对话框
open()、accept()、reject()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <QApplication> #include <QWidget> #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QCheckBox> #include <QVBoxLayout> int main (int argc, char *argv[]) { QApplication app (argc, argv) ; QWidget window; window.setWindowTitle ("登录界面教学" ); window.resize (360 , 260 ); auto *title = new QLabel ("欢迎登录" , &window); auto *account = new QLineEdit (&window); auto *password = new QLineEdit (&window); auto *remember = new QCheckBox ("记住账号" , &window); auto *login = new QPushButton ("登录" , &window); auto *message = new QLabel (&window); account->setPlaceholderText ("请输入账号" ); password->setPlaceholderText ("请输入密码" ); password->setEchoMode (QLineEdit::Password); auto *layout = new QVBoxLayout (&window); layout->setContentsMargins (20 , 20 , 20 , 20 ); layout->setSpacing (12 ); layout->addWidget (title); layout->addWidget (account); layout->addWidget (password); layout->addWidget (remember); layout->addWidget (login); layout->addWidget (message); QObject::connect (login, &QPushButton::clicked, &window, [account, password, remember, message]() { const QString name = account->text ().trimmed (); if (name.isEmpty () || password->text ().isEmpty ()) { message->setText ("请填写账号和密码" ); return ; } message->setText ( QString ("账号:%1;记住账号:%2" ) .arg (name) .arg (remember->isChecked () ? "是" : "否" )); }); window.show (); return app.exec (); }
自定义控件 自绘控件继承自 QWidget,最核心的三个概念:
名字
职责
update()
告诉 Qt:“我的显示内容变了,请安排重画”
paintEvent()
Qt 需要这个控件重画时调用的函数
QPainter
真正执行画矩形、文字、图片、路径等操作的工具
rect() 是控件自己的局部区域,左上角通常是 (0,0)。
窗口被遮挡后重新露出、控件尺寸变化,也可能触发绘制,因此 paintEvent() 要能根据已保存的状态恢复画面。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #pragma once #include <QWidget> #include <QPainter> #include <algorithm> class SimpleLevelBar : public QWidget{ public : explicit SimpleLevelBar (QWidget *parent = nullptr ) : QWidget(parent) { setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed); setMinimumSize (40 , 16 ); } QSize sizeHint () const override { return QSize (240 , 24 ); } void setLevel (float level) { level = std::clamp (level, 0.0f , 1.0f ); if (m_level == level) { return ; } m_level = level; update (); } protected : void paintEvent (QPaintEvent *) override { QPainter painter (this ) ; painter.setRenderHint (QPainter::Antialiasing); const QRectF track = QRectF (rect ()).adjusted (2 , 2 , -2 , -2 ); painter.setPen (Qt::NoPen); painter.setBrush (QColor ("#D9DEE7" )); painter.drawRoundedRect (track, 4 , 4 ); QRectF fill = track; fill.setWidth (track.width () * m_level); painter.setBrush ( m_level > 0.8f ? QColor ("#E85D5D" ) : QColor ("#42B883" )); if (m_level > 0.0f ) { painter.drawRoundedRect (fill, 4 , 4 ); } } private : float m_level = 0.0f ; };
少量列表项,可以给每项放一个自定义 QWidget:创建列表项 → 创建一个包含 QLabel+QPushButton 的行控件 → 将行控件放到列表项里。
列表项很多时,应该使用 Delegate:第一种方法每行都创建真实 QWidget、Label、Button。几千行时,对象数量、内存和布局开销都会增加。 更适合大量数据的做法是继承 QStyledItemDelegate:
paint():画文字和按钮外观。
sizeHint():提供列表项大小。
editorEvent():处理点击,判断是否点击了按钮区域。
“继承并实现一个自定义的 QStyledItemDelegate。需要重写 paint 方法,在这个方法中使用 QPainter 来绘制,包括文本和按钮样式。为了响应交互,比如按钮的点击,还需要重写 editorEvent 方法来处理鼠标事件,判断点击位置是否在您绘制的按钮区域内,并发出自定义的信号。虽然也可以使用 QListView::setIndexWidget 为每一项直接设置一个真实的 QWidget,但这种方法会为每个列表项都创建一个完整的窗口部件实例,当列表项非常多时,会增加性能消耗”
布局方式
布局类
排列方式
适用场景
QVBoxLayout
从上到下
登录表单、纵向工具栏
QHBoxLayout
从左到右
一排按钮、输入框+发送按钮
QGridLayout
行列网格,可以跨行跨列
多列设置项、计算器键盘
QFormLayout
标签+输入控件组成的表单
登录页面、编码参数设置
QStackedLayout
多个页面叠放,默认显示一个
登录方式切换、多步骤页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 auto *layout = new QVBoxLayout (this );layout->addWidget (new QLineEdit (this )); layout->addWidget (new QLineEdit (this )); layout->addWidget (new QPushButton ("登录" , this )); auto *row = new QHBoxLayout;row->addWidget (codeEdit, 1 ); row->addWidget (getCodeButton, 0 ); mainLayout->addLayout (row);
辅助容器 QSplitter:允许用户拖动分隔线;QScrollArea:内容太多时提供滚动条。
1 2 3 4 5 6 7 auto *splitter = new QSplitter (Qt::Horizontal, this );splitter->addWidget (layerPanel); splitter->addWidget (previewPanel); mainLayout->addWidget (splitter);
1 2 3 4 5 6 7 8 9 10 11 12 auto *content = new QWidget;auto *form = new QFormLayout (content);form->addRow ("名称:" , new QLineEdit (content)); form->addRow ("地址:" , new QLineEdit (content)); auto *scroll = new QScrollArea (this );scroll->setWidgetResizable (true ); scroll->setWidget (content); mainLayout->addWidget (scroll);
QML 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import QtQuickimport QtQuick.ControlsRectangle { id: panel width : parent .width / 2 height : 160 color : "#202020" radius : 8 property bool recording : false Button { anchors.centerIn : parent text : panel.recording ? "停止录制" : "开始录制" onClicked : { panel.recording = !panel.recording; } } }
语法
含义
Rectangle {}
创建一个矩形对象
id: panel
在当前组件中引用这个对象
color: "#202020"
设置属性
property bool recording
声明自己的属性
text: panel.recording ? ...
建立依赖其他属性的绑定
onClicked: {}
响应点击信号
anchors.centerIn: parent
在父元素中居中
常见的控件:
类型
用途
在播放器中的例子
Item
无外观的基础容器
组织视频、浮层
Rectangle
背景、边框、圆角
卡片、面板、高亮边框
Text / Label
显示文字
房间标题、FPS
Image
显示图片
头像、表情
MouseArea
接收鼠标输入
直播间右键、拖动
Button
标准按钮
设置操作
TextField
单行输入
输入直播间 ID
Slider
拖动数值
音量、时间轴
CheckBox / Switch
开关状态
启用某项功能
RowLayout / ColumnLayout
自动排列并分配空间
控制栏、设置面板
ListView
滚动列表
播放列表
Repeater
根据数据生成元素
少量重复控件
Menu / MenuItem
弹出菜单和操作项
直播间右键菜单
Instantiator
根据模型创建对象
动态画质、线路菜单
Behavior / NumberAnimation
属性动画
悬浮颜色、弹幕移动
ScrollView
提供滚动容器
设置页面使用
Flickable
提供可拖拽、可惯性滚动的内容区域
是常见滚动基础组件
ScrollBar
可拖动的滚动条
项目封装为 StyledScrollBar
ScrollIndicator
主要显示滚动位置的指示器
与可操作滚动条用途不同
MenuSeparator
菜单里的分隔线
直播间右键菜单使用
ToolSeparator
工具栏里的分隔线
Qt 提供的标准组件
SplitView
带可拖动分隔条的分栏容器
主视频布局没有用它
布局方式
布局
用途
RowLayout
播放控制栏、设置项的标签和输入框横排
ColumnLayout
设置项纵排、登录框内容
GridLayout
布局预设的网格排列
StackLayout
切换“直播”“录制”设置页