解码Qt布局管理器与样式表

声明:未特殊说明基类均使用QWidget,若使用QMainWindow均已提示

布局管理器概述

Qt布局管理器是QLayout类及其子类的统称,核心作用是自动管理容器内子控件的位置和大小,适配不同尺寸的窗口/屏幕,无需手动计算控件坐标和尺寸,提升界面的可扩展性和适配性。

核心特性

  • 自动调整子控件的位置、大小,响应窗口尺寸变化;
  • 支持动态添加/移除子控件,自动重新布局;
  • 可设置对齐方式、间距、边距等属性,精细化控制布局;
  • 与控件的sizeHint(首选大小)、sizePolicy(大小策略)配合,实现更灵活的尺寸适配。

Qt中QLayout的直接/间接子类(核心布局管理器):QBoxLayoutQGridLayoutQFormLayoutQStackedLayout

image

QDockWidget(停靠窗口)、QSplitter(分割器)属于布局相关的容器组件,并非QLayout子类,但常用于复杂界面的布局组织。

核心布局管理器

QBoxLayout(盒式布局)

QBoxLayout是抽象布局类,提供水平/垂直两种布局方向,通过指定方向将子控件沿单一轴线排列。

核心方向枚举

  • QBoxLayout::LeftToRight:水平从左到右
  • QBoxLayout::RightToLeft:水平从右到左
  • QBoxLayout::TopToBottom:垂直从上到下
  • QBoxLayout::BottomToTop:垂直从下到上

核心方法

  • addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = Qt::AlignCenter):添加控件,stretch为拉伸系数(占剩余空间的比例),alignment为对齐方式;
  • addSpacing(int size):添加固定尺寸的空白间距;
  • addStretch(int stretch = 0):添加可拉伸的空白(占剩余空间);
  • setDirection(QBoxLayout::Direction direction):设置布局方向;
  • setSpacing(int spacing):设置子控件之间的间距;
  • setContentsMargins(int left, int top, int right, int bottom):设置布局的内边距(布局边缘与子控件的距离)。

示例1:QBoxLayout水平布局(带间距和边距)

#include <QApplication>
#include <QBoxLayout>
#include <QPushButton>

/**
 * @brief 主函数,演示QBoxLayout水平布局的完整用法
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码,0表示正常退出
 * @note QBoxLayout需绑定到父容器(如QWidget),子控件会随布局自动调整位置和大小
 *       setSpacing()设置子控件间距,setContentsMargins()设置布局内边距
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv); // 初始化Qt应用程序,处理事件循环
    QWidget w;                 // 主窗口容器,承载布局和控件
    w.setWindowTitle("QBoxLayout水平布局测试");

    QStringList names = {"One", "Two", "Three", "Four", "Five"};
    /**
     * @brief 创建QBoxLayout对象
     * @param direction 布局方向,LeftToRight表示水平从左到右
     * @param parent 布局的父容器,布局会自动设置为父容器的布局
     */
    QBoxLayout box(QBoxLayout::LeftToRight, &w);

    // 设置子控件间距为15px
    box.setSpacing(15);
    // 设置布局内边距:上下左右各20px
    box.setContentsMargins(20, 20, 20, 20);

    for (int i = 0; i < 5; i++) {
        QPushButton *button = new QPushButton(&w); // 创建按钮,父控件为w
        button->setText(names.at(i));              // 设置按钮文本
        /**
         * @brief 向布局添加控件
         * @param widget 要添加的子控件
         * @param stretch 拉伸系数,0表示不拉伸(按sizeHint显示)
         * @param alignment 对齐方式,AlignCenter表示居中
         */
        box.addWidget(button, 0, Qt::AlignCenter);
    }

    w.show(); // 显示主窗口
    return a.exec(); // 启动应用程序事件循环,阻塞直到程序退出
}

image

示例2:QBoxLayout垂直布局(带拉伸空白)

#include <QApplication>
#include <QBoxLayout>
#include <QPushButton>

/**
 * @brief 主函数,演示QBoxLayout垂直布局(带拉伸空白)
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码,0表示正常退出
 * @note addStretch()添加的可拉伸空白会占据剩余空间,实现控件对齐
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("QBoxLayout垂直布局测试");

    QStringList names = {"顶部按钮", "中间按钮", "底部按钮"};
    /**
     * @brief 创建垂直方向的QBoxLayout
     * @param direction TopToBottom表示垂直从上到下排列控件
     * @param parent 布局绑定到w
     */
    QBoxLayout box(QBoxLayout::TopToBottom, &w);

    box.setSpacing(10);
    box.setContentsMargins(20, 20, 20, 20);

    // 添加顶部按钮(不拉伸)
    QPushButton *btn1 = new QPushButton(names.at(0), &w);
    box.addWidget(btn1);

    // 添加可拉伸空白(系数1),推动下方控件到底部
    box.addStretch(1);

    // 添加中间按钮(不拉伸)
    QPushButton *btn2 = new QPushButton(names.at(1), &w);
    box.addWidget(btn2);

    // 添加可拉伸空白(系数1)
    box.addStretch(1);

    // 添加底部按钮(不拉伸)
    QPushButton *btn3 = new QPushButton(names.at(2), &w);
    box.addWidget(btn3);

    w.show();
    return a.exec();
}

image

QVBoxLayout&QHBoxLayout(垂直/水平布局)

QVBoxLayoutQHBoxLayoutQBoxLayout的直接子类,分别封装了垂直(TopToBottom)和水平(LeftToRight)布局方向,使用更便捷,无需手动设置方向。

核心特性

  • QVBoxLayout:子控件沿垂直方向从上到下排列,添加顺序决定显示顺序;
  • QHBoxLayout:子控件沿水平方向从左到右排列,添加顺序决定显示顺序;
  • 继承QBoxLayout的所有方法(addStretchsetSpacing等),用法完全一致。

在设计器上使用布局管理器快速设置布局,比如水平布局,和垂直布局

image

示例:QHBoxLayout + QVBoxLayout嵌套布局

#include <QApplication>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QWidget>

/**
 * @brief 主函数,演示布局嵌套(水平布局包含垂直布局)
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码
 * @note 布局嵌套是复杂界面的核心用法,通过多层布局组合实现灵活排版
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("布局嵌套示例");

    // 外层水平布局
    QHBoxLayout *hLayout = new QHBoxLayout(&w);
    hLayout->setSpacing(20);
    hLayout->setContentsMargins(20, 20, 20, 20);

    // 左侧垂直布局(包含3个按钮)
    QVBoxLayout *vLeftLayout = new QVBoxLayout();
    vLeftLayout->addWidget(new QPushButton("左侧按钮1"));
    vLeftLayout->addWidget(new QPushButton("左侧按钮2"));
    vLeftLayout->addWidget(new QPushButton("左侧按钮3"));
    vLeftLayout->setSpacing(10);

    // 右侧垂直布局(包含2个按钮+拉伸空白)
    QVBoxLayout *vRightLayout = new QVBoxLayout();
    vRightLayout->addWidget(new QPushButton("右侧按钮1"));
    vRightLayout->addWidget(new QPushButton("右侧按钮2"));
    vRightLayout->addStretch(1); // 拉伸空白占据剩余空间,按钮居上
    vRightLayout->setSpacing(10);

    // 将两个垂直布局添加到外层水平布局
    hLayout->addLayout(vLeftLayout);
    hLayout->addLayout(vRightLayout);

    w.show();
    return a.exec();
}

QFormLayout(表单布局)

QFormLayout专门用于构建表单界面,以“标签-输入控件”的两列形式排列子控件,左列显示标签(QLabel),右列显示输入型控件(QLineEditQComboBox等),自动适配标签宽度,提升表单可读性。

image

核心方法

  • addRow(const QString &labelText, QWidget *field):快速添加标签文本+输入控件;
  • addRow(QLabel *label, QWidget *field):添加自定义标签控件+输入控件;
  • addRow(QWidget *widget):添加跨两列的控件;
  • setLabelAlignment(Qt::Alignment alignment):设置左列标签的对齐方式;
  • setFieldGrowthPolicy(QFormLayout::FieldGrowthPolicy policy):设置右列输入控件的增长策略(如ExpandingFieldsGrow表示输入控件可拉伸);
  • setRowSpacing(int row, int spacing):设置指定行的间距。

示例:QFormLayout完整表单(含跨列控件)

#include <QApplication>
#include <QFormLayout>
#include <QLineEdit>
#include <QLabel>
#include <QComboBox>
#include <QPushButton>
#include <QWidget>

/**
 * @brief 主函数,演示QFormLayout完整表单的实现
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码
 * @note QFormLayout支持跨列控件和标签对齐,适合快速构建登录、注册等表单界面
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("QFormLayout完整表单");

    /**
     * @brief 创建表单布局,绑定到主窗口w
     */
    QFormLayout *formLayout = new QFormLayout(&w);
    formLayout->setSpacing(15);
    formLayout->setContentsMargins(20, 20, 20, 20);

    // 1. 添加普通行:标签文本 + 输入控件
    formLayout->addRow("用户名:", new QLineEdit());

    // 2. 密码行:自定义标签 + 密码输入框
    QLabel *pwdLabel = new QLabel("密码:");
    QLineEdit *pwdEdit = new QLineEdit();
    pwdEdit->setEchoMode(QLineEdit::Password); // 输入内容隐藏为圆点
    formLayout->addRow(pwdLabel, pwdEdit);

    // 3. 性别行:标签 + 下拉框
    QComboBox *genderCombo = new QComboBox();
    genderCombo->addItems({"男", "女", "其他"});
    formLayout->addRow("性别:", genderCombo);

    // 4. 跨列控件:按钮(占据两列)
    QPushButton *submitBtn = new QPushButton("提交");
    formLayout->addRow(submitBtn);
    // 设置跨列控件的对齐方式(居中)
    formLayout->setAlignment(submitBtn, Qt::AlignCenter);

    // 5. 设置标签对齐方式(右对齐)
    formLayout->setLabelAlignment(Qt::AlignRight);

    // 6. 设置输入控件增长策略(可拉伸)
    formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);

    w.show();
    return a.exec();
}

QGridLayout(网格布局)

QGridLayout以多行多列的网格形式排列子控件,每个控件可占据一个或多个网格单元,支持跨行/跨列布局,是最灵活的核心布局管理器,适合复杂界面的精准排版。

image

核心方法

  • addWidget(QWidget *widget, int row, int column, int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = Qt::AlignCenter):添加控件到指定网格,row/column为行列索引(从0开始),rowSpan/columnSpan为跨行/跨列数;
  • setRowStretch(int row, int stretch):设置行的拉伸系数(窗口缩放时行高的占比);
  • setColumnStretch(int column, int stretch):设置列的拉伸系数;
  • setRowMinimumHeight(int row, int minSize):设置行的最小高度;
  • setColumnMinimumWidth(int column, int minSize):设置列的最小宽度;
  • setSpacing(int spacing):设置网格单元之间的间距(行间距和列间距相同);
  • setHorizontalSpacing(int spacing):单独设置列间距;
  • setVerticalSpacing(int spacing):单独设置行间距。

示例:QGridLayout跨行跨列布局(计算器界面雏形)

#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QWidget>

/**
 * @brief 主函数,演示QGridLayout跨行跨列布局(计算器界面)
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码
 * @note 网格布局的跨行跨列功能适合需要精准排版的界面(如计算器、表格)
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("QGridLayout计算器界面");

    QGridLayout *gridLayout = new QGridLayout(&w);
    gridLayout->setSpacing(10);
    gridLayout->setContentsMargins(15, 15, 15, 15);

    // 显示框(跨4列,行索引0)
    QLineEdit *displayEdit = new QLineEdit();
    displayEdit->setReadOnly(true); // 只读,用于显示结果
    displayEdit->setAlignment(Qt::AlignRight); // 文本右对齐
    gridLayout->addWidget(displayEdit, 0, 0, 1, 4); // 1行4列

    // 按钮布局(行索引1-4,列索引0-3)
    QString btnTexts[4][4] = {
        {"7", "8", "9", "/"},
        {"4", "5", "6", "*"},
        {"1", "2", "3", "-"},
        {"0", ".", "=", "+"}
    };

    for (int row = 0; row < 4; row++) {
        for (int col = 0; col < 4; col++) {
            QPushButton *btn = new QPushButton(btnTexts[row][col]);
            gridLayout->addWidget(btn, row + 1, col); // 行索引从1开始(跳过显示框)
        }
    }

    // 特殊处理:0按钮跨2列
    QPushButton *zeroBtn = new QPushButton("0");
    gridLayout->addWidget(zeroBtn, 4, 0, 1, 2); // 行4,列0,跨2列

    // 设置列拉伸系数(所有列均分空间)
    for (int col = 0; col < 4; col++) {
        gridLayout->setColumnStretch(col, 1);
    }

    // 设置行拉伸系数(显示框不拉伸,按钮行均分)
    gridLayout->setRowStretch(0, 0);
    for (int row = 1; row < 5; row++) {
        gridLayout->setRowStretch(row, 1);
    }

    w.show();
    return a.exec();
}

布局相关高级容器组件

以下组件并非QLayout子类,但常用于复杂界面的布局组织,与布局管理器配合使用可实现更灵活的界面效果。

QStackedLayout(堆叠布局)

QStackedLayoutQLayout子类,将多个控件堆叠显示,同一时间仅一个控件可见,其余隐藏,常用于“标签页式”切换(无标题栏的简易Tab),需配合按钮、列表等控件实现切换逻辑。

核心方法

  • addWidget(QWidget *widget):添加控件到堆叠布局;
  • insertWidget(int index, QWidget *widget):在指定索引位置插入控件;
  • removeWidget(QWidget *widget):移除控件(不删除控件对象);
  • count() const:返回布局中控件的数量;
  • currentIndex() const:返回当前可见控件的索引(从0开始);
  • setCurrentIndex(int index):切换到指定索引的控件(索引超出范围则无效);
  • setCurrentWidget(QWidget *widget):切换到指定控件(控件必须已添加到布局);
  • widget(int index) const:返回指定索引的控件(索引无效则返回nullptr)。

信号

  • currentChanged(int index):当前可见控件变化时触发,参数为新索引。

示例:QStackedLayout+QListWidget实现页面切换

#include <QApplication>
#include <QStackedLayout>
#include <QHBoxLayout>
#include <QListWidget>
#include <QLabel>
#include <QWidget>

/**
 * @brief 主函数,演示QStackedLayout+QListWidget实现页面切换
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码
 * @note QStackedLayout配合QListWidget可实现类似QTabWidget的效果,更灵活可控
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("QStackedLayout页面切换");
    w.resize(600, 400);

    // 外层水平布局:列表框 + 堆叠布局
    QHBoxLayout *hLayout = new QHBoxLayout(&w);
    hLayout->setSpacing(0);
    hLayout->setContentsMargins(0, 0, 0, 0);

    // 左侧列表框(用于切换页面)
    QListWidget *listWidget = new QListWidget();
    listWidget->addItems({"页面1", "页面2", "页面3"});
    listWidget->setFixedWidth(150); // 固定宽度
    listWidget->setCurrentRow(0); // 默认选中第0行

    // 右侧堆叠布局(3个页面)
    QStackedLayout *stackLayout = new QStackedLayout();
    // 页面1:标签
    QLabel *page1 = new QLabel("这是页面1的内容\\n(可放置任意控件)");
    page1->setAlignment(Qt::AlignCenter);
    // 页面2:文本编辑框
    QLabel *page2 = new QLabel("这是页面2的内容\\n(可放置表单、按钮等)");
    page2->setAlignment(Qt::AlignCenter);
    // 页面3:图片标签(示例)
    QLabel *page3 = new QLabel("这是页面3的内容\\n(可放置图表、表格等)");
    page3->setAlignment(Qt::AlignCenter);

    stackLayout->addWidget(page1);
    stackLayout->addWidget(page2);
    stackLayout->addWidget(page3);

    // 将列表框和堆叠布局添加到外层水平布局
    hLayout->addWidget(listWidget);
    hLayout->addLayout(stackLayout);

    // 列表框选中项变化时,切换堆叠布局的页面
    QObject::connect(listWidget, &QListWidget::currentRowChanged, [&](int row) {
        /**
         * @brief setCurrentIndex() 切换到指定索引的页面
         * @param row 列表框选中行的索引,与堆叠布局的页面索引对应
         */
        stackLayout->setCurrentIndex(row);
    });

    w.show();
    return a.exec();
}

image

QDockWidget(停靠窗口)

QDockWidget是停靠窗口组件,可附着在QMainWindow的边缘(停靠区),也可浮动为独立窗口,常用于工具面板、属性面板、日志面板等,需配合QMainWindow使用(QMainWindow提供专门的停靠区支持)。

核心方法

  • QDockWidget(const QString &title, QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()):构造函数,title为窗口标题;
  • setWidget(QWidget *widget):设置停靠窗口的核心控件(如布局、表单、文本框等);
  • setAllowedAreas(Qt::DockWidgetAreas areas):设置允许停靠的区域(可组合多个区域,如Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
  • setFloating(bool floating):设置是否浮动(true为独立窗口,false为停靠状态);
  • setFeatures(QDockWidget::DockWidgetFeatures features):设置停靠窗口的功能(如DockWidgetClosable允许关闭、DockWidgetMovable允许移动);
  • setTitleBarWidget(QWidget *widget):自定义标题栏控件。

QMainWindow停靠区枚举

  • Qt::LeftDockWidgetArea:左侧停靠区
  • Qt::RightDockWidgetArea:右侧停靠区
  • Qt::TopDockWidgetArea:顶部停靠区
  • Qt::BottomDockWidgetArea:底部停靠区
  • Qt::NoDockWidgetArea:无停靠区(仅浮动)

示例:QMainWindow+多个QDockWidget实现复杂布局

#include <QApplication>
#include <QMainWindow>
#include <QTextEdit>
#include <QDockWidget>
#include <QListWidget>
#include <QVBoxLayout>
#include <QWidget>

/**
 * @brief 主函数,演示QMainWindow+多个QDockWidget的复杂布局
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码
 * @note QMainWindow可添加多个停靠窗口,支持拖拽停靠到不同区域,适合多面板工具类软件
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMainWindow w;
    w.setWindowTitle("QDockWidget复杂布局");
    w.resize(800, 600);

    // 1. 设置主窗口中心控件(核心内容区)
    QTextEdit *centralEdit = new QTextEdit();
    centralEdit->setPlaceholderText("中心内容区...");
    w.setCentralWidget(centralEdit);

    // 2. 左侧停靠窗口(列表框)
    QDockWidget *leftDock = new QDockWidget("左侧面板", &w);
    QListWidget *leftList = new QListWidget();
    leftList->addItems({"项目1", "项目2", "项目3", "项目4"});
    leftDock->setWidget(leftList);
    // 设置允许停靠的区域:左侧
    leftDock->setAllowedAreas(Qt::LeftDockWidgetArea);
    // 设置功能:可关闭、可移动
    leftDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
    // 添加到主窗口左侧停靠区
    w.addDockWidget(Qt::LeftDockWidgetArea, leftDock);

    // 3. 右侧停靠窗口(表单布局)
    QDockWidget *rightDock = new QDockWidget("右侧面板", &w);
    QWidget *rightWidget = new QWidget();
    QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
    rightLayout->addWidget(new QLabel("属性设置"));
    rightLayout->addWidget(new QLineEdit("属性1"));
    rightLayout->addWidget(new QLineEdit("属性2"));
    rightLayout->addStretch(1);
    rightDock->setWidget(rightWidget);
    // 设置允许停靠的区域:右侧
    rightDock->setAllowedAreas(Qt::RightDockWidgetArea);
    // 添加到主窗口右侧停靠区
    w.addDockWidget(Qt::RightDockWidgetArea, rightDock);

    // 4. 底部停靠窗口(日志面板)
    QDockWidget *bottomDock = new QDockWidget("日志面板", &w);
    QTextEdit *logEdit = new QTextEdit();
    logEdit->setReadOnly(true);
    logEdit->append("日志开始...");
    bottomDock->setWidget(logEdit);
    // 设置允许停靠的区域:底部
    bottomDock->setAllowedAreas(Qt::BottomDockWidgetArea);
    // 添加到主窗口底部停靠区
    w.addDockWidget(Qt::BottomDockWidgetArea, bottomDock);

    w.show();
    return a.exec();
}

image

QSplitter(分割器)

QSplitter是分割容器,可将多个控件按水平/垂直方向分割,用户可通过拖拽分割线调整各控件的大小,常用于多面板界面(如文件管理器的目录树+文件列表、代码编辑器的编辑区+侧边栏)。

核心方法

  • QSplitter(Qt::Orientation orientation, QWidget *parent = nullptr):构造函数,orientation为分割方向(Qt::Horizontal水平、Qt::Vertical垂直);
  • addWidget(QWidget *widget):添加控件到分割器(顺序决定显示位置);
  • insertWidget(int index, QWidget *widget):在指定索引位置插入控件;
  • setStretchFactor(int index, int stretch):设置指定索引控件的拉伸系数(窗口缩放时,系数越大,占比越大);
  • setSizes(const QList<int> &sizes):设置各控件的初始大小(列表长度需与控件数一致,值为像素);
  • sizes() const:返回当前各控件的大小;
  • setHandleWidth(int width):设置分割线的宽度(默认3px);
  • setOpaqueResize(bool opaque):设置是否实时调整大小(true实时调整,false拖拽时显示虚线框)。

信号

  • splitterMoved(int pos, int index):分割线移动时触发,pos为新位置,index为分割线索引。

示例:QSplitter嵌套实现文件管理器风格布局

QMainWindow

QMainWindow 不是普通的 QWidget,它的内部布局是预定义的(菜单栏、工具栏、中心控件、状态栏):

  • 只有设置为 centralWidget 的控件,才会自动占满 MainWindow 的客户区(去除菜单栏 / 状态栏后的区域);
  • 如果直接创建子控件(如 new QSplitter(Qt::Horizontal, this)),控件会以 sizeHint(最小尺寸)显示,不会自动扩展。
#include <QApplication>
#include <QSplitter>
#include <QListWidget>
#include <QTableWidget>
#include <QTextEdit>
#include <QMainWindow> // 改用QMainWindow(自带中心控件)

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 1. 主窗口用QMainWindow(自带中心区域,天然占满窗口)
    QMainWindow w;
    w.setWindowTitle("QSplitter文件管理器风格");
    w.resize(800, 600); // 窗口初始大小
    w.setMinimumSize(600, 400);

    // 2. 外层水平分割器(作为中心控件)
    QSplitter *outerSplitter = new QSplitter(Qt::Horizontal);
    w.setCentralWidget(outerSplitter); // 直接设为中心控件(必占满窗口)

    // 3. 左侧目录列表(直接加到外层分割器)
    QListWidget *dirList = new QListWidget();
    dirList->addItems({"桌面", "文档", "下载", "图片", "视频"});
    dirList->setMinimumWidth(150);
    outerSplitter->addWidget(dirList);

    // 4. 右侧垂直分割器(加到外层分割器)
    QSplitter *innerSplitter = new QSplitter(Qt::Vertical);
    outerSplitter->addWidget(innerSplitter);

    // 5. 右侧上半部分:文件表格
    QTableWidget *fileTable = new QTableWidget(5, 3);
    fileTable->setHorizontalHeaderLabels({"名称", "大小", "修改日期"});
    innerSplitter->addWidget(fileTable);

    // 6. 右侧下半部分:预览框
    QTextEdit *previewEdit = new QTextEdit();
    previewEdit->setReadOnly(true);
    previewEdit->setPlaceholderText("文件预览...");
    previewEdit->setMinimumHeight(100);
    innerSplitter->addWidget(previewEdit);

    // 7. 设置分割器初始比例(简单直观)
    outerSplitter->setSizes({150, 650}); // 左150,右650(总宽800)
    innerSplitter->setSizes({400, 200}); // 上400,下200(总高600)

    w.show();
    return a.exec();
}

Qwidget

#include <QApplication>
#include <QSplitter>
#include <QListWidget>
#include <QTableWidget>
#include <QTextEdit>
#include <QWidget>

/**
 * @brief 主函数,演示QSplitter嵌套实现文件管理器风格布局
 * @param argc 命令行参数个数
 * @param argv 命令行参数数组
 * @return int 程序退出码
 * @note QSplitter支持嵌套,可实现多层分割布局,用户可自由调整各面板大小
 */
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("QSplitter文件管理器风格");
    w.resize(800, 600);

    // 1. 外层水平分割器(左侧列表 + 右侧垂直分割器)
    QSplitter *outerSplitter = new QSplitter(Qt::Horizontal, &w);

    // 左侧:目录树列表
    QListWidget *dirList = new QListWidget();
    dirList->addItems({"桌面", "文档", "下载", "图片", "视频"});
    dirList->setMinimumWidth(150); // 设置最小宽度,防止拖拽过窄
    outerSplitter->addWidget(dirList);

    // 右侧:垂直分割器(文件列表 + 预览区)
    QSplitter *innerSplitter = new QSplitter(Qt::Vertical, outerSplitter);

    // 上半部分:文件列表(表格)
    QTableWidget *fileTable = new QTableWidget(5, 3);
    fileTable->setHorizontalHeaderLabels({"名称", "大小", "修改日期"});
    innerSplitter->addWidget(fileTable);

    // 下半部分:预览区(文本框)
    QTextEdit *previewEdit = new QTextEdit();
    previewEdit->setReadOnly(true);
    previewEdit->setPlaceholderText("文件预览...");
    previewEdit->setMinimumHeight(100); // 设置最小高度
    innerSplitter->addWidget(previewEdit);

    // 设置右侧垂直分割器的初始大小(上半部分占2/3,下半部分占1/3)
    innerSplitter->setSizes({400, 200});
    // 设置拉伸系数(文件列表可拉伸,预览区不拉伸)
    innerSplitter->setStretchFactor(0, 1);
    innerSplitter->setStretchFactor(1, 0);

    // 添加右侧垂直分割器到外层水平分割器
    outerSplitter->addWidget(innerSplitter);

    // 设置外层水平分割器的拉伸系数(左侧不拉伸,右侧可拉伸)
    outerSplitter->setStretchFactor(0, 0);
    outerSplitter->setStretchFactor(1, 1);
    // 设置分割线宽度
    outerSplitter->setHandleWidth(6);
    innerSplitter->setHandleWidth(6);

    w.show();
    return a.exec();
}

image

布局使用进阶技巧

布局的边距与间距设置

  • 边距(Contents Margins):布局边缘与父容器或子控件的距离,通过setContentsMargins(int left, int top, int right, int bottom)设置,默认有边距(通常为9px),可设为0取消边距;
  • 间距(Spacing):布局内子控件之间的距离,通过setSpacing(int spacing)设置,默认间距为6px,根据界面美观度调整。

控件的大小策略(sizePolicy)

布局管理器会参考控件的sizePolicy来分配空间,sizePolicyQt::SizePolicy枚举定义,核心值:

  • Qt::Fixed:控件大小固定(仅使用sizeHint),不拉伸、不缩小;
  • Qt::Minimum:控件最小大小为sizeHint,可拉伸;
  • Qt::Maximum:控件最大大小为sizeHint,可缩小;
  • Qt::Preferred:优先使用sizeHint,可拉伸、可缩小(默认);
  • Qt::Expanding:控件会尽可能占据剩余空间,拉伸优先级高。

设置方式

QPushButton *btn = new QPushButton("拉伸按钮");
// 设置水平方向为Expanding,垂直方向为Preferred
btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);

动态添加/移除布局中的控件

  • 添加控件:直接调用布局的addWidgetinsertWidget方法;
  • 移除控件:调用removeWidget(QWidget *widget),注意:该方法仅将控件从布局中移除,不会删除控件对象,需手动管理内存(如delete或设置父控件自动销毁)。

示例:动态添加/移除按钮

QMainWindow

#include <QApplication>
#include <QVBoxLayout>
#include <QPushButton>
#include <QMainWindow> // 主窗口改为QMainWindow
#include <QWidget>
#include <QList>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMainWindow w; // 主窗口类型改为QMainWindow
    w.setWindowTitle("动态添加/移除控件");
    w.resize(600, 400); // 主窗口初始大小
    w.setMinimumSize(400, 300); // 防止缩太小

    // 关键:创建中心容器控件(所有子控件/布局都挂载到这个Widget上)
    QWidget *centralWidget = new QWidget(&w);
    // 给中心容器设置垂直布局(替代直接给MainWindow设布局)
    QVBoxLayout *vLayout = new QVBoxLayout(centralWidget);
    vLayout->setSpacing(10);
    vLayout->setContentsMargins(20, 20, 20, 20);

    // 添加按钮(父对象改为centralWidget,而非MainWindow)
    QPushButton *addBtn = new QPushButton("添加按钮", centralWidget);
    // 移除按钮(初始禁用)
    QPushButton *removeBtn = new QPushButton("移除最后一个按钮", centralWidget);
    removeBtn->setEnabled(false);

    vLayout->addWidget(addBtn);
    vLayout->addWidget(removeBtn);

    // 存储动态添加的按钮
    QList<QPushButton*> dynamicBtns;

    // 添加按钮逻辑(完全保留原有逻辑)
    QObject::connect(addBtn, &QPushButton::clicked, [&]() {
        QPushButton *newBtn = new QPushButton(QString("动态按钮%1").arg(dynamicBtns.size() + 1), centralWidget);
        dynamicBtns.append(newBtn);
        // 插入到移除按钮之前
        vLayout->insertWidget(vLayout->count() - 1, newBtn);
        // 启用移除按钮
        removeBtn->setEnabled(true);
    });

    // 移除按钮逻辑(完全保留原有逻辑)
    QObject::connect(removeBtn, &QPushButton::clicked, [&]() {
        if (dynamicBtns.isEmpty()) return;
        QPushButton *lastBtn = dynamicBtns.takeLast();
        // 从布局中移除
        vLayout->removeWidget(lastBtn);
        // 删除按钮对象(释放内存)
        delete lastBtn;
        // 无按钮时禁用移除按钮
        if (dynamicBtns.isEmpty()) {
            removeBtn->setEnabled(false);
        }
    });

    // 核心操作:将中心容器设为MainWindow的centralWidget(必加!)
    w.setCentralWidget(centralWidget);

    w.show();
    return a.exec();
}

QWidget

#include <QApplication>
#include <QVBoxLayout>
#include <QPushButton>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("动态添加/移除控件");

    QVBoxLayout *vLayout = new QVBoxLayout(&w);
    vLayout->setSpacing(10);
    vLayout->setContentsMargins(20, 20, 20, 20);

    // 添加按钮
    QPushButton *addBtn = new QPushButton("添加按钮", &w);
    // 移除按钮(初始禁用,无控件可移除)
    QPushButton *removeBtn = new QPushButton("移除最后一个按钮", &w);
    removeBtn->setEnabled(false);

    vLayout->addWidget(addBtn);
    vLayout->addWidget(removeBtn);

    // 存储动态添加的按钮
    QList<QPushButton*> dynamicBtns;

    // 添加按钮逻辑
    QObject::connect(addBtn, &QPushButton::clicked, [&]() {
        QPushButton *newBtn = new QPushButton(QString("动态按钮%1").arg(dynamicBtns.size() + 1), &w);
        dynamicBtns.append(newBtn);
        // 插入到移除按钮之前
        vLayout->insertWidget(vLayout->count() - 1, newBtn);
        // 启用移除按钮
        removeBtn->setEnabled(true);
    });

    // 移除按钮逻辑
    QObject::connect(removeBtn, &QPushButton::clicked, [&]() {
        if (dynamicBtns.isEmpty()) return;
        QPushButton *lastBtn = dynamicBtns.takeLast();
        // 从布局中移除
        vLayout->removeWidget(lastBtn);
        // 删除按钮对象(释放内存)
        delete lastBtn;
        // 无按钮时禁用移除按钮
        if (dynamicBtns.isEmpty()) {
            removeBtn->setEnabled(false);
        }
    });

    w.show();
    return a.exec();
}

image

Qt样式表(QSS)

Qt样式表(Qt Style Sheet,QSS)是基于CSS语法的界面样式定制机制,可修改QWidget及其子类的外观(颜色、字体、边框、背景等),实现界面与业务逻辑分离,快速打造个性化界面。

样式表基础

应用方式

  • 全局应用:通过QApplication::setStyleSheet(const QString &styleSheet)设置,应用于所有控件;
  • 单个控件应用:通过QWidget::setStyleSheet(const QString &styleSheet)设置,仅应用于当前控件;
  • 父控件应用:样式会继承给子控件(除非子控件通过自身样式表覆盖);
  • 文件加载:将样式表内容写入.qss文件,通过读取文件内容应用(适合复杂样式)。

示例:从文件加载样式表

#include <QApplication>
#include <QFile>
#include <QWidget>

/**
 * @brief 从QSS文件加载样式表
 * @param filePath QSS文件路径
 * @return QString 样式表内容(加载失败返回空字符串)
 * @note 需确保文件路径正确,相对路径基于程序运行目录
 */
QString loadStyleSheet(const QString &filePath) {
    QFile file(filePath);
    if (file.open(QFile::ReadOnly | QFile::Text)) {
        // 读取文件内容并返回
        return file.readAll();
    }
    return "";
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("从文件加载QSS");

    // 加载样式表文件(假设style.qss与程序同目录)
    QString style = loadStyleSheet("style.qss");
    if (!style.isEmpty()) {
        a.setStyleSheet(style);
    }

    w.show();
    return a.exec();
}

语法规则

QSS语法与CSS基本一致,核心结构:

/* 注释:单行/多行均使用/* ... */
选择器 {
    属性1: 值1;
    属性2: 值2;
    /* 单个控件可设置多个属性 */
}

  • 选择器:指定样式应用的控件范围(如QPushButton#myBtn);
  • 属性:控件的外观属性(如colorbackground-color);
  • :属性的具体取值(如颜色名、像素值、URL、枚举值);
  • 分号:分隔多个属性-值对,最后一个属性可省略分号;
  • 优先级:子控件样式 > 父控件样式 > 全局样式;ID选择器 > 类选择器 > 类型选择器。

常用选择器类型

选择器类型语法示例说明
类型选择器QPushButton匹配所有QPushButton及其子类控件
ID选择器QPushButton#myBtn匹配objectNamemyBtnQPushButtonsetObjectName("myBtn")
类选择器.QPushButton匹配所有QPushButton控件(不包含子类)
后代选择器QGroupBox QLabel匹配QGroupBox内的所有QLabel(任意层级嵌套)
子选择器QGroupBox > QLabel匹配QGroupBox直接子控件中的QLabel(仅一级嵌套)
子控件选择器QComboBox::down-arrow匹配QComboBox的内置子控件(如下拉箭头、编辑框)
状态选择器QPushButton:hover匹配处于指定状态的控件(如悬停、按下、选中)
组合选择器QPushButton, QLabel匹配多个选择器对应的控件(用逗号分隔)
属性选择器QPushButton[enabled="false"]匹配指定属性值的控件(Qt 5.15+支持)

示例:多选择器组合使用

#include <QApplication>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("选择器组合示例");

    QGroupBox *groupBox = new QGroupBox("分组框", &w);
    QVBoxLayout *vLayout = new QVBoxLayout(groupBox);

    QLabel *label1 = new QLabel("分组框内的标签(后代选择器)");
    QPushButton *btn1 = new QPushButton("普通按钮");
    QPushButton *btn2 = new QPushButton("特殊按钮");
    btn2->setObjectName("myBtn"); // 设置ID为myBtn
    QPushButton *btn3 = new QPushButton("禁用按钮");
    btn3->setEnabled(false);

    vLayout->addWidget(label1);
    vLayout->addWidget(btn1);
    vLayout->addWidget(btn2);
    vLayout->addWidget(btn3);

    // 样式表:多选择器组合
    // R 是 C++11 及以上标准中 原始字符串字面量(Raw String Literal) 的前缀,核心作用是避免字符串内的转义字符处理
    w.setStyleSheet(R"(
        /* 类型选择器:所有QPushButton */
        QPushButton {
            color: black;
            background-color: #f0f0f0;
            padding: 6px 12px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        /* ID选择器:objectName为myBtn的QPushButton */
        QPushButton#myBtn {
            background-color: #2196F3;
            color: white;
            border: none;
        }
        /* 后代选择器:QGroupBox内的QLabel */
        QGroupBox QLabel {
            color: #333;
            font-size: 14px;
            margin-bottom: 10px;
        }
        /* 状态选择器:禁用的QPushButton */
        QPushButton:disabled {
            background-color: #e0e0e0;
            color: #999;
        }
        /* 组合选择器:QGroupBox和QLabel的边框 */
        QGroupBox, QLabel {
            border: 1px solid transparent;
        }
    )");

    w.show();
    return a.exec();
}

image

常用属性与值

属性类别常用属性取值示例
颜色相关color文字颜色:red#FF0000rgb(255,0,0)rgba(255,0,0,0.5)(半透明)
background-color背景色:blue#0000FFrgb(0,0,255)
边框相关border边框(宽度+样式+颜色):2px solid black1px dashed red
border-width边框宽度:2px1px 2px(上下1px,左右2px)
border-style边框样式:solid(实线)、dashed(虚线)、dotted(点线)、none(无)
border-color边框颜色:black#333rgb(51,51,51)
border-radius边框圆角:4px50%(圆形,需控件宽高相等)
字体相关font字体(粗细+大小+字体名):bold 14px Arial12px "微软雅黑"
font-size字体大小:12px1em(相对大小)
font-weight字体粗细:normal(正常)、bold(粗体)、700(数值,越大越粗)
font-family字体族:Arial"微软雅黑""SimSun"(宋体)
内边距/外边距padding内边距(控件内容与边框的距离):6px2px 4px(上下2px,左右4px)
margin外边距(控件边框与父容器的距离):10px5px 0(上下5px,左右0)
大小相关width/height控件宽/高:200px50%(父容器的50%)
min-width/min-height最小宽/高:100px
max-width/max-height最大宽/高:300px
背景相关background-image背景图片:url(:/images/bg.png)(资源文件)、url(./bg.png)(本地文件)
background-repeat背景重复:no-repeat(不重复)、repeat-x(水平重复)、repeat-y(垂直重复)
background-position背景位置:center(居中)、left top(左上)、50% 50%(居中)
文本相关text-align文本对齐:left(左对齐)、center(居中)、right(右对齐)
text-decoration文本装饰:none(无)、underline(下划线)、line-through(删除线)

示例:常用属性综合使用

#include <QApplication>
#include <QLabel>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("常用属性综合示例");
    w.resize(400, 300);

    QLabel *label = new QLabel("Qt样式表常用属性示例", &w);
    label->setAlignment(Qt::AlignCenter);
    label->setStyleSheet(R"(
        QLabel {
            /* 颜色 */
            color: white;
            background-color: #2196F3;
            /* 边框 */
            border: 2px solid #1976D2;
            border-radius: 8px;
            /* 字体 */
            font: bold 16px "微软雅黑";
            /* 内边距 */
            padding: 15px;
            /* 大小 */
            min-width: 200px;
            max-width: 300px;
            /* 背景图片(可选,需替换为实际路径) */
            /* background-image: url(:/images/bg.png); */
            background-repeat: no-repeat;
            background-position: center;
        }
    )");

    w.show();
    return a.exec();
}

image

继承性与优先级

  • 继承性:父控件的样式会传递给子控件,但并非所有属性都可继承(可继承属性:colorfonttext-align等;不可继承属性:background-colorborderpadding等);
  • 优先级
    • 子控件自身的样式表 > 父控件样式表 > 全局样式表;
    • 选择器优先级:ID选择器(100)> 类选择器/状态选择器(10)> 类型选择器(1);
    • 选择器越具体,优先级越高(如QGroupBox QPushButton#myBtn > QPushButton#myBtn);
    • 相同优先级时,后定义的样式覆盖先定义的样式。

伪状态样式表

概述

伪状态是控件的动态状态(如鼠标悬停、按下、禁用、选中),QSS通过选择器:伪状态为不同状态的控件设置差异化样式,伪状态可组合使用(如QPushButton:hover:pressed表示鼠标悬停且按下的状态)。

常用伪状态

伪状态说明适用控件类型
:hover鼠标悬停在控件上所有可交互控件(QPushButton、QLabel等)
:pressed控件被鼠标按下(未释放)QPushButton、QCheckBox等可点击控件
:checked控件被选中QCheckBox、QRadioButton、QAction等
:unchecked控件未被选中同上
:disabled控件禁用(setEnabled(false)所有控件
:enabled控件启用(默认状态)所有控件
:focus控件获得焦点(如输入框被点击)QLineEdit、QSpinBox等输入控件
:blur控件失去焦点同上
:selected控件内容被选中(如QListWidget项、QTextEdit文本)QListWidget、QTextEdit等
:indeterminate控件处于不确定状态(如三态复选框)QCheckBox、QRadioButton等
:on/:off控件处于开启/关闭状态(如QSwitch、QToggleButton)Qt 5.15+支持的开关控件

使用示例(按钮多状态样式)

#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("伪状态样式表示例");

    QVBoxLayout *vLayout = new QVBoxLayout(&w);
    vLayout->setSpacing(15);
    vLayout->setContentsMargins(30, 30, 30, 30);

    QPushButton *btn1 = new QPushButton("普通按钮(hover/pressed)");
    QPushButton *btn2 = new QPushButton("禁用按钮(disabled)");
    btn2->setEnabled(false);
    QPushButton *btn3 = new QPushButton("可选中按钮(checked/unchecked)");
    btn3->setCheckable(true); // 设置为可选中状态

    vLayout->addWidget(btn1);
    vLayout->addWidget(btn2);
    vLayout->addWidget(btn3);

    // 伪状态样式表
    w.setStyleSheet(R"(
        /* 默认状态 */
        QPushButton {
            color: white;
            background-color: #2196F3;
            border: none;
            border-radius: 6px;
            padding: 10px 20px;
            font-size: 14px;
            transition: background-color 0.3s; /* 过渡动画(Qt 5.15+支持) */
        }
        /* 鼠标悬停状态 */
        QPushButton:hover {
            background-color: #1976D2;
        }
        /* 鼠标按下状态 */
        QPushButton:pressed {
            background-color: #0D47A1;
            padding: 11px 19px; /* 按下时轻微缩进,模拟按压效果 */
        }
        /* 禁用状态 */
        QPushButton:disabled {
            background-color: #E0E0E0;
            color: #9E9E9E;
        }
        /* 选中状态 */
        QPushButton:checked {
            background-color: #4CAF50;
        }
        /* 选中+悬停状态(组合伪状态) */
        QPushButton:checked:hover {
            background-color: #388E3C;
        }
    )");

    w.show();
    return a.exec();
}

image

样式盒子模型

概述

Qt样式盒子模型定义了控件的四个矩形区域(从外到内),所有与尺寸相关的属性(marginborderpaddingwidthheight)均基于该模型计算:

  • Margin(外边距):控件边框与父容器或其他控件的距离,不影响控件自身大小,仅影响控件在布局中的位置;
  • Border(边框):控件的边框,包含宽度、样式、颜色,边框宽度会增加控件的实际大小;
  • Padding(内边距):控件边框与内容区域的距离,内边距会增加控件的实际大小;
  • Content(内容区域):控件的核心内容区域(如文字、图片、子控件),widthheight属性默认指内容区域的大小。

盒子模型尺寸计算

  • 实际宽度计算
    控件实际宽度 = 内容宽度(width) + 左右边框宽度(border-width) + 左右内边距(padding);
    控件实际高度 = 内容高度(height) + 上下边框宽度(border-width) + 上下内边距(padding);

应用示例

#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("样式盒子模型示例");

		QVBoxLayout *vLayout = new QVBoxLayout(&w);
    vLayout->setSpacing(20);
    vLayout->setContentsMargins(30, 30, 30, 30);
    // 示例1:默认盒子模型(content-box)
    QPushButton *btn1 = new QPushButton("盒子模型");
    // 设置固定尺寸策略(布局不拉伸)
    btn1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    btn1->setStyleSheet(R"(
        QPushButton {
            width: 200px;          /* 内容宽度200px */
            height: 50px;          /* 内容高度50px */
            padding: 10px;         /* 内边距10px(上下左右) */
            border: 2px solid #2196F3; /* 边框2px */
            background-color: #E3F2FD;
            color: #2196F3;
        }
    )");
    // 实际宽度 = 200 + 2*2 + 2*10 = 224px;实际高度 = 50 + 2*2 + 2*10 = 74px
		vLayout->addWidget(btn1);
		QLabel *lab1 = new QLabel;
    vLayout->addWidget(lab1);
    
    w.show();
    // 窗口显示后更新实际尺寸(避免布局未生效)
    lab1->setText(QString("实际尺寸:%1 × %2").arg(btn1->width()).arg(btn1->height()));
    return a.exec();
}

image

高级样式技巧

自定义子控件样式

Qt控件的内置子控件(如下拉箭头、滚动条、复选框图标)可通过::子控件名选择器定制样式,常用内置子控件:

  • QComboBox::down-arrow(下拉箭头)、::drop-down(下拉按钮区域);
  • QScrollBar::handle(滚动滑块)、::sub-line(上/左按钮)、::add-line(下/右按钮)、::groove(滚动轨道);
  • QCheckBox::indicator(复选框图标);
  • QRadioButton::indicator(单选框图标);
  • QSlider::handle(滑块)、::groove(滑动轨道);
  • QTabBar::tab(标签页)、::tab:selected(选中的标签页)。

示例:自定义QComboBox样式

#include <QApplication>
#include <QComboBox>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("自定义QComboBox样式");

    QVBoxLayout *vLayout = new QVBoxLayout(&w);
    vLayout->setContentsMargins(30, 30, 30, 30);

    QComboBox *combo = new QComboBox();
    combo->addItems({"选项1", "选项2", "选项3", "选项4"});
    combo->setMinimumWidth(200);

    // 自定义QComboBox样式
    combo->setStyleSheet(R"(
        /* 组合框整体样式 */
        QComboBox {
            padding: 8px 12px;
            border: 1px solid #DDDDDD;
            border-radius: 6px;
            font-size: 14px;
            background-color: white;
        }
        /* 下拉箭头区域 */
        QComboBox::drop-down {
            subcontrol-origin: padding;
            subcontrol-position: top right;
            width: 24px; /* 下拉箭头区域宽度 */
            border-left: 1px solid #DDDDDD;
        }
        /* 下拉箭头图标 */
        QComboBox::down-arrow {
            image: url(./images/down_arrow.png); /* 替换为实际箭头图片路径 */
            width: 16px;
            height: 16px;
        }
        /* 鼠标悬停状态 */
        QComboBox:hover {
            border-color: #2196F3;
        }
        /* 获得焦点状态 */
        QComboBox:focus {
            border-color: #2196F3;
            outline: none; /* 取消默认焦点边框 */
        }
        /* 下拉列表框样式 */
        QComboBox QAbstractItemView {
            border: 1px solid #DDDDDD;
            border-radius: 4px;
            padding: 4px;
            background-color: white;
            selection-background-color: #E3F2FD;
            selection-color: #2196F3;
        }
    )");

    vLayout->addWidget(combo);
    w.show();
    return a.exec();
}

image

背景渐变与图片

QSS支持线性渐变、径向渐变作为背景,也支持背景图片的平铺、拉伸、定位等效果。

示例:渐变背景与背景图片

#include <QApplication>
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QColor>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("渐变与背景图片示例");
    w.resize(400, 300); // 固定窗口尺寸,渐变范围足够大

    // 1. 布局:让Label完全铺满窗口,无任何边距
    QVBoxLayout *vLayout = new QVBoxLayout(&w);
    vLayout->setContentsMargins(0, 0, 0, 0); // 彻底去掉布局边距
    vLayout->setSpacing(0);

    QLabel *label = new QLabel("渐变背景 + 背景图片", &w);
    label->setAlignment(Qt::AlignCenter);
    vLayout->addWidget(label);

    // 2. 调整渐变:加大颜色对比度,让过渡更明显
    // 先注释图片,确认渐变可见;之后再加半透明图片
    label->setStyleSheet(R"(
        QLabel {
            /* 强制Label占满窗口(双重保障) */
            min-width: 400px;
            min-height: 300px;
            /* 高对比度渐变:从深蓝→亮橙,对角线过渡,视觉超明显 */
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                                       stop:0 #0066CC, stop:0.5 #FF9900, stop:1 #FF3366);
            /* 先注释图片,确认渐变可见后再取消注释 */
            /* background-image: url(./images/logo.png); */
            background-repeat: no-repeat;
            background-position: center;
            /* 文字样式增强,和渐变对比明显 */
            color: white;
            font: bold 20px "微软雅黑";
        }
    )");

    // 3. (可选)如果要加图片:设置图片半透明,不遮挡渐变
    // 替换为你的图片路径(本地绝对路径,比如 D:/logo.png)
    // QPixmap pixmap("./images/logo.png");
    // // 图片半透明(0.3=30%透明度)+ 按比例缩放
    // pixmap = pixmap.scaled(label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    // QPixmap transparentPixmap(pixmap.size());
    // transparentPixmap.fill(Qt::transparent);
    // QPainter painter(&transparentPixmap);
    // painter.setOpacity(0.3); // 图片透明度
    // painter.drawPixmap(0, 0, pixmap);
    // painter.end();
    // label->setPixmap(transparentPixmap);
    // label->setScaledContents(false); // 保持图片比例

    w.show();
    return a.exec();
}

image

渐变类型说明

  • qlineargradient(x1,y1,x2,y2, stop:0 颜色1, stop:1 颜色2):线性渐变,x1,y1x2,y2为渐变起点和终点(0-1之间,0表示左/上,1表示右/下);
  • qradialgradient(cx,cy,r, fx,fy, fr, stop:0 颜色1, stop:1 颜色2):径向渐变,cx,cy为圆心,r为半径,fx,fy为焦点,fr为焦点半径;
  • qconicalgradient(cx,cy, angle, stop:0 颜色1, stop:1 颜色2):锥形渐变,cx,cy为中心,angle为起始角度(0-360)。

样式表的动态切换

通过修改控件或应用程序的styleSheet属性,可实现样式的动态切换(如白天/黑夜模式)。

示例:动态切换样式(白天/黑夜模式)

#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

// 白天模式样式
const QString dayStyle = R"(
    QWidget {
        background-color: #F5F5F5;
    }
    QPushButton {
        color: white;
        background-color: #2196F3;
        border: none;
        border-radius: 6px;
        padding: 10px 20px;
    }
    QPushButton:hover {
        background-color: #1976D2;
    }
)";

// 黑夜模式样式
const QString nightStyle = R"(
    QWidget {
        background-color: #212121;
    }
    QPushButton {
        color: white;
        background-color: #616161;
        border: none;
        border-radius: 6px;
        padding: 10px 20px;
    }
    QPushButton:hover {
        background-color: #757575;
    }
)";

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.setWindowTitle("动态切换样式");

    QVBoxLayout *vLayout = new QVBoxLayout(&w);
    vLayout->setSpacing(20);
    vLayout->setContentsMargins(30, 30, 30, 30);

    QPushButton *toggleBtn = new QPushButton("切换到黑夜模式");
    QPushButton *testBtn = new QPushButton("测试按钮");

    vLayout->addWidget(toggleBtn);
    vLayout->addWidget(testBtn);

    // 初始设置白天模式
    a.setStyleSheet(dayStyle);

    // 切换样式逻辑
    bool isDayMode = true;
    QObject::connect(toggleBtn, &QPushButton::clicked, [&]() {
        if (isDayMode) {
            // 切换到黑夜模式
            a.setStyleSheet(nightStyle);
            toggleBtn->setText("切换到白天模式");
        } else {
            // 切换到白天模式
            a.setStyleSheet(dayStyle);
            toggleBtn->setText("切换到黑夜模式");
        }
        isDayMode = !isDayMode;
    });

    w.show();
    return a.exec();
}

image

常见问题与注意事项

  • 路径问题:背景图片、图标等资源文件路径需正确,建议使用Qt资源文件(.qrc)管理资源,路径格式为url(目录/文件名)
  • 属性支持:部分QSS属性仅支持特定Qt版本,使用前需确认版本兼容性;
  • 自定义控件样式:自定义控件需重写paintEvent方法或使用setStyleSheet支持,部分复杂控件(如自定义绘制的控件)可能需要手动处理样式表;
  • 性能问题:复杂样式表(如大量渐变、背景图片)可能影响界面渲染性能,建议简化不必要的样式;
  • 冲突问题:避免同时使用Qt内置样式(如QApplication::setStyle)和QSS,可能导致样式冲突;
  • 调试技巧:使用QApplication::styleSheet()获取当前样式表,检查语法错误;通过qDebug()输出样式表应用日志,排查问题。
基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样统计,通过模拟系统元件的故障修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值