QT 自定义标题栏

QT默认的窗口标题栏不支持自定义,所以参考网上的一些教程,做了一个比较通用的模板类,实现了自定义标题栏,支持边框阴影、圆角、拖动等一些常用功能,继承的类可直接使用ui文件。

参考文章

Qt 之 自定义窗口标题栏_qt 自定义标题栏-CSDN博客

效果

没有标题栏时:

有标题栏时:

实现原理

与参考文章中的基本一致,额外使用了setContentsMargins接口,为标题栏预留位置,所以ui文件不需要再单独为标题栏在顶部留一段空白。

代码

basetitlebar.h 自定义标题栏基类

#ifndef __BASETITLEBAR_H__
#define __BASETITLEBAR_H__

#include <QWidget>

class QPaintEvent;
class QMouseEvent;
class QColor;
class QIcon;
class QString;
class CBaseTitleBarPrivate;
class CBaseTitleBar : public QWidget
{
public:
	//parent为父窗口,窗口的一些事件直接关联到父窗口
	CBaseTitleBar(QWidget *parent = nullptr);
	~CBaseTitleBar();

	// 更新窗体大小的状态
	virtual void updateSizeState() = 0;
	// 设置图标
	virtual void setIcon(const QIcon& icon) = 0;
	// 设置标题文字
	virtual void setTitle(const QString& text) = 0;

	// 设置主窗口
	void setParentWindow(QWidget *parent);
	// 设置标题栏背景色;
	void setBackgroundColor(const QColor& color);
	// 设置边框圆角半径;
	void setBorderRadius(qreal radius);
	// 父窗口是否最大化
	bool isMaximized();
	// 操作父窗口最小化
	void setMinimized();
	// 操作父窗口最大化
	void setMaximized();
	// 操作父窗口还原
	void setRestored();
	// 操作父窗口关闭
	void setClosed();
	// 设置标题栏高度;
	void setTitleFixedHeight(int nHeight);
	// 获取标题栏高度;
	int getTitleFixedHeight();

protected:
	virtual void paintEvent(QPaintEvent *event);
	virtual void mouseDoubleClickEvent(QMouseEvent *event);
	virtual void mousePressEvent(QMouseEvent *event);
	virtual void mouseMoveEvent(QMouseEvent *event);
	virtual void mouseReleaseEvent(QMouseEvent *event);

private:
	CBaseTitleBarPrivate* d_ptr;
};

class CDefaultTitleBarPrivate;
class CDefaultTitleBar : public CBaseTitleBar
{
	Q_OBJECT

public:
	CDefaultTitleBar(QWidget *parent = nullptr);
	~CDefaultTitleBar();
	void updateSizeState();
	void setIcon(const QIcon& icon);
	void setTitle(const QString& text);

private slots:
	void onButtonMinClicked();
	void onButtonRestoreClicked();
	void onButtonMaxClicked();
	void onButtonCloseClicked();

private:
	CDefaultTitleBarPrivate* d_ptr;
};

#endif // __BASETITLEBAR_H__

basetitlebar.cpp 自定义标题栏实现

#include <QColor>
#include <QPainter>
#include <QPainterPath>
#include <QRect>
#include <QBrush>
#include <QPoint>
#include <QLabel>
#include <QIcon>
#include <QPixmap>
#include <QPushButton>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QFile>
#include "basetitlebar.h"

class CBaseTitleBarPrivate
{
public:
	CBaseTitleBarPrivate(QWidget *wnd)
		: bgColor(153, 153, 153), corRadius(8), parentWnd(wnd), bPressed(false), nTitleHeight(30)
	{
	}

	QWidget* parentWnd;
	QColor bgColor;
	qreal corRadius;
	bool bPressed;
	QPoint qpDragDltPos;
	int nTitleHeight;
};

CBaseTitleBar::CBaseTitleBar(QWidget *parent)
	:d_ptr(new CBaseTitleBarPrivate(parent))
{
	setFixedHeight(getTitleFixedHeight());
}
CBaseTitleBar::~CBaseTitleBar()
{
	delete d_ptr;
}
void CBaseTitleBar::setParentWindow(QWidget *parent)
{
	setParent(parent);
	d_ptr->parentWnd = parent;
}
void CBaseTitleBar::setBackgroundColor(const QColor& color)
{
	d_ptr->bgColor = color;
}
void CBaseTitleBar::setBorderRadius(qreal radius)
{
	d_ptr->corRadius = radius;
}
void CBaseTitleBar::setTitleFixedHeight(int nHeight)
{
	d_ptr->nTitleHeight = nHeight;
	setFixedHeight(nHeight);
}
int CBaseTitleBar::getTitleFixedHeight()
{
	return d_ptr->nTitleHeight;
}
bool CBaseTitleBar::isMaximized()
{
	if (!d_ptr->parentWnd)
	{
		return false;
	}

	return d_ptr->parentWnd->isMaximized();
}
void CBaseTitleBar::setMinimized()
{
	if (d_ptr->parentWnd)
	{
		d_ptr->parentWnd->showMinimized();
	}
}
void CBaseTitleBar::setMaximized()
{
	if (d_ptr->parentWnd)
	{
		d_ptr->parentWnd->showMaximized();
	}
}
void CBaseTitleBar::setRestored()
{
	if (d_ptr->parentWnd)
	{
		d_ptr->parentWnd->showNormal();
	}
}
void CBaseTitleBar::setClosed()
{
	if (d_ptr->parentWnd)
	{
		d_ptr->parentWnd->close();
	}
}
void CBaseTitleBar::paintEvent(QPaintEvent *event)
{
	int nWidth = this->width();
	int nHeight = this->height();

	QPainter painter(this);
	QPainterPath pathBack;
	pathBack.setFillRule(Qt::WindingFill);
	pathBack.addRoundedRect(QRect(0, 0, nWidth, nHeight), d_ptr->corRadius, d_ptr->corRadius);
	pathBack.addRect(QRect(0, nHeight-d_ptr->corRadius, nWidth, d_ptr->corRadius));
	painter.setRenderHint(QPainter::Antialiasing, true);
	painter.setPen(Qt::NoPen);
	painter.fillPath(pathBack, QBrush(d_ptr->bgColor));

	QWidget::paintEvent(event);
}
void CBaseTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
	isMaximized() ? setRestored() : setMaximized();
}
void CBaseTitleBar::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton && !isMaximized())
	{
		d_ptr->bPressed = true;
		if (d_ptr->parentWnd)
		{
			d_ptr->qpDragDltPos = event->globalPos() - d_ptr->parentWnd->pos();
		}
		else
		{
			d_ptr->qpDragDltPos = event->globalPos() - this->pos();
		}
	}
	return QWidget::mousePressEvent(event);
}
void CBaseTitleBar::mouseMoveEvent(QMouseEvent *event)
{
	if (d_ptr->bPressed)
	{
		if (d_ptr->parentWnd)
		{
			d_ptr->parentWnd->move(event->globalPos() - d_ptr->qpDragDltPos);
		}
		else
		{
			this->move(event->globalPos() - d_ptr->qpDragDltPos);
		}
	}
	return QWidget::mouseMoveEvent(event);
}
void CBaseTitleBar::mouseReleaseEvent(QMouseEvent *event)
{
	d_ptr->bPressed = false;
	return QWidget::mouseReleaseEvent(event);
}


class CDefaultTitleBarPrivate
{
public:
	QLabel* pIcon;					// 标题栏图标;
	QLabel* pTitleContent;			// 标题栏内容;
	QPushButton* pButtonMin;		// 最小化按钮;
	QPushButton* pButtonRestore;	// 最大化还原按钮;
	QPushButton* pButtonMax;		// 最大化按钮;
	QPushButton* pButtonClose;		// 关闭按钮;
};

CDefaultTitleBar::CDefaultTitleBar(QWidget *parent)
	: CBaseTitleBar(parent), d_ptr(new CDefaultTitleBarPrivate)
{
	d_ptr->pIcon = new QLabel;
	d_ptr->pTitleContent = new QLabel;

	d_ptr->pButtonMin = new QPushButton;
	d_ptr->pButtonRestore = new QPushButton;
	d_ptr->pButtonMax = new QPushButton;
	d_ptr->pButtonClose = new QPushButton;

	d_ptr->pButtonMin->setMouseTracking(true);
	d_ptr->pButtonRestore->setMouseTracking(true);
	d_ptr->pButtonMax->setMouseTracking(true);
	d_ptr->pButtonClose->setMouseTracking(true);

	setTitleFixedHeight(26);
	d_ptr->pIcon->setFixedSize(QSize(30, 26));
	d_ptr->pButtonMin->setFixedSize(QSize(30, 26));
	d_ptr->pButtonRestore->setFixedSize(QSize(30, 26));
	d_ptr->pButtonMax->setFixedSize(QSize(30, 26));
	d_ptr->pButtonClose->setFixedSize(QSize(30, 26));

	d_ptr->pTitleContent->setObjectName("TitleContent");
	d_ptr->pButtonMin->setObjectName("ButtonMin");
	d_ptr->pButtonRestore->setObjectName("ButtonRestore");
	d_ptr->pButtonMax->setObjectName("ButtonMax");
	d_ptr->pButtonClose->setObjectName("ButtonClose");

	QHBoxLayout* mylayout = new QHBoxLayout(this);
	mylayout->setContentsMargins(5, 0, 0, 0);
	mylayout->setSpacing(0);
	mylayout->addWidget(d_ptr->pIcon);
	mylayout->addWidget(d_ptr->pTitleContent);
	mylayout->addStretch();
	mylayout->addWidget(d_ptr->pButtonMin);
	mylayout->addWidget(d_ptr->pButtonRestore);
	mylayout->addWidget(d_ptr->pButtonMax);
	mylayout->addWidget(d_ptr->pButtonClose);

	connect(d_ptr->pButtonMin, SIGNAL(clicked()), this, SLOT(onButtonMinClicked()));
	connect(d_ptr->pButtonRestore, SIGNAL(clicked()), this, SLOT(onButtonRestoreClicked()));
	connect(d_ptr->pButtonMax, SIGNAL(clicked()), this, SLOT(onButtonMaxClicked()));
	connect(d_ptr->pButtonClose, SIGNAL(clicked()), this, SLOT(onButtonCloseClicked()));

	QFile file(":/qss/title.css");
	file.open(QFile::ReadOnly);
	if (file.isOpen())
	{
		QString styleSheet = this->styleSheet();
		styleSheet += QLatin1String(file.readAll());
		this->setStyleSheet(styleSheet);
	}
}
CDefaultTitleBar::~CDefaultTitleBar()
{
	delete d_ptr;
}
void CDefaultTitleBar::updateSizeState()
{
	if (isMaximized())
	{
		d_ptr->pButtonMax->setVisible(false);
		d_ptr->pButtonRestore->setVisible(true);
	}
	else
	{
		d_ptr->pButtonMax->setVisible(true);
		d_ptr->pButtonRestore->setVisible(false);
	}
}
void CDefaultTitleBar::setIcon(const QIcon& icon)
{
	QSize sz = d_ptr->pIcon->size();
	d_ptr->pIcon->setPixmap(icon.pixmap(sz));
}
void CDefaultTitleBar::setTitle(const QString& text)
{
	d_ptr->pTitleContent->setText(text);
}
void CDefaultTitleBar::onButtonMinClicked()
{
	setMinimized();
}
void CDefaultTitleBar::onButtonRestoreClicked()
{
	setRestored();
}
void CDefaultTitleBar::onButtonMaxClicked()
{
	setMaximized();
}
void CDefaultTitleBar::onButtonCloseClicked()
{
	setClosed();
}

basewindow.h 自定义窗口模板类

#ifndef __BASEWINDOW_H__
#define __BASEWINDOW_H__

#include <QWidget>
#include <QPainter>
#include <QPoint>
#include <QColor>
#include <QIcon>
#include <QString>
#include <QEvent>
#include <QResizeEvent>
#include <QPaintEvent>
#include <QMouseEvent>
#include "basetitlebar.h"

enum Direction
{
	UP = 0,
	DOWN = 1,
	LEFT,
	RIGHT,
	LEFTTOP,
	LEFTBOTTOM,
	RIGHTBOTTOM,
	RIGHTTOP,
	NONE
};

template <class WidgetClass>
class CBaseWindow : public WidgetClass
{
public:
	// 不带标题栏
	CBaseWindow(QWidget *parent = nullptr);
	// 使用传入的标题栏
	CBaseWindow(CBaseTitleBar* pTitleBar, QWidget *parent = nullptr);
	virtual ~CBaseWindow();

	// 设置标题栏
	void setTitleBar(CBaseTitleBar* pTitleBar);
	// 设置标题栏图标
	void setIcon(const QIcon& icon);
	// 设置标题栏文字
	void setTitle(const QString& text);
	// 设置背景颜色
	void setBackgroundColor(const QColor& color);
	// 设置设置窗体周围阴影尺寸
	void setFrameShadowSize(int nSize);
	// 设置边框尺寸
	void setFrameBorderSize(int nSize);
	// 设置边框圆角半径
	void setFrameBorderRadius(int nRadius);
	// 设置点击任意位置拖动,默认是不设置标题栏时起作用
	void setDragMove(bool bEnable);

protected:
	void resizeEvent(QResizeEvent *event);
	void paintEvent(QPaintEvent *event);
	void mouseReleaseEvent(QMouseEvent *event);
	void mouseMoveEvent(QMouseEvent *event);
	void mousePressEvent(QMouseEvent *event);
	void changeEvent(QEvent *event);

private:
	void initWnd();
	void updateMargins();
	bool region(const QPoint &cursorGlobalPoint);

protected:
	//窗口显示效果
	CBaseTitleBar* m_pTitleBar;
	QColor m_bgColor;
	int m_nFrameShadow;
	int m_nFrameShadowSaved;
	int m_nFrameBorder;
	int m_nBorderRadius;
	//窗口拖拉
	bool m_bDragMove;
	bool m_bPressDown;
	QPoint m_qpDragPos;
	Direction m_dDir;
};

template <class WidgetClass>
CBaseWindow<WidgetClass>::CBaseWindow(QWidget *parent)
	: QWidget(parent), m_nFrameShadow(10), m_nFrameShadowSaved(10), m_nFrameBorder(4), m_nBorderRadius(8),
	m_bgColor(215, 221, 228), m_pTitleBar(nullptr),
	m_bPressDown(false), m_dDir(NONE), m_bDragMove(false)
{
	initWnd();
	setDragMove(true);
}

template <class WidgetClass>
CBaseWindow<WidgetClass>::CBaseWindow(CBaseTitleBar* pTitleBar, QWidget *parent)
	: QWidget(parent), m_nFrameShadow(10), m_nFrameShadowSaved(10), m_nFrameBorder(4), m_nBorderRadius(8),
	m_bgColor(215, 221, 228), m_pTitleBar(nullptr),
	m_bPressDown(false), m_dDir(NONE), m_bDragMove(false)
{
	initWnd();
	setTitleBar(pTitleBar);
}

template <class WidgetClass>
CBaseWindow<WidgetClass>::~CBaseWindow()
{
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setTitleBar(CBaseTitleBar* pTitleBar)
{
	if (pTitleBar)
	{
		delete m_pTitleBar;
		m_pTitleBar = nullptr;
	}
	if (pTitleBar)
	{
		m_pTitleBar = pTitleBar;
		m_pTitleBar->setParentWindow(this);
		// 边框圆角半径
		m_pTitleBar->setBorderRadius(m_nBorderRadius);
		// 标题栏相当于窗口的上边框
		m_pTitleBar->move(m_nFrameShadow, m_nFrameShadow);
		// 设置边框margins,用于画透明部分背景
		updateMargins();

		m_pTitleBar->setMouseTracking(true);
		m_pTitleBar->setIcon(windowIcon());
		m_pTitleBar->setTitle(windowTitle());
		m_pTitleBar->updateSizeState();
	}
	setDragMove(pTitleBar == nullptr);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setIcon(const QIcon& icon)
{
	if (m_pTitleBar)
	{
		m_pTitleBar->setIcon(icon);
	}
	setWindowIcon(icon);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setTitle(const QString& text)
{
	if (m_pTitleBar)
	{
		m_pTitleBar->setTitle(text);
	}
	setWindowTitle(text);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setBackgroundColor(const QColor& color)
{
	m_bgColor = color;
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setFrameShadowSize(int nSize)
{
	m_nFrameShadow = nSize;
	m_nFrameShadowSaved = nSize;
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setFrameBorderSize(int nSize)
{
	m_nFrameBorder = nSize;
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setFrameBorderRadius(int nRadius)
{
	m_nBorderRadius = nRadius;
	if (m_pTitleBar)
	{
		m_pTitleBar->setBorderRadius(nRadius);
	}
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::setDragMove(bool bEnable)
{
	m_bDragMove = bEnable;
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::resizeEvent(QResizeEvent *event)
{
	QWidget::resizeEvent(event);

	if (isMaximized())
	{
		m_nFrameShadow = 0;
	}
	else
	{
		m_nFrameShadow = m_nFrameShadowSaved;
	}

	updateMargins();

	if (m_pTitleBar)
	{
		int width = event->size().width();
		m_pTitleBar->move(m_nFrameShadow, m_nFrameShadow);
		m_pTitleBar->resize(width - m_nFrameShadow * 2, m_pTitleBar->getTitleFixedHeight());
		m_pTitleBar->updateSizeState();
	}
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::paintEvent(QPaintEvent* event)
{
	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing, true);
	painter.setPen(Qt::NoPen);

	int nWidth = this->width();
	int nHeight = this->height();

	if (!isMaximized())
	{
		//透明背景
		QRect shadowRect(0, 0, nWidth, nHeight);
		QPainterPath pathShadow;
		pathShadow.setFillRule(Qt::WindingFill);
		pathShadow.addRect(shadowRect);
		painter.fillPath(pathShadow, QBrush(QColor(0, 0, 0, 2)));
	}

	//边框
	QRect frameRect(m_nFrameShadow, m_nFrameShadow, nWidth - m_nFrameShadow * 2, nHeight - m_nFrameShadow * 2);
	QPainterPath pathBack;
	pathBack.setFillRule(Qt::WindingFill);
	pathBack.addRoundedRect(frameRect, m_nBorderRadius, m_nBorderRadius);
	painter.fillPath(pathBack, QBrush(m_bgColor));

	return QWidget::paintEvent(event);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::mouseReleaseEvent(QMouseEvent *event)
{
	if ((event->button() == Qt::LeftButton) && m_bPressDown)
	{
		region(event->globalPos());
		m_bPressDown = false;
	}
	QWidget::mouseReleaseEvent(event);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::mouseMoveEvent(QMouseEvent *event)
{
	QPoint gloPoint = event->globalPos();
	if (!m_bPressDown)
	{
		region(gloPoint);
	}
	else
	{
		QRect rect = this->rect();
		QPoint tl = mapToGlobal(rect.topLeft());
		QPoint rb = mapToGlobal(rect.bottomRight());

		if (m_dDir != NONE)
		{
			QRect rMove(tl, rb);
			switch (m_dDir)
			{
			case LEFT:
				if (rb.x() - gloPoint.x() <= minimumWidth())
					rMove.setX(tl.x());
				else
					rMove.setX(gloPoint.x());
				break;
			case RIGHT:
				rMove.setWidth(gloPoint.x() - tl.x());
				break;
			case UP:
				if (rb.y() - gloPoint.y() <= minimumHeight())
					rMove.setY(tl.y());
				else
					rMove.setY(gloPoint.y());
				break;
			case DOWN:
				rMove.setHeight(gloPoint.y() - tl.y());
				break;
			case LEFTTOP:
				if (rb.x() - gloPoint.x() <= minimumWidth())
					rMove.setX(tl.x());
				else
					rMove.setX(gloPoint.x());
				if (rb.y() - gloPoint.y() <= minimumHeight())
					rMove.setY(tl.y());
				else
					rMove.setY(gloPoint.y());
				break;
			case RIGHTTOP:
				rMove.setWidth(gloPoint.x() - tl.x());
				rMove.setY(gloPoint.y());
				break;
			case LEFTBOTTOM:
				rMove.setX(gloPoint.x());
				rMove.setHeight(gloPoint.y() - tl.y());
				break;
			case RIGHTBOTTOM:
				rMove.setWidth(gloPoint.x() - tl.x());
				rMove.setHeight(gloPoint.y() - tl.y());
				break;
			default:
				break;
			}
			setGeometry(rMove);
		}
		else if (m_bDragMove)
		{
			this->move(event->globalPos() - m_qpDragPos);
		}
	}
	QWidget::mouseMoveEvent(event);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton && !isMaximized())
	{
		region(event->globalPos());
		m_bPressDown = true;
		m_qpDragPos = event->globalPos() - this->pos();
	}
	QWidget::mousePressEvent(event);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::changeEvent(QEvent *event)
{
	if ((event->type() == QEvent::ActivationChange) && (!this->isActiveWindow()))
	{
		m_bPressDown = false;
	}
	QWidget::changeEvent(event);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::initWnd()
{
	// FramelessWindowHint属性设置窗口去除边框;
	// WindowMinimizeButtonHint 属性设置在窗口最小化时,点击任务栏窗口可以显示出原窗口;
	setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
	// 设置窗口背景透明;
	setAttribute(Qt::WA_TranslucentBackground);
	// 处理鼠标移动事件
	setMouseTracking(true);
}

template <class WidgetClass>
void CBaseWindow<WidgetClass>::updateMargins()
{
	int left = m_nFrameBorder + m_nFrameShadow;
	int top = m_nFrameShadow;
	if (m_pTitleBar)
	{
		top += m_pTitleBar->getTitleFixedHeight();
	}
	else
	{
		top += m_nFrameBorder;
	}
	int right = m_nFrameBorder + m_nFrameShadow;
	int bottom = m_nFrameBorder + m_nFrameShadow;
	setContentsMargins(left, top, right, bottom);
}

template <class WidgetClass>
bool CBaseWindow<WidgetClass>::region(const QPoint &cursorGlobalPoint)
{
	QRect rect = this->rect();
	QPoint tl = mapToGlobal(rect.topLeft());
	QPoint rb = mapToGlobal(rect.bottomRight());

	int x = cursorGlobalPoint.x();
	int y = cursorGlobalPoint.y();
	int pad = m_nFrameShadow;
	bool ret;

	if (tl.x() + pad >= x && tl.x() <= x && tl.y() + pad >= y && tl.y() <= y)
	{
		// 左上角
		m_dDir = LEFTTOP;
		setCursor(QCursor(Qt::SizeFDiagCursor));  // 设置鼠标形状
		ret = true;
	}
	else if (x >= rb.x() - pad && x <= rb.x() && y >= rb.y() - pad && y <= rb.y())
	{
		// 右下角
		m_dDir = RIGHTBOTTOM;
		setCursor(QCursor(Qt::SizeFDiagCursor));
		ret = true;
	}
	else if (x <= tl.x() + pad && x >= tl.x() && y >= rb.y() - pad && y <= rb.y())
	{
		//左下角
		m_dDir = LEFTBOTTOM;
		setCursor(QCursor(Qt::SizeBDiagCursor));
		ret = true;
	}
	else if (x <= rb.x() && x >= rb.x() - pad && y >= tl.y() && y <= tl.y() + pad)
	{
		// 右上角
		m_dDir = RIGHTTOP;
		setCursor(QCursor(Qt::SizeBDiagCursor));
		ret = true;
	}
	else if (x <= tl.x() + pad && x >= tl.x())
	{
		// 左边
		m_dDir = LEFT;
		setCursor(QCursor(Qt::SizeHorCursor));
		ret = true;
	}
	else if (x <= rb.x() && x >= rb.x() - pad)
	{
		// 右边
		m_dDir = RIGHT;
		setCursor(QCursor(Qt::SizeHorCursor));
		ret = true;
	}
	else if (y >= tl.y() && y <= tl.y() + pad)
	{
		// 上边
		m_dDir = UP;
		setCursor(QCursor(Qt::SizeVerCursor));
		ret = true;
	}
	else if (y <= rb.y() && y >= rb.y() - pad)
	{
		// 下边
		m_dDir = DOWN;
		setCursor(QCursor(Qt::SizeVerCursor));
		ret = true;
	}
	else
	{
		// 默认
		m_dDir = NONE;
		setCursor(QCursor(Qt::ArrowCursor));
		ret = false;
	}

	return ret;
}

#endif

custommainwindow.h 使用的类

#ifndef __CUSTOMMAINWINDOW_H__
#define __CUSTOMMAINWINDOW_H__

#include "basewindow.h"

namespace Ui {
class CustomMainWindow;
}

class CustomMainWindow : public CBaseWindow<QWidget>
{
    Q_OBJECT

public:
    explicit CustomMainWindow(QWidget *parent = 0);
    ~CustomMainWindow();

    Ui::CustomMainWindow *ui;
};

#endif // __CUSTOMMAINWINDOW_H__

custommainwindow.cpp 使用的类

#include "custommainwindow.h"
#include "ui_custommainwindow.h"
#include "basetitlebar.h"

CustomMainWindow::CustomMainWindow(QWidget *parent)
	: CBaseWindow<QWidget>(parent), ui(new Ui::CustomMainWindow)
{
    ui->setupUi(this);
    //注释该行代码则不使用标题栏
	setTitleBar(new CDefaultTitleBar());
	setIcon(QIcon(":/images/icon.png"));
	setTitle(QString("测试窗口"));
}
CustomMainWindow::~CustomMainWindow()
{
    delete ui;
}

完整代码下载链接:

QT自定义标题栏窗口带阴影圆角资源-CSDN文库

Qt 中,可以通过自定义 QWidget 的 paintEvent() 函数来实现自定义标题栏。具体步骤如下: 1.创建一个新的 QWidget,用于作为自定义标题栏。 2.将 QWidget 的窗口标志设置为 Qt::WindowFlags(Qt::FramelessWindowHint),这样可以去掉默认的标题栏。 3.重写 QWidget 的 paintEvent() 函数,在该函数中绘制自定义标题栏。 4.将 QWidget 设置为 QMainWindow 的标题栏,即调用 QMainWindow 的 setWindowTitle() 函数,并将其参数设置为自定义标题栏的指针。 下面是一个简单的示例代码: ``` #include <QtWidgets> // 继承 QWidget,作为自定义标题栏 class CustomTitleBar : public QWidget { public: CustomTitleBar(QWidget *parent = nullptr) : QWidget(parent) { // 设置窗口标志 setWindowFlags(Qt::FramelessWindowHint); } protected: void paintEvent(QPaintEvent *) override { QPainter painter(this); painter.fillRect(rect(), Qt::blue); painter.drawText(rect(), Qt::AlignCenter, "Custom Title Bar"); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow mainWindow; // 设置主窗口标题 mainWindow.setWindowTitle("Main Window"); // 创建自定义标题栏 CustomTitleBar *titleBar = new CustomTitleBar(&mainWindow); // 设置自定义标题栏为主窗口的标题栏 mainWindow.setMenuWidget(titleBar); mainWindow.show(); return app.exec(); } ``` 运行该程序,可以看到自定义的蓝色标题栏。你可以根据自己的需要修改 paintEvent() 函数,来实现各种不同样式的标题栏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值