如何在父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
相关产品推荐
相关产品推荐

