首页 > 其他分享 >实现qt 窗口无边框拖拽

实现qt 窗口无边框拖拽

时间:2024-11-10 13:08:35浏览次数:1  
标签:FramelessWidget qt void 拖拽 movePoint 边框 event rect Qt

无边框拖拽是参考Qt实战6.万能的无边框窗口(FramelessWindow) - Qt小罗 - 博客园的文章,对其代码进行修改而来。

本篇一共会提供本人写的无边框的代码以及Qt实战6.万能的无边框窗口(FramelessWindow) - Qt小罗 - 博客园里面的完整代码供大家参考.

代码使用的话,我是直接让widget继承于framlessWidget,下图是效果图

参考的代码就不解释了,只解释一点我写的

相比较,我将m_movePoint变成是m_pressPoint距离鼠标的相对坐标;然后让m_bIsResizing的值由m_direction来判断是否要拉伸窗口,同时添加了一个透明的带边框的窗体border(TransparentBorder不是qt库的)来实现预览移动而拉伸的状态,因为我将qt小罗的及时修改边框的位置和大小改成延时,所以需要有个能预览的边框来观看。

至于函数

由鼠标按下和松开来调用其他函数,例如鼠标按下要对一些变量进行重新设置避免上次操作的影响、判断是否要拉伸窗口和让border绑定父窗口显示出border。其他函数需要自己查看

代码存放:

haoyouxiaoju/qt_widget: 存放qt 写过的widget

本人的代码

//framelessWidget.h

#pragma once

#include <QWidget>
class TransparentBorder;


class FramelessWidget : public QWidget
{
	Q_OBJECT
public:
		enum Direction {//鼠标处于哪个边界
		BOTTOMRIGHT,
		TOPRIGHT,
		TOPLEFT,
		BOTTOMLEFT,
		RIGHT,
		DOWN,
		LEFT,
		UP,
		NONE
	};
	enum {//距离边界多少时改变鼠标样式
		MARGIN_MIN_SIZE = 0,
		MARGIN_MAX_SIZE = 4
	};
public:
	FramelessWidget(QWidget* parent = nullptr);
	~FramelessWidget();
	
	
	void setBorderColor(const QColor& color);


protected:
	bool event(QEvent* event) override;
	void leaveEvent(QEvent* event) override;
	void mousePressEvent(QMouseEvent* event) override;
	void mouseMoveEvent(QMouseEvent* event) override;
	void mouseReleaseEvent(QMouseEvent* event) override;
	//修改鼠标样式,且是否处于边界
	void updateRegion(QMouseEvent* event);
	//修改大小和位置,即geometry
	void resizeRegion(int marginTop, int marginBottom, int marginLeft, int marginRight);
	void createShadow();
	void maximizeWidget();
	void restoreWidget();


    void paintEvent(QPaintEvent* event) override;

private:
	bool m_bIsPressed;		//是否鼠标按下
	bool m_bIsResizing;		//是否要拉伸
	bool m_bIsDoublePressed;//没用到
	QPoint m_pressPoint;	//鼠标按下时的坐标
	QPoint m_pressPoint_initial;//没用到
	QPoint m_movePoint;		//鼠标移动了的相对坐标
	Direction m_direction;	//鼠标的状态即在哪个边界


	QRect rect;				//用于存放geometry
	TransparentBorder* border;

};

class TransparentBorder :public  QWidget {
public:
	TransparentBorder();
	~TransparentBorder();


	void resizeBorder(const QPoint& movePoint,FramelessWidget::Direction direction);
	void moveBorder(const QPoint& movePoint);

	void setParentRect(const QRect& rect);
	void setBorderColor(const QColor& color);
protected:

	void paintEvent(QPaintEvent* event) override;
	
private:
	QPoint marginOrigin;
	QRect parentRect;
	QColor borderColor;
};
//framelessWidget.cpp
#include "framelesswidget.h"
#include <QEvent>
#include <QMouseEvent>
#include <QRect>
#include <QApplication>
#include <QGraphicsDropShadowEffect>
#include <QtMath>
#include <QPen>
#include <QPainter>
#include <QPainterPath>
#include "model/data.h"

FramelessWidget::FramelessWidget(QWidget* parent)
	: QWidget(parent), m_bIsPressed(false), m_bIsResizing(false), m_bIsDoublePressed(false),
	m_direction(NONE)
{
	setWindowFlags(Qt::FramelessWindowHint);    //隐藏标题栏(无边框)
	setAttribute(Qt::WA_StyledBackground);      //启用样式背景绘制
	//setAttribute(Qt::WA_TranslucentBackground); //背景透明
	setAttribute(Qt::WA_Hover);
	setAttribute(Qt::WA_StaticContents);
	this->setMinimumSize(50, 50);
	
	border = new TransparentBorder();//并没有让border挂在this下面,所以得析构时得delete
	border->hide();

}

FramelessWidget::~FramelessWidget()
{
	delete border;
}

bool FramelessWidget::event(QEvent* event)
{
	///
	// 使得移除窗口仍能进行鼠标移动的事件
	///
	if (event->type() == QEvent::HoverMove) {
		QHoverEvent* hoverEvent = static_cast<QHoverEvent*>(event);
		QMouseEvent mouseEvent(QEvent::MouseMove, hoverEvent->pos(),
			Qt::NoButton, Qt::NoButton, Qt::NoModifier);
		mouseMoveEvent(&mouseEvent);
		//LOG() << "hover move";
	}

	return QWidget::event(event);
}

void FramelessWidget::mousePressEvent(QMouseEvent* event)
{
	QWidget::mousePressEvent(event);
	if (event->button() == Qt::LeftButton) {
		m_bIsPressed = true;
		m_pressPoint = event->globalPos();//鼠标按下的绝对坐标
		m_movePoint = QPoint(0, 0);//使得上次移动的相对坐标清零

	}
	//*
	//如果m_direction不为NoNE 即 鼠标在窗口边界 那么就是要进行窗口拉伸
	//*
	if (m_direction != NONE) {
		m_bIsResizing = true;
	}
	//由于使用的是 额外创建一个boder边框使得能够预览窗口的位置
	// 所以得让boder知道要绑定谁,且知道他的geometry
	border->setParentRect(geometry());
	border->show();//显示边框
}

void FramelessWidget::mouseMoveEvent(QMouseEvent* event)
{

	QWidget::mouseMoveEvent(event);
	m_movePoint = event->globalPos() - m_pressPoint;
	//LOG() <<"m_bIsResizing"<< m_bIsResizing;
	//LOG() <<"m_bIsPressed"<< m_bIsPressed;
	
	//*
	//	鼠标没按下 且 不处于拉伸状态才来判断是不是在边界
	//*
	if (windowState() != Qt::WindowMaximized && !m_bIsPressed && !m_bIsResizing) {
		updateRegion(event);
	}

//	LOG() << "width" << minimumWidth();
//	LOG() << "height" << minimumHeight();

	//*
	//	鼠标按下 但不处于拉伸状态
	//*
	if (m_bIsPressed && !m_bIsResizing) {
		border->moveBorder(m_movePoint);
	}
	//拉伸状态
	else if (m_bIsResizing) {
		border->resizeBorder(m_movePoint, m_direction);
	}



}

// 用于识别是否是拉伸动作
void FramelessWidget::updateRegion(QMouseEvent* event)
{
	QRect mainRect = geometry();

	int marginTop = event->globalY() - mainRect.y();
	int marginBottom = mainRect.y() + mainRect.height() - event->globalY();
	int marginLeft = event->globalX() - mainRect.x();
	int marginRight = mainRect.x() + mainRect.width() - event->globalX();

	//LOG() << marginTop << "|" << marginBottom << "|" << marginLeft << "|" << marginRight;

	if (!m_bIsResizing && !m_bIsPressed) {
		if ((marginRight >= MARGIN_MIN_SIZE && marginRight <= MARGIN_MAX_SIZE)
			&& ((marginBottom <= MARGIN_MAX_SIZE) && marginBottom >= MARGIN_MIN_SIZE)) {
			m_direction = BOTTOMRIGHT;
			setCursor(Qt::SizeFDiagCursor);
		}
		else if ((marginTop >= MARGIN_MIN_SIZE && marginTop <= MARGIN_MAX_SIZE)
			&& (marginRight >= MARGIN_MIN_SIZE && marginRight <= MARGIN_MAX_SIZE)) {
			m_direction = TOPRIGHT;
			setCursor(Qt::SizeBDiagCursor);
		}
		else if ((marginLeft >= MARGIN_MIN_SIZE && marginLeft <= MARGIN_MAX_SIZE)
			&& (marginTop >= MARGIN_MIN_SIZE && marginTop <= MARGIN_MAX_SIZE)) {
			m_direction = TOPLEFT;
			setCursor(Qt::SizeFDiagCursor);
		}
		else if ((marginLeft >= MARGIN_MIN_SIZE && marginLeft <= MARGIN_MAX_SIZE)
			&& (marginBottom >= MARGIN_MIN_SIZE && marginBottom <= MARGIN_MAX_SIZE)) {
			m_direction = BOTTOMLEFT;
			setCursor(Qt::SizeBDiagCursor);
		}
		else if (marginBottom <= MARGIN_MAX_SIZE && marginBottom >= MARGIN_MIN_SIZE) {
			m_direction = DOWN;
			setCursor(Qt::SizeVerCursor);
		}
		else if (marginLeft <= MARGIN_MAX_SIZE - 1 && marginLeft >= MARGIN_MIN_SIZE - 1) {
			m_direction = LEFT;
			setCursor(Qt::SizeHorCursor);
		}
		else if (marginRight <= MARGIN_MAX_SIZE && marginRight >= MARGIN_MIN_SIZE) {
			m_direction = RIGHT;
			setCursor(Qt::SizeHorCursor);
		}
		else if (marginTop <= MARGIN_MAX_SIZE && marginTop >= MARGIN_MIN_SIZE) {
			m_direction = UP;
			setCursor(Qt::SizeVerCursor);
		}
		else {
			m_direction = NONE;
			setCursor(Qt::ArrowCursor);

		}
	}
	//LOG() << m_direction;

}

//对窗口进行大小和位置进行设置
void FramelessWidget::resizeRegion(int marginTop, int marginBottom,
	int marginLeft, int marginRight)
{
	if (m_bIsPressed && m_bIsResizing) {
		//LOG() << "resize" << m_direction;
		switch (m_direction) {
		case BOTTOMRIGHT:
		{
			rect = geometry();
			rect.setBottomRight(rect.bottomRight() + m_movePoint);
			this->setGeometry(rect);
		}
		break;
		case TOPRIGHT:
		{
			rect = geometry();
			// 设置的宽度 小于 最小宽度 高度 小于 最小高度
			if (geometry().width() + m_movePoint.x() <= minimumWidth() && geometry().height() - m_movePoint.y() <= minimumHeight()) {
				rect.setRect(rect.x() ,
					rect.y() + rect.height() - minimumHeight(),
					minimumWidth(),
					minimumHeight());
				//LOG() << "1";
			}
			// 设置的宽度 小于 最小宽度 高度 大于 最小高度
			else if (geometry().width() + m_movePoint.x() <= minimumWidth() && geometry().height() - m_movePoint.y() > minimumHeight()) {
				rect.setRect(rect.x() ,
					rect.y() + m_movePoint.y(),
					minimumWidth(),
					rect.height() - m_movePoint.y());
				//LOG() << "2";
			}
			// 设置的宽度 大于 最小宽度 高度 小于 最小高度
			else if (geometry().height() - m_movePoint.y() <= minimumHeight() && geometry().width() + m_movePoint.x() > minimumWidth()) {
				rect.setRect(rect.x() ,
					rect.y() + rect.height() - minimumHeight(),
					rect.width() + m_movePoint.x(),
					minimumHeight());
				//LOG() << "3"<<rect;

			}
			// 设置的宽度 大于 最小宽度 高度 大于 最小高度
			else {
				rect.setTopRight(rect.topRight() + m_movePoint);
				//LOG() << "4";

			}


			this->setGeometry(rect);
		}
		break;
		case TOPLEFT:
		{
			rect = geometry();
			// 设置的宽度 小于 最小宽度 高度 小于 最小高度
			if (geometry().width() - m_movePoint.x() <= minimumWidth() && geometry().height() - m_movePoint.y() <= minimumHeight()) {
				rect.setRect(rect.x() +rect.width() -minimumWidth(),
					rect.y() + rect.height() -minimumHeight(),
					minimumWidth(),
					minimumHeight());
				//LOG() << "1";
			}
			// 设置的宽度 小于 最小宽度 高度 大于 最小高度
			else if (geometry().width() - m_movePoint.x() <= minimumWidth() && geometry().height() - m_movePoint.y() > minimumHeight()) {
				rect.setRect(rect.x() +rect.width() -minimumWidth() ,
					rect.y() + m_movePoint.y(),
					minimumWidth(),
					rect.height() - m_movePoint.y());
				//LOG() << "2";
			}
			// 设置的宽度 大于 最小宽度 高度 小于 最小高度
			else if (geometry().height() - m_movePoint.y() <= minimumHeight() && geometry().width() - m_movePoint.x() > minimumWidth()) {
				rect.setRect(rect.x() + m_movePoint.x(),
					rect.y() + rect.height() - minimumHeight(),
					rect.width() - m_movePoint.x(),
					minimumHeight());
				//LOG() << "3"<<rect;

			}
			// 设置的宽度 大于 最小宽度 高度 大于 最小高度
			else {
				rect.setTopLeft(rect.topLeft() + m_movePoint);
				//LOG() << "4";

			}


			this->setGeometry(rect);

		}
		break;
		case BOTTOMLEFT:
		{
			rect = geometry();
			// 设置的宽度 小于 最小宽度 高度 小于 最小高度
			if (geometry().width() - m_movePoint.x() <= minimumWidth() && geometry().height() + m_movePoint.y() <= minimumHeight()) {
				rect.setRect(rect.x() +rect.width() -minimumWidth(),
					rect.y(),
					minimumWidth(),
					minimumHeight());
				//LOG() << "1";
			}
			// 设置的宽度 小于 最小宽度 高度 大于 最小高度
			else if (geometry().width() - m_movePoint.x() <= minimumWidth() && geometry().height() + m_movePoint.y() > minimumHeight()) {
				rect.setRect(rect.x() +rect.width() -minimumWidth() ,
					rect.y(),
					minimumWidth(),
					rect.height() + m_movePoint.y());
				//LOG() << "2";
			}
			// 设置的宽度 大于 最小宽度 高度 小于 最小高度
			else if (geometry().height() + m_movePoint.y() <= minimumHeight() && geometry().width() - m_movePoint.x() > minimumWidth()) {
				rect.setRect(rect.x() + m_movePoint.x(),
					rect.y(),
					rect.width() - m_movePoint.x(),
					minimumHeight());
				//LOG() << "3"<<rect;

			}
			// 设置的宽度 大于 最小宽度 高度 大于 最小高度
			else {
				rect.setBottomLeft(rect.bottomLeft() + m_movePoint);
				//LOG() << "4";

			}


			this->setGeometry(rect);

		}
		break;
		case RIGHT:
		{
			rect = geometry();
			rect.setRight(rect.right() + m_movePoint.x());
			this->setGeometry(rect);
			//setFixedSize(rect.width(), rect.height());

		}
		break;
		case DOWN:
		{
			rect = geometry();
			rect.setBottom(rect.bottom() + m_movePoint.y());
			//rect.setHeight(rect.height() + m_movePoint.y());
			this->setGeometry(rect);
			//setFixedSize(rect.width(), rect.height());
			//LOG() << "down";
		}
		break;
		case LEFT:
		{
			if (geometry().width() - m_movePoint.x() < minimumWidth()) {
				rect = geometry();
				rect.setRect(rect.x() + rect.width() - minimumWidth(),
					rect.y() ,
					minimumWidth(),
					rect.height());
				this->setGeometry(rect);
			}
			else {

				rect = geometry();
				rect.setLeft(rect.left() + m_movePoint.x());
				//rect.setX(rect.width() - m_movePoint.x());
				this->setGeometry(rect);

				//setFixedSize(rect.width(), rect.height());
				//this->move(rect.x() + m_movePoint.x(), rect.y());
			}
		}
		break;
		case UP:
		{
			if (geometry().height() - m_movePoint.y() < minimumHeight()) {
				rect = geometry();
				rect.setRect(rect.x(),
					rect.y() + rect.height() - minimumHeight(),
					rect.width(),
					minimumHeight());
				this->setGeometry(rect);
			}
			else {
				rect = geometry();
				rect.setTop(rect.top() + m_movePoint.y());
				this->setGeometry(rect);
				//LOG() << "UP";
			}
			

		}
		break;
		default:
		{
		}
		break;
		}
	}
	else {
		m_bIsResizing = false;
		//当不在边界一定得设置NONE,不然会导致在边界后,下次不在边界会被判断成拉伸状态
		m_direction = NONE;
	}
}

void FramelessWidget::mouseReleaseEvent(QMouseEvent* event)
{
	///
	//	鼠标松开 需要判断 是否处于拉伸状态需要修改窗口
	//			是否是窗口需要移动
	///
    QWidget::mouseReleaseEvent(event);
	LOG() << m_direction;
	if (NONE != m_direction) {
		//LOG() << "resize";
		resizeRegion(0, 0, 0, 0);
	}
	// 鼠标松开,当鼠标按下的状态还没修改
	//	处于移动窗口的状态
	if (!m_bIsResizing && m_bIsPressed) {
		this->move(geometry().x() + m_movePoint.x(), geometry().y() + m_movePoint.y());
	}
	
	//LOG() << "1:" << geometry();

	// 修改鼠标的样式
	if (windowState() != Qt::WindowMaximized) {
		updateRegion(event);
	}

	//重置值,防止影响下次判断
    if (event->button() == Qt::LeftButton) {
        m_bIsPressed = false;
		m_bIsResizing = false;
		m_bIsDoublePressed = false;
		m_direction = NONE;
	}
	//完成 操作 取消显示边框
	border->hide();

	//LOG() << "move_point" << m_movePoint;
	//LOG()<<"2:" << geometry();
}

void FramelessWidget::leaveEvent(QEvent *event)
{
   // m_bIsPressed = false;
   // m_bIsDoublePressed = false;
   // m_bIsResizing = false;

    QWidget::leaveEvent(event);
}

void FramelessWidget::createShadow()
{
    QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setColor(Qt::black);
    shadowEffect->setOffset(0, 0);
    shadowEffect->setBlurRadius(13);
    this->setGraphicsEffect(shadowEffect);
}

void FramelessWidget::maximizeWidget()
{
  
    showMaximized();
}
void FramelessWidget::restoreWidget()
{
   
    showNormal();
}

void FramelessWidget::setBorderColor(const QColor& color)
{
	this->border->setBorderColor(color);
}


void FramelessWidget::paintEvent(QPaintEvent* event)
{

    QWidget::paintEvent(event);


}


TransparentBorder::TransparentBorder():
	QWidget(),marginOrigin(0,0),parentRect(0,0,0,0),borderColor(Qt::white)
{
	setWindowOpacity(1);
	this->setAttribute(Qt::WA_TranslucentBackground, true);//透明
	this->setWindowFlags(Qt::FramelessWindowHint);//无边框

}

TransparentBorder::~TransparentBorder()
{
}

//边框的大小设置
void TransparentBorder::resizeBorder(const QPoint& m_movePoint, FramelessWidget::Direction direction)
{
	switch (direction) {
	case FramelessWidget::Direction::BOTTOMRIGHT:
		{
		LOG() << "BottomRight";
			QRect rect(parentRect);
			rect.setBottomRight(rect.bottomRight() + m_movePoint);
			this->setGeometry(rect);
		}
		break;
		case FramelessWidget::Direction::TOPRIGHT:
		{
			QRect rect(parentRect);
			rect.setTopRight(rect.topRight() + m_movePoint);
			this->setGeometry(rect);
		}
		break;
		case FramelessWidget::Direction::TOPLEFT:
		{
			QRect rect(parentRect);
			rect.setTopLeft(rect.topLeft() + m_movePoint);
			this->setGeometry(rect);
		}
		break;
		case FramelessWidget::Direction::BOTTOMLEFT:
		{
			QRect rect(parentRect);
			rect.setBottomLeft(rect.bottomLeft() + m_movePoint);
			this->setGeometry(rect);
		}
		break;
		case FramelessWidget::Direction::RIGHT:
		{
			QRect rect(parentRect);
			rect.setRight(rect.right() + m_movePoint.x());
			setGeometry(rect);

		}
		break;
		case FramelessWidget::Direction::DOWN:
		{
			//LOG() << "down";
			//LOG() << "parentRect:" << parentRect;
			QRect rect(parentRect);
			rect.setBottom(rect.bottom() + m_movePoint.y());
			//rect.setHeight(rect.height() + m_movePoint.y());
			setGeometry(rect);

		}
		break;
		case FramelessWidget::Direction::LEFT:
		{
			QRect rect(parentRect);
			rect.setLeft(rect.left() + m_movePoint.x());
			setGeometry(rect);

		}
		break;
		case FramelessWidget::Direction::UP:
		{
			QRect rect(parentRect);
			//rect.setHeight(rect.height() - m_movePoint.y());
			rect.setTop(rect.top() + m_movePoint.y());
			setGeometry(rect);
			//setFixedSize(rect.width(), rect.height());
			//LOG() << "UP";
			
		}
		break;
		default:
		{
		}
		break;
		}

}

//移动边框
void TransparentBorder::moveBorder(const QPoint& movePoint)
{
	this->move(parentRect.x()+movePoint.x(), parentRect.y()+movePoint.y());
}


//设置要绑定哪个窗口
void TransparentBorder::setParentRect(const QRect& rect)
{
	parentRect.setRect(rect.x(),rect.y(),rect.width(),rect.height());
	this->setGeometry(parentRect);

}

void TransparentBorder::setBorderColor(const QColor& color)
{
	borderColor = color;
}

// 渲染时画出出边框
void TransparentBorder::paintEvent(QPaintEvent *event)
{

	QRect rect = geometry();
	QPainter painter(this);
    painter.setBrush(QColor(9,151,247,1));//painter区域全部的背景色
    painter.setPen(QPen(borderColor,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
    painter.setCompositionMode(QPainter::CompositionMode_Difference);
    painter.drawRect(0,0,rect.width(),rect.height());

	//this->resize(parentRect.width(),parentRect.height());
}

qt 小罗的代码

//framelessWidget.h
#pragma once

#include <QWidget>

class FramelessWidget : public QWidget
{
	Q_OBJECT
		enum Direction {
		BOTTOMRIGHT,
		TOPRIGHT,
		TOPLEFT,
		BOTTOMLEFT,
		RIGHT,
		DOWN,
		LEFT,
		UP,
		NONE
	};
	enum {
		MARGIN_MIN_SIZE = 0,
		MARGIN_MAX_SIZE = 5
	};
public:
	FramelessWidget(QWidget* parent = nullptr);
	~FramelessWidget();
protected:
	bool event(QEvent* event) override;
	void leaveEvent(QEvent* event) override;
	void mousePressEvent(QMouseEvent* event) override;
	void mouseMoveEvent(QMouseEvent* event) override;
	void mouseReleaseEvent(QMouseEvent* event) override;
	void updateRegion(QMouseEvent* event);
	void resizeRegion(int marginTop, int marginBottom, int marginLeft, int marginRight);
	void createShadow();
	void maximizeWidget();
	void restoreWidget();

private:
	bool m_bIsPressed;
	bool m_bIsResizing;
	bool m_bIsDoublePressed;
	QPoint m_pressPoint;
	QPoint m_pressPoint_initial;
	QPoint m_movePoint;
	Direction m_direction;

	QRect rect;

};
//framelessWidget.cpp
#include "framelesswidget.h"
#include <QEvent>
#include <QMouseEvent>
#include <QRect>
#include <QApplication>
#include <QGraphicsDropShadowEffect>

#include "model/data.h"

FramelessWidget::FramelessWidget(QWidget *parent)
	: QWidget(parent),m_bIsPressed(false),m_bIsResizing(false),m_bIsDoublePressed(false),
    m_direction(NONE)
{
	setWindowFlags(Qt::FramelessWindowHint);    //隐藏标题栏(无边框)
	setAttribute(Qt::WA_StyledBackground);      //启用样式背景绘制
	setAttribute(Qt::WA_TranslucentBackground); //背景透明
	setAttribute(Qt::WA_Hover);
    this->setMinimumSize(50, 50);

}

FramelessWidget::~FramelessWidget()
{}

bool FramelessWidget::event(QEvent *event)
{
    if (event->type() == QEvent::HoverMove) {
        QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
        QMouseEvent mouseEvent(QEvent::MouseMove, hoverEvent->pos(),
                               Qt::NoButton, Qt::NoButton, Qt::NoModifier);
        mouseMoveEvent(&mouseEvent);
    }

    return QWidget::event(event);
}

void FramelessWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_bIsPressed = true;
        m_pressPoint = event->globalPos();
    }

    return QWidget::mousePressEvent(event);
}

void FramelessWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (m_bIsPressed) {
        if (m_bIsResizing) {
            m_movePoint = event->globalPos() - m_pressPoint;
            m_pressPoint += m_movePoint;
        } else {
            if (!m_bIsDoublePressed && windowState() == Qt::WindowMaximized) {
                restoreWidget();
                QPointF point(width() * ((double)(event->globalPos().x())/QGuiApplication::primaryScreen()->geometry().width()),
                              height() * ((double)(event->globalPos().y())/QGuiApplication::primaryScreen()->geometry().height()));

                move(event->globalPos() - point.toPoint());

                m_pressPoint = event->globalPos();
            }

            QPoint point = event->globalPos() - m_pressPoint;
            move(pos() + point);

            m_pressPoint = event->globalPos();
        }
    }

    if (windowState() != Qt::WindowMaximized) {
        updateRegion(event);
    }

    QWidget::mouseMoveEvent(event);
}

void FramelessWidget::updateRegion(QMouseEvent *event)
{
    QRect mainRect = geometry();

    int marginTop = event->globalY() - mainRect.y();
    int marginBottom = mainRect.y() + mainRect.height() - event->globalY();
    int marginLeft = event->globalX() - mainRect.x();
    int marginRight = mainRect.x() + mainRect.width() - event->globalX();

    //LOG() << marginTop << "|" << marginBottom << "|" << marginLeft << "|" << marginRight;

    if (!m_bIsResizing) {
        if ( (marginRight >= MARGIN_MIN_SIZE && marginRight <= MARGIN_MAX_SIZE)
             && ((marginBottom <= MARGIN_MAX_SIZE) && marginBottom >= MARGIN_MIN_SIZE) ) {
            m_direction = BOTTOMRIGHT;
            setCursor(Qt::SizeFDiagCursor);
        } else if ( (marginTop >= MARGIN_MIN_SIZE && marginTop <= MARGIN_MAX_SIZE)
                    && (marginRight >= MARGIN_MIN_SIZE && marginRight <= MARGIN_MAX_SIZE)) {
            m_direction = TOPRIGHT;
            setCursor(Qt::SizeBDiagCursor);
        } else if ( (marginLeft >= MARGIN_MIN_SIZE && marginLeft <= MARGIN_MAX_SIZE)
                    && (marginTop >= MARGIN_MIN_SIZE && marginTop <= MARGIN_MAX_SIZE) ) {
            m_direction = TOPLEFT;
            setCursor(Qt::SizeFDiagCursor);
        } else if ( (marginLeft >= MARGIN_MIN_SIZE && marginLeft <= MARGIN_MAX_SIZE)
                    && (marginBottom >= MARGIN_MIN_SIZE && marginBottom <= MARGIN_MAX_SIZE)) {
            m_direction = BOTTOMLEFT;
            setCursor(Qt::SizeBDiagCursor);
        } else if (marginBottom <= MARGIN_MAX_SIZE && marginBottom >= MARGIN_MIN_SIZE) {
            m_direction = DOWN;
            setCursor(Qt::SizeVerCursor);
        } else if (marginLeft <= MARGIN_MAX_SIZE - 1 && marginLeft >= MARGIN_MIN_SIZE - 1) {
            m_direction = LEFT;
            setCursor(Qt::SizeHorCursor);
        } else if (marginRight <= MARGIN_MAX_SIZE && marginRight >= MARGIN_MIN_SIZE) {
            m_direction = RIGHT;
            setCursor(Qt::SizeHorCursor);
        } else if (marginTop <= MARGIN_MAX_SIZE && marginTop >= MARGIN_MIN_SIZE) {
            m_direction = UP;
            setCursor(Qt::SizeVerCursor);
        } else {
            if (!m_bIsPressed) {
                setCursor(Qt::ArrowCursor);
            }
        }
    }

    if (NONE != m_direction) {
        m_bIsResizing = true;
        resizeRegion(marginTop, marginBottom, marginLeft, marginRight);
    }
}

void FramelessWidget::resizeRegion(int marginTop, int marginBottom,
                               int marginLeft, int marginRight)
{
    if (m_bIsPressed) {
        switch (m_direction) {
        case BOTTOMRIGHT:
        {
            rect = geometry();
            rect.setBottomRight(rect.bottomRight() + m_movePoint);
            this->setGeometry(rect);
            
           /* LOG() << m_pressPoint;
            LOG() << m_movePoint;
            LOG() << rect;
            LOG() << m_bIsPressed;
            LOG() << m_direction;*/
        }
            break;
        case TOPRIGHT:
        {
            if (marginLeft > minimumWidth() && marginBottom > minimumHeight()) {
                QRect rect = geometry();
                rect.setTopRight(rect.topRight() + m_movePoint);
                setGeometry(rect);
            }
        }
            break;
        case TOPLEFT:
        {
            if (marginRight > minimumWidth() && marginBottom > minimumHeight()) {
                QRect rect = geometry();
                rect.setTopLeft(rect.topLeft() + m_movePoint);
                setGeometry(rect);
            }
        }
            break;
        case BOTTOMLEFT:
        {
            if (marginRight > minimumWidth() && marginTop> minimumHeight()) {
                QRect rect = geometry();
                rect.setBottomLeft(rect.bottomLeft() + m_movePoint);
                setGeometry(rect);
            }
        }
            break;
        case RIGHT:
        {
            QRect rect = geometry();
            rect.setWidth(rect.width() + m_movePoint.x());
            setGeometry(rect);
        }
            break;
        case DOWN:
        {
            QRect rect = geometry();
            rect.setHeight(rect.height() + m_movePoint.y());
            setGeometry(rect);
        }
            break;
        case LEFT:
        {
            if (marginRight > minimumWidth()) {
                QRect rect = geometry();
                rect.setLeft(rect.x() + m_movePoint.x());
                setGeometry(rect);
            }
        }
            break;
        case UP:
        {
            if (marginBottom > minimumHeight()) {
                QRect rect = geometry();
                rect.setTop(rect.y() + m_movePoint.y());
                setGeometry(rect);
            }
        }
            break;
        default:
        {
        }
            break;
        }
    } else {
        m_bIsResizing = false;
        m_direction = NONE;
    }
}

void FramelessWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_bIsPressed = false;
        m_bIsResizing = false;
        m_bIsDoublePressed = false;
    }

    QWidget::mouseReleaseEvent(event);
}

void FramelessWidget::leaveEvent(QEvent *event)
{
    m_bIsPressed = false;
    m_bIsDoublePressed = false;
    m_bIsResizing = false;

    QWidget::leaveEvent(event);
}

void FramelessWidget::createShadow()
{
    QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setColor(Qt::black);
    shadowEffect->setOffset(0, 0);
    shadowEffect->setBlurRadius(13);
    this->setGraphicsEffect(shadowEffect);
}

void FramelessWidget::maximizeWidget()
{
  
    showMaximized();
}
void FramelessWidget::restoreWidget()
{
   
    showNormal();
}



标签:FramelessWidget,qt,void,拖拽,movePoint,边框,event,rect,Qt
From: https://www.cnblogs.com/hyxj/p/18537865/framelessWidget

相关文章

  • 【UE4】基于蓝图拖拽物品的基本逻辑
    整体效果是基于获取玩家的鼠标位置到场景里的位置再tick就不会出现拖拽卡顿会很丝滑本人新手请大家多多担待,有问题大家帮忙指出来先创建拖拽物品的Actor(可以命名为Bp_Box01),再创建放置物品的位置(Bp_Box02)。放置物体在Bp_Box01中放置一个正方体,再在Bp_Box02中放置正方体和......
  • STM32+阿里云+ESP8266+MQTT+DHT11
    一、阿里云平台环境搭建注册完账号以后,找到控制台->物联网平台。    1.创建一个公共实例,若该实例有ID则为新公共实例2.创建一个产品[如何在物联网平台创建产品_物联网平台(IoT)-阿里云帮助中心(aliyun.com)](https://help.aliyun.com/zh/iot/user-guide/create......
  • 基于YOLOv8深度学习的木薯病害智能诊断与防治系统【python源码+Pyqt5界面+数据集+训练
    背景及意义木薯是一种重要的农作物,广泛用于食品、饲料以及工业生产等多个领域。然而,木薯病害的发生会严重影响其产量和品质,对农民的收入和食品安全造成明显的负面影响。本文基于YOLOv8深度学习框架,通过2606张图片,训练了一个木薯叶片病害的识别模型,可用于识别5种不同的木......
  • 基于YOLO11/v10/v8/v5深度学习的煤矿传送带异物检测系统设计与实现【python源码+Pyqt5
    《------往期经典推荐------》一、AI应用软件开发实战专栏【链接】项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.......
  • QT中大量数据存储至excel的问题解决
            因为这个问题困扰了我很久,所以在这里记录一下,顺便给可能会遇到类似问题的人提供一点帮助。        在qt中,如果用C++处理数据保存到excel,正常来说在pro文件中添加axcontainer 然后就能够调用到excel,但是这只能适用于数量级没那么大时的需求。  ......
  • Qt 学习第 天:文件和事件
    一、创建widget对象(文件)二、设计ui界面放一个label标签上去,设置成box就可以显示边框了三、新建Mylabel类四、提升ui界面的label标签为Mylabel五、修改mylabel.h,mylabel.cpp#ifndefMYLABEL_H#defineMYLABEL_H#include<QLabel>classMylabel:publicQLabel{......
  • QT:控制台数据新增、删除、查询、更新
    效果图: CH1301.pro 详细代码QT-=guiQT+=sqlCONFIG+=c++11consoleCONFIG-=app_bundle#Thefollowingdefinemakesyourcompileremitwarningsifyouuse#anyQtfeaturethathasbeenmarkeddeprecated(theexactwarnings#dependonyourcompil......
  • 「QT」几何数据类 之 QLine 整型直线类
    ✨博客主页何曾参静谧的博客......
  • 「QT」几何数据类 之 QPoint 整型点类
    ✨博客主页何曾参静谧的博客......
  • 来了,超全MQTT实用示例
    Air201快速入门之MQTT示例合宙Air201资产定位模组——是一个集成超低功耗4G通信、语音通话、超低功耗定位、计步、震动、Type-C、充电、放音、录音等功能的超小PCBA。内部集成高效、简单、可靠的LuatOS语言,旨在帮助客户降低开发难度,降低研发成本,以及打造超小超低功......