强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Qt 与 GTK 图形框架教程 / 03 - Qt Widgets 控件 / Qt Widgets

Qt Widgets 控件 / Qt Widgets

全面掌握 Qt Widgets 体系:布局管理、常用控件、对话框、菜单栏和样式定制。 Master Qt Widgets: layouts, controls, dialogs, menus, and styling.


3.1 控件总览 / Widget Overview

核心控件分类 / Core Widget Categories

类别 / Category控件 / Widgets说明 / Description
按钮QPushButton, QToolButton, QRadioButton, QCheckBox各类交互按钮
输入QLineEdit, QTextEdit, QSpinBox, QComboBox文本与数值输入
显示QLabel, QProgressBar, QLCDNumber信息展示
容器QWidget, QGroupBox, QTabWidget, QStackedWidget控件容器
项视图QListView, QTreeView, QTableView模型-视图架构
对话框QMessageBox, QFileDialog, QColorDialog标准对话框
主窗口QMainWindow, QDockWidget, QStatusBar应用主框架

继承层次 / Inheritance Hierarchy

QObject
└── QPaintDevice
    └── QWidget              ← 所有控件的基类
        ├── QLabel           ← 文本/图片标签
        ├── QPushButton      ← 按钮
        ├── QLineEdit        ← 单行文本
        ├── QTextEdit        ← 多行富文本
        ├── QComboBox        ← 下拉列表
        ├── QSpinBox         ← 数值输入
        ├── QCheckBox        ← 复选框
        ├── QRadioButton     ← 单选按钮
        ├── QSlider          ← 滑块
        ├── QProgressBar     ← 进度条
        ├── QListView        ← 列表视图
        ├── QTreeView        ← 树视图
        ├── QTableView       ← 表格视图
        ├── QGroupBox        ← 分组框
        ├── QTabWidget       ← 选项卡容器
        └── QMainWindow      ← 主窗口
            ├── QMenuBar     ← 菜单栏
            ├── QToolBar     ← 工具栏
            └── QStatusBar   ← 状态栏

3.2 布局管理 / Layout Management

布局管理器自动处理控件的尺寸和位置,是实现自适应界面的关键。 Layout managers automatically handle widget size and position.

布局类型 / Layout Types

布局 / Layout类 / Class用途 / Purpose
水平QHBoxLayout水平排列 / Horizontal arrangement
垂直QVBoxLayout垂直排列 / Vertical arrangement
网格QGridLayout行列网格 / Row-column grid
表单QFormLayout标签-字段对 / Label-field pairs
堆叠QStackedLayout一次显示一个 / Show one at a time

C++ 完整示例 / C++ Complete Example

// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QFormLayout>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include <QComboBox>
#include <QSpinBox>
#include <QGroupBox>
#include <QTabWidget>
#include <QSplitter>
#include <QMessageBox>
#include <QFileDialog>
#include <QStatusBar>
#include <QMenuBar>
#include <QToolBar>
#include <QAction>
#include <QApplication>

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);

private slots:
    void onNewFile();
    void onAbout();

private:
    void createMenus();
    void createToolBar();
    void createStatusBar();
    QWidget *createFormTab();
    QWidget *createLayoutTab();

    QTextEdit *m_textEdit;
};

#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle("Qt Widgets 示例 / Qt Widgets Example");
    resize(800, 600);

    createMenus();
    createToolBar();
    createStatusBar();

    // 主选项卡容器
    auto *tabs = new QTabWidget(this);
    tabs->addTab(createFormTab(), "表单 / Form");
    tabs->addTab(createLayoutTab(), "布局 / Layout");

    setCentralWidget(tabs);
}

// ============================================================
// 菜单栏 / Menu Bar
// ============================================================
void MainWindow::createMenus()
{
    // 文件菜单 / File Menu
    auto *fileMenu = menuBar()->addMenu("文件(&F)");
    auto *newAct = new QAction("新建(&N)", this);
    newAct->setShortcut(QKeySequence::New);
    connect(newAct, &QAction::triggered, this, &MainWindow::onNewFile);
    fileMenu->addAction(newAct);

    auto *openAct = new QAction("打开(&O)", this);
    openAct->setShortcut(QKeySequence::Open);
    fileMenu->addAction(openAct);

    fileMenu->addSeparator();

    auto *exitAct = new QAction("退出(&Q)", this);
    exitAct->setShortcut(QKeySequence::Quit);
    connect(exitAct, &QAction::triggered, qApp, &QApplication::quit);
    fileMenu->addAction(exitAct);

    // 编辑菜单 / Edit Menu
    auto *editMenu = menuBar()->addMenu("编辑(&E)");
    editMenu->addAction("撤销(&U)", QKeySequence::Undo);
    editMenu->addAction("重做(&R)", QKeySequence::Redo);
    editMenu->addSeparator();
    editMenu->addAction("剪切(&T)", QKeySequence::Cut);
    editMenu->addAction("复制(&C)", QKeySequence::Copy);
    editMenu->addAction("粘贴(&P)", QKeySequence::Paste);

    // 帮助菜单 / Help Menu
    auto *helpMenu = menuBar()->addMenu("帮助(&H)");
    auto *aboutAct = new QAction("关于(&A)", this);
    connect(aboutAct, &QAction::triggered, this, &MainWindow::onAbout);
    helpMenu->addAction(aboutAct);
}

// ============================================================
// 工具栏 / Tool Bar
// ============================================================
void MainWindow::createToolBar()
{
    auto *toolbar = addToolBar("主工具栏 / Main");
    toolbar->setMovable(false);

    toolbar->addAction("新建", this, &MainWindow::onNewFile);
    toolbar->addAction("打开");
    toolbar->addAction("保存");
    toolbar->addSeparator();
    toolbar->addAction("剪切");
    toolbar->addAction("复制");
    toolbar->addAction("粘贴");
}

// ============================================================
// 状态栏 / Status Bar
// ============================================================
void MainWindow::createStatusBar()
{
    statusBar()->showMessage("就绪 / Ready", 3000);
}

// ============================================================
// 表单布局 Tab / Form Layout Tab
// ============================================================
QWidget *MainWindow::createFormTab()
{
    auto *widget = new QWidget;
    auto *formLayout = new QFormLayout(widget);
    formLayout->setLabelAlignment(Qt::AlignRight);

    auto *nameEdit = new QLineEdit;
    nameEdit->setPlaceholderText("请输入姓名 / Enter name");
    formLayout->addRow("姓名 / Name:", nameEdit);

    auto *emailEdit = new QLineEdit;
    emailEdit->setPlaceholderText("请输入邮箱 / Enter email");
    formLayout->addRow("邮箱 / Email:", emailEdit);

    auto *ageSpin = new QSpinBox;
    ageSpin->setRange(0, 150);
    ageSpin->setValue(25);
    formLayout->addRow("年龄 / Age:", ageSpin);

    auto *countryCombo = new QComboBox;
    countryCombo->addItems({"中国 / China", "美国 / USA", "日本 / Japan",
                            "德国 / Germany", "其他 / Other"});
    formLayout->addRow("国家 / Country:", countryCombo);

    auto *bioEdit = new QTextEdit;
    bioEdit->setPlaceholderText("个人简介 / Bio...");
    bioEdit->setMaximumHeight(100);
    formLayout->addRow("简介 / Bio:", bioEdit);

    // 按钮行 / Button row
    auto *btnLayout = new QHBoxLayout;
    auto *submitBtn = new QPushButton("提交 / Submit");
    auto *resetBtn = new QPushButton("重置 / Reset");
    btnLayout->addStretch();
    btnLayout->addWidget(submitBtn);
    btnLayout->addWidget(resetBtn);
    formLayout->addRow("", btnLayout);

    return widget;
}

// ============================================================
// 网格布局 Tab / Grid Layout Tab
// ============================================================
QWidget *MainWindow::createLayoutTab()
{
    auto *widget = new QWidget;
    auto *grid = new QGridLayout(widget);

    // 第一行:水平布局 / Row 1: horizontal layout
    auto *hGroupBox = new QGroupBox("水平布局 / HBoxLayout");
    auto *hLayout = new QHBoxLayout(hGroupBox);
    for (int i = 1; i <= 4; ++i) {
        hLayout->addWidget(new QPushButton(QString("按钮 %1").arg(i)));
    }
    grid->addWidget(hGroupBox, 0, 0, 1, 2);

    // 第二行左侧:垂直布局 / Row 2 left: vertical layout
    auto *vGroupBox = new QGroupBox("垂直布局 / VBoxLayout");
    auto *vLayout = new QVBoxLayout(vGroupBox);
    for (int i = 1; i <= 3; ++i) {
        vLayout->addWidget(new QPushButton(QString("项 %1").arg(i)));
    }
    vLayout->addStretch();
    grid->addWidget(vGroupBox, 1, 0);

    // 第二行右侧:分割器 / Row 2 right: splitter
    m_textEdit = new QTextEdit;
    m_textEdit->setPlainText("这是文本编辑器 / This is a text editor");
    auto *rightLabel = new QLabel("右侧面板 / Right Panel");
    rightLabel->setAlignment(Qt::AlignCenter);
    rightLabel->setStyleSheet("background: #e0e0e0; padding: 20px;");

    auto *splitter = new QSplitter(Qt::Vertical);
    splitter->addWidget(m_textEdit);
    splitter->addWidget(rightLabel);
    grid->addWidget(splitter, 1, 1);

    return widget;
}

void MainWindow::onNewFile()
{
    statusBar()->showMessage("新建文件 / New file created", 3000);
}

void MainWindow::onAbout()
{
    QMessageBox::about(this, "关于 / About",
        "Qt Widgets 示例程序\nQt Widgets Example\n\nVersion 1.0");
}

Python 完整示例 / Python Complete Example (PySide6)

#!/usr/bin/env python3
"""Qt Widgets 完整示例 - PySide6"""

import sys
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QTabWidget,
    QHBoxLayout, QVBoxLayout, QGridLayout, QFormLayout,
    QPushButton, QLabel, QLineEdit, QTextEdit,
    QComboBox, QSpinBox, QGroupBox, QSplitter,
    QMessageBox, QFileDialog, QStatusBar,
    QToolBar
)
from PySide6.QtGui import QAction, QKeySequence
from PySide6.QtCore import Qt


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Qt Widgets 示例 / Qt Widgets Example")
        self.resize(800, 600)

        self._create_menus()
        self._create_toolbar()
        self._create_statusbar()

        tabs = QTabWidget()
        tabs.addTab(self._create_form_tab(), "表单 / Form")
        tabs.addTab(self._create_layout_tab(), "布局 / Layout")
        self.setCentralWidget(tabs)

    def _create_menus(self):
        # 文件菜单
        file_menu = self.menuBar().addMenu("文件(&F)")

        new_act = QAction("新建(&N)", self)
        new_act.setShortcut(QKeySequence.StandardKey.New)
        new_act.triggered.connect(self._on_new_file)
        file_menu.addAction(new_act)

        file_menu.addSeparator()

        exit_act = QAction("退出(&Q)", self)
        exit_act.setShortcut(QKeySequence.StandardKey.Quit)
        exit_act.triggered.connect(QApplication.quit)
        file_menu.addAction(exit_act)

        # 帮助菜单
        help_menu = self.menuBar().addMenu("帮助(&H)")
        about_act = QAction("关于(&A)", self)
        about_act.triggered.connect(self._on_about)
        help_menu.addAction(about_act)

    def _create_toolbar(self):
        toolbar = self.addToolBar("主工具栏")
        toolbar.setMovable(False)
        toolbar.addAction("新建", self._on_new_file)
        toolbar.addAction("打开")
        toolbar.addAction("保存")

    def _create_statusbar(self):
        self.statusBar().showMessage("就绪 / Ready", 3000)

    def _create_form_tab(self) -> QWidget:
        widget = QWidget()
        form = QFormLayout(widget)
        form.setLabelAlignment(Qt.AlignmentFlag.AlignRight)

        name_edit = QLineEdit()
        name_edit.setPlaceholderText("请输入姓名")
        form.addRow("姓名 / Name:", name_edit)

        email_edit = QLineEdit()
        email_edit.setPlaceholderText("请输入邮箱")
        form.addRow("邮箱 / Email:", email_edit)

        age_spin = QSpinBox()
        age_spin.setRange(0, 150)
        age_spin.setValue(25)
        form.addRow("年龄 / Age:", age_spin)

        country = QComboBox()
        country.addItems(["中国", "美国", "日本", "德国", "其他"])
        form.addRow("国家 / Country:", country)

        bio = QTextEdit()
        bio.setPlaceholderText("个人简介...")
        bio.setMaximumHeight(100)
        form.addRow("简介 / Bio:", bio)

        btn_layout = QHBoxLayout()
        btn_layout.addStretch()
        btn_layout.addWidget(QPushButton("提交 / Submit"))
        btn_layout.addWidget(QPushButton("重置 / Reset"))
        form.addRow("", btn_layout)

        return widget

    def _create_layout_tab(self) -> QWidget:
        widget = QWidget()
        grid = QGridLayout(widget)

        # 水平布局
        h_group = QGroupBox("水平布局 / HBoxLayout")
        h_layout = QHBoxLayout(h_group)
        for i in range(1, 5):
            h_layout.addWidget(QPushButton(f"按钮 {i}"))
        grid.addWidget(h_group, 0, 0, 1, 2)

        # 垂直布局
        v_group = QGroupBox("垂直布局 / VBoxLayout")
        v_layout = QVBoxLayout(v_group)
        for i in range(1, 4):
            v_layout.addWidget(QPushButton(f"项 {i}"))
        v_layout.addStretch()
        grid.addWidget(v_group, 1, 0)

        # 分割器
        text_edit = QTextEdit()
        text_edit.setPlainText("文本编辑器 / Text Editor")
        label = QLabel("右侧面板 / Right Panel")
        label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        label.setStyleSheet("background: #e0e0e0; padding: 20px;")

        splitter = QSplitter(Qt.Orientation.Vertical)
        splitter.addWidget(text_edit)
        splitter.addWidget(label)
        grid.addWidget(splitter, 1, 1)

        return widget

    def _on_new_file(self):
        self.statusBar().showMessage("新建文件 / New file", 3000)

    def _on_about(self):
        QMessageBox.about(self, "关于 / About",
                          "Qt Widgets 示例程序\nVersion 1.0")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

3.3 布局伸缩因子 / Layout Stretch Factors

伸缩因子控制控件在窗口缩放时的相对比例。 Stretch factors control the relative ratio when the window resizes.

// 伸缩因子示例 / Stretch factor example
auto *layout = new QHBoxLayout;

// 左侧占 1 份,右侧占 3 份(窗口缩放时右侧是左侧的 3 倍宽)
auto *leftPanel = new QWidget;
auto *rightPanel = new QWidget;

layout->addWidget(leftPanel, 1);   // stretch = 1
layout->addWidget(rightPanel, 3);  // stretch = 3

布局尺寸策略 / Size Policy

策略 / Policy说明 / Description
Fixed固定大小,不拉伸 / Fixed size, no stretch
Minimum最小尺寸,可拉伸 / Minimum size, can stretch
Maximum最大尺寸,可压缩 / Maximum size, can shrink
Preferred首选尺寸,可拉伸压缩 / Preferred, flexible
Expanding尽量占据更多空间 / Expands as much as possible
MinimumExpanding最小尺寸,但尽量扩展 / Min size, tries to expand
auto *btn = new QPushButton("固定宽度");
btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
btn->setFixedWidth(120);

3.4 常用对话框 / Standard Dialogs

对话框速查表 / Dialog Quick Reference

对话框 / Dialog类 / Class用途 / Purpose
信息框QMessageBox::information()提示信息 / Info message
警告框QMessageBox::warning()警告信息 / Warning
错误框QMessageBox::critical()错误信息 / Critical error
确认框QMessageBox::question()确认操作 / Confirmation
文件选择QFileDialog::getOpenFileName()打开文件 / Open file
保存文件QFileDialog::getSaveFileName()保存文件 / Save file
选择目录QFileDialog::getExistingDirectory()选目录 / Select dir
颜色选择QColorDialog::getColor()选颜色 / Pick color
字体选择QFontDialog::getFont()选字体 / Pick font
输入文本QInputDialog::getText()文本输入 / Text input

C++ 示例 / C++ Example

#include <QMessageBox>
#include <QFileDialog>
#include <QColorDialog>
#include <QFontDialog>
#include <QInputDialog>

void dialogExamples(QWidget *parent)
{
    // 信息框
    QMessageBox::information(parent, "提示 / Info",
        "操作成功完成\nOperation completed.");

    // 确认框
    auto reply = QMessageBox::question(parent, "确认 / Confirm",
        "确定要删除吗?\nAre you sure to delete?",
        QMessageBox::Yes | QMessageBox::No);
    if (reply == QMessageBox::Yes) {
        // 执行删除
    }

    // 文件选择
    QString file = QFileDialog::getOpenFileName(parent,
        "打开文件 / Open File",
        QDir::homePath(),
        "文本文件 (*.txt);;所有文件 (*.*)");

    // 颜色选择
    QColor color = QColorDialog::getColor(Qt::white, parent,
        "选择颜色 / Pick Color");
    if (color.isValid()) {
        qDebug() << "Selected color:" << color.name();
    }

    // 字体选择
    bool ok;
    QFont font = QFontDialog::getFont(&ok, QFont("Arial", 12), parent);
    if (ok) {
        qDebug() << "Selected font:" << font.family();
    }

    // 输入对话框
    QString text = QInputDialog::getText(parent,
        "输入 / Input", "请输入名称 / Enter name:",
        QLineEdit::Normal, "", &ok);
    if (ok && !text.isEmpty()) {
        qDebug() << "User entered:" << text;
    }
}

Python 示例 / Python Example

from PySide6.QtWidgets import (
    QMessageBox, QFileDialog, QColorDialog,
    QFontDialog, QInputDialog
)
from PySide6.QtGui import QColor, QFont

def dialog_examples(parent):
    """常用对话框示例"""
    # 信息框
    QMessageBox.information(parent, "提示", "操作成功")

    # 确认框
    reply = QMessageBox.question(parent, "确认", "确定要删除吗?",
        QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
    if reply == QMessageBox.StandardButton.Yes:
        print("User confirmed deletion")

    # 文件选择
    file, _ = QFileDialog.getOpenFileName(
        parent, "打开文件", "", "文本文件 (*.txt);;所有文件 (*)")

    # 颜色选择
    color = QColorDialog.getColor(QColor("white"), parent, "选择颜色")
    if color.isValid():
        print(f"Selected: {color.name()}")

    # 输入对话框
    text, ok = QInputDialog.getText(parent, "输入", "请输入名称:")
    if ok and text:
        print(f"Entered: {text}")

3.5 样式与 QSS / Styling with QSS

Qt 样式表(QSS)语法类似 CSS,用于定制控件外观。 Qt Style Sheets (QSS) syntax is similar to CSS for customizing widget appearance.

常用 QSS 选择器 / Common QSS Selectors

选择器 / Selector示例 / Example说明 / Description
类型选择器QPushButton { }所有 QPushButton / All QPushButtons
类选择器.QPushButton { }精确类型 / Exact type only
ID 选择器#myButton { }objectName 匹配 / By objectName
属性选择器QPushButton[flat="true"] { }属性匹配 / By property
后代选择器QGroupBox QPushButton { }后代控件 / Descendant widgets
子选择器QGroupBox > QPushButton { }直接子控件 / Direct children
伪状态QPushButton:hover { }鼠标悬停 / Mouse hover

完整样式示例 / Complete Style Example

// appstyle.h
#ifndef APPSTYLE_H
#define APPSTYLE_H

#include <QString>

inline QString applicationStyle() {
    return R"(
        /* 主窗口 / Main Window */
        QMainWindow {
            background-color: #f5f5f5;
        }

        /* 菜单栏 / Menu Bar */
        QMenuBar {
            background-color: #2c3e50;
            color: #ecf0f1;
            padding: 2px;
        }
        QMenuBar::item:selected {
            background-color: #3498db;
            border-radius: 4px;
        }
        QMenu {
            background-color: #2c3e50;
            color: #ecf0f1;
            border: 1px solid #34495e;
        }
        QMenu::item:selected {
            background-color: #3498db;
        }

        /* 按钮 / Buttons */
        QPushButton {
            background-color: #3498db;
            color: white;
            border: none;
            border-radius: 4px;
            padding: 8px 16px;
            font-weight: bold;
        }
        QPushButton:hover {
            background-color: #2980b9;
        }
        QPushButton:pressed {
            background-color: #21618c;
        }
        QPushButton:disabled {
            background-color: #bdc3c7;
            color: #7f8c8d;
        }

        /* 危险按钮 / Danger Button */
        QPushButton[cssClass="danger"] {
            background-color: #e74c3c;
        }
        QPushButton[cssClass="danger"]:hover {
            background-color: #c0392b;
        }

        /* 输入框 / Input Fields */
        QLineEdit, QTextEdit, QSpinBox, QComboBox {
            background-color: white;
            border: 2px solid #dcdde1;
            border-radius: 4px;
            padding: 6px;
            color: #2c3e50;
        }
        QLineEdit:focus, QTextEdit:focus {
            border-color: #3498db;
        }

        /* 选项卡 / Tabs */
        QTabWidget::pane {
            border: 1px solid #dcdde1;
            border-radius: 4px;
            background: white;
        }
        QTabBar::tab {
            background: #dcdde1;
            padding: 8px 16px;
            margin-right: 2px;
            border-top-left-radius: 4px;
            border-top-right-radius: 4px;
        }
        QTabBar::tab:selected {
            background: white;
            font-weight: bold;
        }

        /* 分组框 / Group Box */
        QGroupBox {
            font-weight: bold;
            border: 1px solid #dcdde1;
            border-radius: 4px;
            margin-top: 8px;
            padding-top: 16px;
        }
        QGroupBox::title {
            subcontrol-origin: margin;
            left: 10px;
            padding: 0 6px;
        }

        /* 状态栏 / Status Bar */
        QStatusBar {
            background-color: #2c3e50;
            color: #ecf0f1;
        }

        /* 滚动条 / Scrollbar */
        QScrollBar:vertical {
            background: #f5f5f5;
            width: 10px;
            border-radius: 5px;
        }
        QScrollBar::handle:vertical {
            background: #bdc3c7;
            border-radius: 5px;
            min-height: 30px;
        }
        QScrollBar::handle:vertical:hover {
            background: #95a5a6;
        }
    )";
}

#endif // APPSTYLE_H
// main.cpp - 应用样式
#include <QApplication>
#include "mainwindow.h"
#include "appstyle.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    app.setStyleSheet(applicationStyle());

    MainWindow window;
    window.show();
    return app.exec();
}

3.6 QMessageBox 按钮定制 / Custom QMessageBox

// 自定义消息框 / Custom message box
QMessageBox msgBox;
msgBox.setWindowTitle("保存更改 / Save Changes");
msgBox.setText("文档已修改。是否保存?\nDocument modified. Save?");
msgBox.setInformativeText("您的更改将丢失,如果不保存。\n"
                          "Changes will be lost if not saved.");
msgBox.setStandardButtons(QMessageBox::Save
                        | QMessageBox::Discard
                        | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
msgBox.setIcon(QMessageBox::Warning);

int ret = msgBox.exec();
switch (ret) {
    case QMessageBox::Save:
        // 保存
        break;
    case QMessageBox::Discard:
        // 丢弃
        break;
    case QMessageBox::Cancel:
        // 取消
        break;
}

注意事项 / Important Notes

⚠️ 不要手动设置几何属性 / Don’t Set Geometry Manually

使用布局管理器而非 setGeometry()。手动设置的控件在窗口缩放时不会自适应。 Use layouts instead of setGeometry(). Manual geometry won’t adapt on resize.

⚠️ QSS 性能 / QSS Performance

大量使用复杂 QSS 选择器可能影响性能。优先使用 ID 选择器 #name。 Heavy QSS selectors may impact performance. Prefer ID selectors #name.

⚠️ 内存管理 / Memory Management

传入父对象的控件会自动释放。new 时务必指定 parent 或手动 delete。 Widgets with parents are auto-deleted. Always pass parent or manually delete.

⚠️ 对话框阻塞 / Dialog Blocking

QMessageBox::exec()QFileDialog::getOpenFileName() 是阻塞调用。 非模态对话框使用 show() 代替 exec()

exec() calls are blocking. Use show() for non-modal dialogs.


业务场景 / Business Scenarios

场景 / Scenario推荐控件 / Recommended
设置面板QFormLayout + QGroupBox + QTabWidget
数据录入表单QFormLayout + QSpinBox + QComboBox
文本编辑器QTextEdit + QMenuBar + QToolBar + QStatusBar
文件管理器QTreeView + QListView + QSplitter
仪表盘QGridLayout + 自定义 QWidget + QChart
属性编辑器QTreeView + QStyledItemDelegate

扩展阅读 / Further Reading

资源 / Resource链接 / Link
Qt Widgets 文档https://doc.qt.io/qt-6/widget-classes.html
布局管理https://doc.qt.io/qt-6/layout.html
QSS 参考https://doc.qt.io/qt-6/stylesheet-reference.html
Qt Designer 教程https://doc.qt.io/qt-6/designer-using-a-ui-file.html

02 - Qt 基础 | 04 - QML 与 Qt Quick