从CSDN过来的兄弟们有福了,调了2天无私奉献,CPP一共130行,看还有精简的地方吗?
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QRubberBand> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE #define DEFAULT_CURSOR Qt::ArrowCursor class MainWindow : public QMainWindow { Q_OBJECT Q_PROPERTY(int m_borderWidth READ borderWidth WRITE setBorderWidth) Q_PROPERTY(bool m_dragEnable READ dragEnable WRITE setDragEnable) Q_PROPERTY(bool m_bottomRightResizeEnable READ bottomRightResizeEnable WRITE setBottomRightResizeEnable) public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); enum Edge { None = 0x0, Left = 0x1, Top = 0x2, Right = 0x4, Bottom = 0x8, TopLeft = Top|Left, TopRight = Top|Right, BottomLeft = Bottom|Left, BottomRight = Bottom|Right, }; Q_DECLARE_FLAGS(Edges, Edge) protected: bool eventFilter(QObject *o, QEvent *e) override; void leaveEvent(QEvent *event); void mousePressEvent(QMouseEvent*e); void hoverMoveEvent(QHoverEvent*); void mouseReleaseEvent(QMouseEvent*); private: Qt::CursorShape calculateCursorPosition(const QPoint &, const QRect &, Edges &); void setBorderWidth(int w) {m_borderWidth = w;} int borderWidth() const {return m_borderWidth;} void setDragEnable(bool w) {m_dragEnable = w;} bool dragEnable() const {return m_dragEnable;} void setBottomRightResizeEnable(bool w) {m_bottomRightResizeEnable = w;} bool bottomRightResizeEnable() const {return m_bottomRightResizeEnable;} private slots: void on_pushButton_clicked(); void on_pushButton_2_clicked(); void on_pushButton_3_clicked(); private: Ui::MainWindow *ui; QRect m_startRect; bool m_leftButtonPressed; Edges m_edgeOnMousePress = Edge::None; int m_borderWidth = 6; QPoint m_dragPos; bool m_dragStart = false,m_dragEnable = true; bool m_bottomRightResizeEnable = true; }; #endif // MAINWINDOW_H
CPP:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QMouseEvent> #include <QTimer> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow), m_leftButtonPressed(false), m_dragPos(QPoint()) { ui->setupUi(this); setWindowFlag(Qt::FramelessWindowHint); installEventFilter(this); } MainWindow::~MainWindow() { delete ui; } bool MainWindow::eventFilter(QObject *o, QEvent *e) { if (e->type()==QEvent::HoverMove && o==this) { hoverMoveEvent(static_cast<QHoverEvent*>(e)); return true; } return QMainWindow::eventFilter(o, e); } void MainWindow::leaveEvent(QEvent *event) { Q_UNUSED(event); if (!m_leftButtonPressed) unsetCursor(); } void MainWindow::mousePressEvent(QMouseEvent *e) { if (e->button() & Qt::LeftButton) { m_leftButtonPressed = true; if (calculateCursorPosition(e->globalPos(), geometry(), m_edgeOnMousePress) != DEFAULT_CURSOR) m_startRect = geometry(); if (this->rect().marginsRemoved(QMargins(borderWidth(), borderWidth(), borderWidth(), borderWidth())).contains(e->pos())) { m_dragStart = true; m_dragPos = e->pos(); } } } void MainWindow::mouseReleaseEvent(QMouseEvent *e) { if (e->button() & Qt::LeftButton) { m_leftButtonPressed = false; m_dragStart = false; if(!m_edgeOnMousePress.testFlag(Edge::None)) unsetCursor(); } } void MainWindow::hoverMoveEvent(QHoverEvent *e) { Edges currentEdge = Edge::None; static bool _cursorchanged = false; if (this->isFullScreen() || this->isMaximized()) { // 一般不来这里,除非拖拉同时按快捷键最大化 if (_cursorchanged){ unsetCursor(); _cursorchanged = false; } return; } if(!m_leftButtonPressed){ auto shape = calculateCursorPosition(mapToGlobal( e->pos() ), geometry(), currentEdge); if (!currentEdge.testFlag(Edge::None)){ setCursor(shape); _cursorchanged = true; }else if (_cursorchanged) { unsetCursor(); _cursorchanged = false; } }else{ if (m_dragStart) { move(geometry().topLeft() + (e->pos() - m_dragPos)); }else if (!m_edgeOnMousePress.testFlag(Edge::None)) { auto curPos = mapToGlobal( e->pos() ); if(m_edgeOnMousePress&(Edge::Top)) m_startRect.setTop(curPos.y()); if(m_edgeOnMousePress&(Edge::Bottom)) m_startRect.setBottom(curPos.y()); if(m_edgeOnMousePress&(Edge::Left)) m_startRect.setLeft(curPos.x()); if(m_edgeOnMousePress&(Edge::Right)) m_startRect.setRight(curPos.x()); QTimer::singleShot(0,this,[=](){ setGeometry(m_startRect); }); } } } #define EDGE_RET2(rect,pos,out,edg,cursor) do{if(rect.contains(pos,true)){out=edg;return cursor;}}while(0) Qt::CursorShape MainWindow::calculateCursorPosition(const QPoint &pos, const QRect &framerect, Edges &_edge) { QRect recL(framerect.x(),framerect.y()+m_borderWidth,m_borderWidth,framerect.height()-2*m_borderWidth); EDGE_RET2(recL,pos,_edge,Edge::Left,Qt::SizeHorCursor); QRect recR(framerect.right()-m_borderWidth,framerect.y()+m_borderWidth,m_borderWidth,framerect.height()-2*m_borderWidth); EDGE_RET2(recR,pos,_edge,Edge::Right,Qt::SizeHorCursor); QRect recB(framerect.x()+m_borderWidth,framerect.bottom()-m_borderWidth,framerect.width() - 2*m_borderWidth,m_borderWidth); EDGE_RET2(recB,pos,_edge,Edge::Bottom,Qt::SizeVerCursor); QRect recT(framerect.x()+m_borderWidth,framerect.y(),framerect.width() - 2*m_borderWidth,m_borderWidth); EDGE_RET2(recT,pos,_edge,Edge::Top,Qt::SizeVerCursor); QRect recBL(framerect.x(),framerect.bottom()-m_borderWidth,m_borderWidth,m_borderWidth); EDGE_RET2(recBL,pos,_edge,Edge::BottomLeft,Qt::SizeBDiagCursor); if(m_bottomRightResizeEnable){ QRect recBR(framerect.right()-m_borderWidth,framerect.bottom()-m_borderWidth,m_borderWidth,m_borderWidth); EDGE_RET2(recBR,pos,_edge,Edge::BottomRight,Qt::SizeFDiagCursor); } QRect recTR(framerect.right()-m_borderWidth,framerect.y(),m_borderWidth,m_borderWidth); EDGE_RET2(recTR,pos,_edge,Edge::TopRight,Qt::SizeBDiagCursor); QRect recTL(framerect.x(),framerect.y(),m_borderWidth,m_borderWidth); EDGE_RET2(recTL,pos,_edge,Edge::TopLeft,Qt::SizeFDiagCursor); _edge = Edge::None; return DEFAULT_CURSOR; } void MainWindow::on_pushButton_clicked() { resize(400,300); } void MainWindow::on_pushButton_2_clicked() { static bool isMax = true; if(isMax) showMaximized(); else showNormal(); isMax = !isMax; } void MainWindow::on_pushButton_3_clicked() { close(); }
实现是实现了,不过呢,用原生的resize / move / setGeometry 函数频繁了会导致边缘抖动,这个应该是QT内部没有做好。
要解决这个问题,有2个方法,请看下篇文章。