You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在父QWidget布局(含QSplitter)中显示子QWidget标题栏?

Qt实现带嵌入式标题栏的子控件方案

针对你需要在QSplitter中的子QWidget顶部添加标题栏的需求,以下是三种实用实现方式:


1. 自定义带标题栏的Widget(最灵活)

通过继承QWidget实现完全自定义的标题栏+内容区域,可自由添加按钮、调整样式。

实现代码

头文件 FramedWidget.h

#ifndef FRAMEDWIDGET_H
#define FRAMEDWIDGET_H

#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>

class FramedWidget : public QWidget
{
    Q_OBJECT
public:
    explicit FramedWidget(const QString& title, QWidget *parent = nullptr);
    void setContentWidget(QWidget* widget);

private:
    QVBoxLayout* m_mainLayout;
    QWidget* m_titleBar;
    QLabel* m_titleLabel;
};

#endif // FRAMEDWIDGET_H

源文件 FramedWidget.cpp

#include "FramedWidget.h"
#include <QHBoxLayout>

FramedWidget::FramedWidget(const QString& title, QWidget *parent)
    : QWidget(parent)
{
    m_mainLayout = new QVBoxLayout(this);
    m_mainLayout->setContentsMargins(0,0,0,0);
    m_mainLayout->setSpacing(0);

    // 构建标题栏
    m_titleBar = new QWidget(this);
    m_titleBar->setStyleSheet("background-color: #eee; border: 1px solid #ccc; border-bottom: none;");
    auto titleLayout = new QHBoxLayout(m_titleBar);
    titleLayout->setContentsMargins(8, 2, 8, 2);

    m_titleLabel = new QLabel(title, this);
    m_titleLabel->setStyleSheet("font-weight: bold;");
    titleLayout->addWidget(m_titleLabel);
    titleLayout->addStretch(); // 此处可添加关闭、折叠等按钮

    m_mainLayout->addWidget(m_titleBar);

    // 构建内容容器
    auto contentContainer = new QWidget(this);
    contentContainer->setStyleSheet("border: 1px solid #ccc; border-top: none;");
    auto contentLayout = new QVBoxLayout(contentContainer);
    contentLayout->setContentsMargins(0,0,0,0);
    m_mainLayout->addWidget(contentContainer);
}

void FramedWidget::setContentWidget(QWidget* widget)
{
    auto contentLayout = qobject_cast<QVBoxLayout*>(m_mainLayout->itemAt(1)->widget()->layout());
    if(contentLayout && widget) {
        contentLayout->addWidget(widget);
    }
}

使用示例

QSplitter* splitter = new QSplitter(Qt::Horizontal, this);

// 创建带标题的左侧控件
FramedWidget* leftFrame = new FramedWidget("左侧功能区", this);
QWidget* leftContent = new QWidget();
// 向leftContent添加你的功能控件
leftFrame->setContentWidget(leftContent);

// 创建带标题的右侧控件
FramedWidget* rightFrame = new FramedWidget("右侧功能区", this);
QWidget* rightContent = new QWidget();
// 向rightContent添加你的功能控件
rightFrame->setContentWidget(rightContent);

splitter->addWidget(leftFrame);
splitter->addWidget(rightFrame);

// 绑定到主窗口布局
auto mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(splitter);
setLayout(mainLayout);

2. 用QGroupBox快速改造(最简方案)

利用QGroupBox的标题特性,通过样式表将其改造成类似标题栏的效果,代码量极少。

使用示例

QSplitter* splitter = new QSplitter(Qt::Horizontal, this);

// 左侧带标题区域
QGroupBox* leftGroup = new QGroupBox("左侧功能区");
leftGroup->setStyleSheet(R"(
    QGroupBox {
        border: 1px solid #ccc;
        border-top: none;
        margin-top: 15px;
    }
    QGroupBox::title {
        background-color: #eee;
        padding: 2px 8px;
        margin-top: -15px;
        border: 1px solid #ccc;
        border-bottom: none;
        font-weight: bold;
    }
)");
auto leftLayout = new QVBoxLayout(leftGroup);
QWidget* leftContent = new QWidget();
leftLayout->addWidget(leftContent);

// 右侧带标题区域
QGroupBox* rightGroup = new QGroupBox("右侧功能区");
rightGroup->setStyleSheet(leftGroup->styleSheet());
auto rightLayout = new QVBoxLayout(rightGroup);
QWidget* rightContent = new QWidget();
rightLayout->addWidget(rightContent);

splitter->addWidget(leftGroup);
splitter->addWidget(rightGroup);

// 绑定到主窗口布局
auto mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(splitter);
setLayout(mainLayout);

3. 利用QDockWidget(自带交互功能)

QDockWidget自带标题栏,可通过设置禁用停靠、移动功能,将其作为嵌入式标题栏控件使用,适合需要标题栏交互(如关闭)的场景。

使用示例

QSplitter* splitter = new QSplitter(Qt::Horizontal, this);

// 左侧带标题的停靠控件(禁用移动、停靠功能)
QDockWidget* leftDock = new QDockWidget("左侧功能区", this);
leftDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
leftDock->setAllowedAreas(Qt::NoDockWidgetArea);
QWidget* leftContent = new QWidget();
leftDock->setWidget(leftContent);

// 右侧带标题的停靠控件
QDockWidget* rightDock = new QDockWidget("右侧功能区", this);
rightDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
rightDock->setAllowedAreas(Qt::NoDockWidgetArea);
QWidget* rightContent = new QWidget();
rightDock->setWidget(rightContent);

splitter->addWidget(leftDock);
splitter->addWidget(rightDock);

// 绑定到主窗口布局
auto mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(splitter);
setLayout(mainLayout);

方案选择建议

  • 自定义Widget:需要完全自定义标题栏样式、添加额外按钮时优先选择,灵活性最高
  • QGroupBox:快速实现简单标题栏,代码量最少,适合基础需求
  • QDockWidget:自带标题栏交互功能,适合需要关闭、停靠等操作的场景

内容的提问来源于stack exchange,提问作者willy_j

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:44:51