QDockWidget 的自定义标题栏
背景
不考虑复杂的dockwidget使用情况下,QDockWidget还是勉强一用的。在需要对UI进行定制的情形下,QDockWidget的标题栏就必然要进行自定义,而且QDockWidget也提供有相应的接口
void QDockWidget::setTitleBarWidget(QWidget *widget);
由于QDockWidget可以直接设置自定义标题栏,就不需要重写QDockWidget本身,也不需要重写鼠标事件用来拖拽标题栏控制DockWidget移动。特别强调,对标题栏的双击控制,仍采用QDockWidget原生效果,双击标题栏,dockWidget会嵌入或浮动到窗口中。
此处讨论的是自定义标题栏的右侧按钮集。
本文提供一种简单的QDockWidget自定义标题栏CqDockWgtTitleBar,提供有最小按钮、浮动按钮、最大按钮和关闭按钮。
此处,
- 最小按钮,用于将DockWidget嵌入到父窗口中;
- 浮动按钮,用于将DockWidget以正常尺寸浮动到当前屏幕上;
- 最大按钮,用于将DockWidget最大化显示在当前屏幕上;
- 关闭按钮,用于将DockWidget关闭,实际上是隐藏。可以通过其他控件将该DockWidget重新显示出来。
关于类CqDockWgtTitleBar的命名,DockWgtTitleBar,不言而喻,dockWidget的标题栏。
前缀Cq,有几重含义
- Custom Qt,自定义化的Qt
- C Qt,C 语言的Qt
- China/Chinese Qt,中国化的Qt。还是需要积累更多更适用的Qt代码,方便实际项目开发,追求中国自主开发和基础功能代码的共享。
具体代码文件有CqDockWgtTitleBar.h和CqDockWgtTitleBar.cpp
-
效果1 (DockWidget嵌入到应用窗口中,忽略主窗口同样显示为三维)
-
效果2 (DockWidget浮动在应用窗口中,忽略主窗口同样显示为三维)
-
效果3 (DockWidget移动到另一屏幕,最大化显示,忽略主窗口同样显示为三维,可以设想此类双屏显示二维地图和三维地球的应用场景。由于双屏分辨率不同,截屏图片中窗口标题栏高度显示存在问题,实际显示正常。)
CqDockWgtTitleBar.h
/**
* @file CqDockWgtTitleBar.h
* @brief QDockWidget 自定义标题栏
* @author 秦风
* @date 2022.11.18
*/
#ifndef CQDOCKWGTTITLEBAR_H
#define CQDOCKWGTTITLEBAR_H
#include <QWidget>
class QDockWidget;
class CqDockWgtTitleBarPrivate;
/**
* @class CqDockWgtTitleBar
* @brief QDockWidget 自定义标题栏
*/
class CqDockWgtTitleBar : public QWidget
{
Q_OBJECT
public:
/**
* @brief 构造函数
* @param parent [in] 需要嵌入的dock窗口
* @param strTitle [in] 窗口标题
*/
CqDockWgtTitleBar(QDockWidget *parent, const QString &strTitle = "");
//! 析构函数
~CqDockWgtTitleBar();
/**
* @brief 设置窗口标题。
* @params title 标题名称
*/
virtual void setWindowTitle(const QString &title);
private slots:
void clickMinBtnSlot();
void clickMaxBtnSlot();
void clickFloatBtnSlot();
void floatChangedSlot(bool bFloat);
private:
Q_DISABLE_COPY(CqDockWgtTitleBar)
Q_DECLARE_PRIVATE(CqDockWgtTitleBar)
QScopedPointer<CqDockWgtTitleBarPrivate> d_ptr;
};
#endif //! CQDOCKWGTTITLEBAR_H
CqDockWgtTitleBar.cpp
#include "CqDockWgtTitleBar.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QDockWidget>
#include <QApplication>
#include <QDesktopWidget>
#include <QStyle>
class CqDockWgtTitleBarPrivate
{
Q_DECLARE_PUBLIC(CqDockWgtTitleBar);
protected:
CqDockWgtTitleBar* const q_ptr; ///< q指针
public:
// 构造函数
CqDockWgtTitleBarPrivate(CqDockWgtTitleBar* parent);
virtual ~CqDockWgtTitleBarPrivate();
QDockWidget *m_pDockWidget; ///< DockWidget
QLabel *m_pIconLbl; ///< 图标
QLabel *m_pTitleLbl; ///< 标题
QPushButton *m_pMinBtn; ///< 最小按钮,用于将DockWidget嵌入到父窗口中
QPushButton *m_pFloatBtn; ///< 浮动按钮,用于将DockWidget以正常尺寸浮动到当前屏幕上
QPushButton *m_pMaxBtn; ///< 最大按钮,用于将DockWidget最大化显示在当前屏幕上
QPushButton *m_pCloseBtn; ///< 关闭按钮
};
CqDockWgtTitleBarPrivate::CqDockWgtTitleBarPrivate(CqDockWgtTitleBar* parent)
: q_ptr(parent)
{
m_pDockWidget = nullptr;
}
CqDockWgtTitleBarPrivate::~CqDockWgtTitleBarPrivate()
{
}
CqDockWgtTitleBar::CqDockWgtTitleBar(QDockWidget *parent, const QString &strTitle)
: QWidget(parent)
, d_ptr(new CqDockWgtTitleBarPrivate(this))
{
Q_D(CqDockWgtTitleBar);
d->m_pIconLbl = new QLabel(this);
d->m_pTitleLbl = new QLabel(this);
QIcon minIcon(style()->standardPixmap(QStyle::SP_TitleBarMinButton));
QIcon floatIcon(style()->standardPixmap(QStyle::SP_TitleBarNormalButton));
QIcon maxIcon(style()->standardPixmap(QStyle::SP_TitleBarMaxButton));
QIcon closeIcon(style()->standardPixmap(QStyle::SP_TitleBarCloseButton));
d->m_pMinBtn = new QPushButton(minIcon, "", this);
d->m_pFloatBtn = new QPushButton(floatIcon, "", this);
d->m_pMaxBtn = new QPushButton(maxIcon, "", this);
d->m_pCloseBtn = new QPushButton(closeIcon, "", this);
QHBoxLayout *pLayout = new QHBoxLayout(this);
pLayout->setMargin(0);
pLayout->setSpacing(0);
pLayout->addWidget(d->m_pIconLbl);
pLayout->addWidget(d->m_pTitleLbl);
pLayout->addStretch();
pLayout->addWidget(d->m_pMinBtn);
pLayout->addWidget(d->m_pFloatBtn);
pLayout->addWidget(d->m_pMaxBtn);
pLayout->addWidget(d->m_pCloseBtn);
d->m_pMinBtn->setFocusPolicy(Qt::NoFocus);
d->m_pFloatBtn->setFocusPolicy(Qt::NoFocus);
d->m_pMaxBtn->setFocusPolicy(Qt::NoFocus);
d->m_pCloseBtn->setFocusPolicy(Qt::NoFocus);
d->m_pTitleLbl->setText(strTitle);
d->m_pMinBtn->setVisible(false);
d->m_pMinBtn->setFocusPolicy(Qt::NoFocus);
d->m_pFloatBtn->setFocusPolicy(Qt::NoFocus);
d->m_pMaxBtn->setFocusPolicy(Qt::NoFocus);
d->m_pCloseBtn->setFocusPolicy(Qt::NoFocus);
d->m_pMinBtn->setToolTip(QStringLiteral("最小化"));
d->m_pFloatBtn->setToolTip(QStringLiteral("向下还原"));
d->m_pMaxBtn->setToolTip(QStringLiteral("最大化"));
d->m_pCloseBtn->setToolTip(QStringLiteral("关闭"));
d->m_pIconLbl->setObjectName("dock_header_icon");
d->m_pTitleLbl->setObjectName("dock_header_title");
d->m_pFloatBtn->setObjectName("dock_header_floatBtn");
d->m_pMaxBtn->setObjectName("dock_header_maxBtn");
d->m_pCloseBtn->setObjectName("dock_header_closeBtn");
if (parent)
{
d->m_pDockWidget = parent;
connect(d->m_pMinBtn, SIGNAL(clicked()), this, SLOT(clickMinBtnSlot()));
connect(d->m_pMaxBtn, SIGNAL(clicked()), this, SLOT(clickMaxBtnSlot()));
connect(d->m_pFloatBtn, SIGNAL(clicked()), this, SLOT(clickFloatBtnSlot()));
connect(d->m_pCloseBtn, SIGNAL(clicked()), d->m_pDockWidget, SLOT(close()));
connect(d->m_pDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(floatChangedSlot(bool)));
}
}
CqDockWgtTitleBar::~CqDockWgtTitleBar()
{
}
void CqDockWgtTitleBar::setWindowTitle(const QString &title)
{
Q_D(CqDockWgtTitleBar);
d->m_pTitleLbl->setText(title);
}
void CqDockWgtTitleBar::clickMinBtnSlot()
{
Q_D(CqDockWgtTitleBar);
d->m_pMinBtn->setVisible(false);
d->m_pMaxBtn->setVisible(true);
d->m_pFloatBtn->setVisible(true);
// 嵌入窗口
if (d->m_pDockWidget->isFloating())
{
d->m_pDockWidget->setFloating(false);
}
}
void CqDockWgtTitleBar::clickMaxBtnSlot()
{
Q_D(CqDockWgtTitleBar);
d->m_pMinBtn->setVisible(true);
d->m_pMaxBtn->setVisible(false);
d->m_pFloatBtn->setVisible(true);
// 设置浮动
if (!d->m_pDockWidget->isFloating())
{
disconnect(d->m_pDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(floatChangedSlot(bool)));
d->m_pDockWidget->setFloating(true);
connect(d->m_pDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(floatChangedSlot(bool)));
}
d->m_pDockWidget->showMaximized();
}
void CqDockWgtTitleBar::clickFloatBtnSlot()
{
Q_D(CqDockWgtTitleBar);
d->m_pMinBtn->setVisible(true);
d->m_pMaxBtn->setVisible(true);
d->m_pFloatBtn->setVisible(false);
// 设置浮动
if (!d->m_pDockWidget->isFloating())
{
d->m_pDockWidget->setFloating(true);
QRect availGeo = QApplication::desktop()->availableGeometry(QApplication::desktop()->screenNumber(QCursor::pos()));
d->m_pDockWidget->move((availGeo.width() - d->m_pDockWidget->width()) / 2,
(availGeo.height() - d->m_pDockWidget->height()) / 2);
}
else
{
d->m_pDockWidget->showNormal();
}
}
void CqDockWgtTitleBar::floatChangedSlot(bool bFloat)
{
Q_D(CqDockWgtTitleBar);
d->m_pMinBtn->setVisible(bFloat);
d->m_pMaxBtn->setVisible(!d->m_pDockWidget->isMaximized());
d->m_pFloatBtn->setVisible(!bFloat || d->m_pDockWidget->isMaximized());
}
参考
本代码有参考
链接: Qt 之QDockwidget 自定义窗口标题栏
考虑了多屏幕的情形下,参考了其直接使用QStyle中图标,
style()->standardPixmap()
这是此前没有见过的用法。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgbjfaa
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13