头文件
#ifndef ABSTRACTMAINWINDOW_H
#define ABSTRACTMAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QStyleOption>
#include <QMouseEvent>
#include <QPoint>
#include <QResizeEvent>
class AbstractMainWindow : public QMainWindow
{
Q_OBJECT
enum CursorPosition
{
None,
TopLeft,
Top,
TopRight,
Right,
BottomRight,
Bottom,
BottomLeft,
Left
};
protected:
QPoint m_startPos;
bool m_isPressed = false;
bool m_followMouseMove = false;
Qt::CursorShape m_cursorShape = Qt::ArrowCursor;
CursorPosition m_cursorPosition = None;
bool m_cursorShapeChangable = true;
int m_deltaLength = 10;
protected:
AbstractMainWindow(QWidget* parent = nullptr);
virtual bool construct();
bool event(QEvent *event);
void paintEvent(QPaintEvent* e);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void setCursorShape(Qt::CursorShape shape);
public:
void setFollowMouseMove(bool value);
void setCursorShapeChangable(bool value);
};
#endif // ABSTRACTMAINWINDOW_H
源文件
#include "AbstractMainWindow.h"
#include <QDebug>
AbstractMainWindow::AbstractMainWindow(QWidget* parent):QMainWindow(parent)
{
//设置鼠标追踪
setMouseTracking(true);
}
bool AbstractMainWindow::construct()
{
return true;
}
bool AbstractMainWindow::event(QEvent *event)
{
if(event->type() == QEvent::HoverMove)
{
/* 处理无边框后拖拽改变窗口大小问题 */
//左上
auto topLeftGPos = this->pos();
//右上
auto topRightGPos = QPoint(this->geometry().right(),y());
//右下
auto bottomRightGPos = QPoint(this->geometry().right(),this->geometry().bottom());
//左下
auto bottomLeftGPos = QPoint(x(),this->geometry().bottom());
auto event_pos = cursor().pos();
//在右边界
if((topRightGPos.x() - m_deltaLength <= event_pos.x()) && (event_pos.x() <= topRightGPos.x() + m_deltaLength))
{
if(m_cursorShape == Qt::ArrowCursor)
{
if((topRightGPos.y() - m_deltaLength <= event_pos.y()) && (event_pos.y() <= topRightGPos.y() + m_deltaLength))
{
m_cursorPosition = TopRight;
setCursorShape(Qt::SizeBDiagCursor);
}
else if((bottomRightGPos.y() - m_deltaLength <= event_pos.y()) && (event_pos.y() <= bottomRightGPos.y() + m_deltaLength))
{
m_cursorPosition = BottomRight;
setCursorShape(Qt::SizeFDiagCursor);
}
else
{
m_cursorPosition = Right;
setCursorShape(Qt::SizeHorCursor);
}
}
}
//在左边界
else if((topLeftGPos.x() - m_deltaLength <= event_pos.x()) && (event_pos.x() <= topLeftGPos.x() + m_deltaLength))
{
if(m_cursorShape == Qt::ArrowCursor)
{
if((topLeftGPos.y() - m_deltaLength <= event_pos.y()) && (event_pos.y() <= topLeftGPos.y() + m_deltaLength))
{
m_cursorPosition = TopLeft;
setCursorShape(Qt::SizeFDiagCursor);
}
else if((bottomLeftGPos.y() - m_deltaLength <= event_pos.y()) && (event_pos.y() <= bottomLeftGPos.y() + m_deltaLength))
{
m_cursorPosition = BottomLeft;
setCursorShape(Qt::SizeBDiagCursor);
}
else
{
m_cursorPosition = Left;
setCursorShape(Qt::SizeHorCursor);
}
}
}
//在上边界
else if((topLeftGPos.y() - m_deltaLength <= event_pos.y()) && (event_pos.y() <= topLeftGPos.y() + m_deltaLength))
{
if(m_cursorShape == Qt::ArrowCursor)
{
m_cursorPosition = Top;
setCursorShape(Qt::SizeVerCursor);
}
}
//在下边界
else if((bottomLeftGPos.y() - m_deltaLength <= event_pos.y()) && (event_pos.y() <= bottomLeftGPos.y() + m_deltaLength))
{
if(m_cursorShape == Qt::ArrowCursor)
{
m_cursorPosition = Bottom;
setCursorShape(Qt::SizeVerCursor);
}
}
else
{
m_cursorPosition = None;
setCursorShape(Qt::ArrowCursor);
}
}
return QMainWindow::event(event);
}
void AbstractMainWindow::paintEvent(QPaintEvent* e)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
(void)e;
}
void AbstractMainWindow::mousePressEvent(QMouseEvent *event)
{
QMainWindow::mousePressEvent(event);
if(m_followMouseMove)
{
if(event->button() == Qt::LeftButton)
{
m_isPressed = true;
m_startPos = event->globalPos();
}
}
m_cursorShape = cursor().shape();
}
void AbstractMainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if(m_followMouseMove)
m_isPressed = false;
QMainWindow::mouseReleaseEvent(event);
}
void AbstractMainWindow::mouseMoveEvent(QMouseEvent *event)
{
if(m_followMouseMove)
{
if(m_isPressed)
{
if(m_cursorShape == Qt::ArrowCursor)
{
auto offset = event->globalPos() - m_startPos;
m_startPos = event->globalPos();
move(x() + offset.x(),y() + offset.y());
}
else
{
auto offset = event->globalPos() - m_startPos;
m_startPos = event->globalPos();
switch(m_cursorPosition)
{
case TopLeft:
{
move(x() + offset.x(),y() + offset.y());
resize(width() - offset.x(),height() - offset.y());
break;
}
case Top:
{
move(x(),y() + offset.y());
resize(width(),height() - offset.y());
break;
}
case TopRight:
{
resize(width() + offset.x(),height() - offset.y());
break;
}
case Right:
{
resize(width() + offset.x(),height());
break;
}
case BottomRight:
{
resize(width() + offset.x(),height() + offset.y());
break;
}
case Bottom:
{
resize(width(),height() + offset.y());
break;
}
case BottomLeft:
{
move(x() + offset.x(),y());
resize(width() - offset.x(),height() + offset.y());
break;
}
case Left:
{
move(x() + offset.x(),y());
resize(width() - offset.x(),height());
break;
}
default:
break;
}
}
}
}
QMainWindow::mouseMoveEvent(event);
}
void AbstractMainWindow::setFollowMouseMove(bool value)
{
m_followMouseMove = value;
}
void AbstractMainWindow::setCursorShapeChangable(bool value)
{
m_cursorShapeChangable = value;
}
void AbstractMainWindow::setCursorShape(Qt::CursorShape shape)
{
if(m_cursorShapeChangable)
{
setCursor(shape);
}
}
默认是不开启通过鼠标来移动窗口的,调用setFollowMouseMove(true)即可