qt 自动隐藏窗体

该博客介绍了如何使用Qt创建一个可自动隐藏和显示的浮动窗口。通过实现鼠标事件处理和窗口移动功能,当窗口边缘触碰到屏幕边界时,窗口将自动隐藏;当鼠标进入窗口区域时,窗口重新显示。代码示例中包括了窗口隐藏、显示、边界检测以及鼠标事件的相关函数实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#ifndef DESKDOCKWIDGET_H
#define DESKDOCKWIDGET_H

#include "qtinclude.h"

class FloatingWidget : public QWidget
{
	Q_OBJECT

public:
	enum FloatingFeature
	{
		NoArea = 0x0,
		TopArea = 0x1,
		BottomArea = 0x2,
		LeftArea = 0x4,
		RightArea = 0x8,
		AllArea = 0xf,
	};

public:
	explicit FloatingWidget(FloatingFeature D, QWidget * parent = nullptr, Qt::WindowFlags flags = 0);

protected:
	virtual void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
	virtual void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
	virtual void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE;
	virtual void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
	virtual void enterEvent(QEvent *) Q_DECL_OVERRIDE;
	virtual void leaveEvent (QEvent *) Q_DECL_OVERRIDE;

	QSize sizeHint() const{ return QSize(128, 142);}

private slots:
	void setDirection(FloatingFeature D);
	void HideDockWidget();
	void ShowDockWidget();

private:
	void MoveWindow(const QPoint & start, const QPoint & end, unsigned int step = 5);

private:
	bool m_IsVisible = true;
	FloatingFeature m_feature;
	QPoint m_dragPosition;
	QPoint m_RecoverPosition;
	QTimer * m_timer = nullptr;
};

#endif // DESKDOCKWIDGET_H

#include "deskdockwidget.h"

#include <QtCore/QtMath>
#include <QtCore/QPropertyAnimation>

#include <QtWidgets/QDesktopWidget>

#define TEST_BIT(a, b) a & b
#define HIDE_BORDER 1 //隐藏时显示border
#define CHECK_BORDER 2 //边界检测宽度

FloatingWidget::FloatingWidget(FloatingFeature D, QWidget * parent, Qt::WindowFlags flags)
	: QWidget(parent, flags)
	, m_feature(D)
{
	setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint);

	setAttribute(Qt::WA_TranslucentBackground, true);

	setMouseTracking(true);
}

void FloatingWidget::MoveWindow(const QPoint & start, const QPoint & end, unsigned int step)
{	
	QPoint distance = end - start;
	QPoint stepPos, stepOne;
	if (end.x() == start.x())
	{
		stepOne.setY(step * (distance.y() > 0 ? 1 : -1));
	}
	else
	{
		stepOne.setX(step * (distance.x() > 0 ? 1 : -1));
	}
	stepPos = stepOne;

	int disLenght = distance.manhattanLength();
	while (stepPos.manhattanLength() <= disLenght)
	{
		move(start + stepPos);
		stepPos += stepOne;
	}

	move(end);

	m_RecoverPosition = start;
}

void FloatingWidget::setDirection(FloatingFeature D)
{
	m_feature = D;
}

void FloatingWidget::paintEvent(QPaintEvent *e)
{
	QPainter p(this);

	QPixmap img(":/images/m.png");

	p.setBrush(QBrush(img));

	p.setPen(QColor("#b5b4c9"));

	p.drawRoundedRect(0,0,width() - 1,height() - 1, 8, 8);
}

void FloatingWidget::HideDockWidget()
{
	if (m_IsVisible == false)
	{
		return;
	}

	m_IsVisible = false;

	int curHeight = height();
	int curWidth = width();

	QDesktopWidget * desktop = qApp->desktop();
	QRect rect = desktop->screenGeometry(this);

	if (frameGeometry().left() - CHECK_BORDER <= rect.top() 
		&& TEST_BIT(m_feature, LeftArea))
	{
		MoveWindow(pos(), pos() - QPoint(curWidth - HIDE_BORDER, 0));
	}
	else if (frameGeometry().right() + CHECK_BORDER >= rect.right()
		&& TEST_BIT(m_feature, RightArea))
	{
		MoveWindow(pos(), pos() + QPoint(curWidth - HIDE_BORDER, 0));
	}
	else if (frameGeometry().top() - CHECK_BORDER <= rect.top()
		&& TEST_BIT(m_feature, TopArea))
	{
		MoveWindow(pos(), pos() - QPoint(0, curHeight - HIDE_BORDER));
	}
	else
	{
		m_IsVisible = true;
	}

	if (m_IsVisible == false)
	{
		if (m_timer && m_timer->isActive())
		{
			m_timer->stop();
		}
	}
}

void FloatingWidget::ShowDockWidget()
{
	if (m_IsVisible)
	{
		return;
	}

	m_IsVisible = true;

	int curHeight = height();
	int curWidth = width();

	QDesktopWidget * desktop = qApp->desktop();
	QRect rect = desktop->screenGeometry(this);
	QRect frameRect = frameGeometry();

	if (frameRect.left() == m_RecoverPosition.x() - (curWidth - HIDE_BORDER)
		&& TEST_BIT(m_feature, LeftArea))
	{
		MoveWindow(pos(), m_RecoverPosition);
	}
	else if (frameRect.left() == m_RecoverPosition.x() + (curWidth - HIDE_BORDER)
		&& TEST_BIT(m_feature, RightArea))
	{
		MoveWindow(pos(), m_RecoverPosition);
	}
	else if (frameRect.top() == m_RecoverPosition.y() - (curHeight - HIDE_BORDER)
		&& TEST_BIT(m_feature, TopArea))
	{
		MoveWindow(pos(), m_RecoverPosition);
	}
	else
	{
		m_IsVisible = false;
	}
}

void FloatingWidget::mousePressEvent(QMouseEvent *e)
{
	if (e->button() == Qt::LeftButton)
	{
		m_dragPosition = e->globalPos() - frameGeometry().topLeft();
		e->accept();
	}
}

void FloatingWidget::mouseMoveEvent(QMouseEvent * event)
{
	if (event->buttons() & Qt::LeftButton)
	{
		QPoint pos = event->globalPos() - m_dragPosition;

		QDesktopWidget * desktop = qApp->desktop();
		QRect rect = desktop->screenGeometry(QCursor::pos());
		QRect frameRect = frameGeometry();
		if (rect.top() >= pos.y())//修正顶端位置
		{
			pos.setY(rect.top());
		}

		if (rect.left()>= pos.x())//修正左侧位置
		{
			int leftScreenNumber = desktop->screenNumber(pos - QPoint(width(), 0));
			if (desktop->screenGeometry(leftScreenNumber).contains((pos - QPoint(width(), 0))) == false)
			{
				pos.setX(rect.left());
			}
		}

		if (rect.right() <= pos.x() + frameRect.width())//修正右侧位置
		{
			int rightScreenNumber = desktop->screenNumber(pos + QPoint(width(), 0));
			if (desktop->screenGeometry(rightScreenNumber).contains((pos + QPoint(width(), 0))) == false)
			{
				pos.setX(rect.right() - frameRect.width());
			}
		}
		move(pos);

		event->accept();
	}
}

void FloatingWidget::mouseReleaseEvent(QMouseEvent * event)
{
	QWidget::mouseReleaseEvent(event);
}

void FloatingWidget::enterEvent(QEvent * e) 
{
	if (m_timer && m_timer->isActive())
	{
		m_timer->stop();
	}

	ShowDockWidget();

	QWidget::enterEvent(e);
}

void FloatingWidget::leaveEvent(QEvent * e) 
{
	QPoint mousePos = mapFromGlobal(QCursor::pos());
	if (rect().contains(mousePos) == false
		&& mousePos.x() != rect().width())
	{
		HideDockWidget();
	}
	else
	{
		if (m_timer == nullptr)
		{
			m_timer = new QTimer(this);
			connect(m_timer, &QTimer::timeout, this, [this]{
				QPoint mousePos = mapFromGlobal(QCursor::pos());
				if (this->rect().contains(mousePos) == false
					&& mousePos.x() != rect().width())
				{
					HideDockWidget();
				}
			});
		}
		m_timer->start(500);
	}

	QWidget::leaveEvent(e);
}

#include "deskdockwidget.h"

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);

	FloatingWidget *w = new FloatingWidget(FloatingWidget::AllArea);

	w->show();

	return a.exec();
}

#ifndef __QT_ALL_INCLUDES__
#define __QT_ALL_INCLUDES__

#include <QtWidgets/QWidget>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDesktopWidget>

#include <QTimer>
#include <QCursor>
#include <QPainter>
#include <QMouseEvent>
#include <QPixmap>
#include <Windows.h>

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值