Qt 窗口随鼠标移动(2020-11-13更新可拉伸窗口大小)

1、原理

 

2、代码

 1 void MyWidget::mouseMoveEvent(QMouseEvent *event)
 2 {
 3     QPoint P3 = event->globalPos();
 4     QPoint P2 = P3 - L;
 5     this->move(P2);
 6 }
 7 
 8 void MyWidget::mousePressEvent(QMouseEvent *event)
 9 {
10     QPoint P3 = event->globalPos();
11     QPoint P2 = this->geometry().topLeft();
12     L = P3 - P2;    // L是QPoint变量,在.h文件中创建
13 }
14 
15 void MyWidget::mouseReleaseEvent(QMouseEvent *)
16 {
17     this->L = QPoint();
18 }
View Code

 

3、展示

 

/*************************************************************************************/

2020-11-12更新升级版

.h文件

 1 private:
 2     void paintMoveRect(QMouseEvent *e);
 3     void mousePressEvent(QMouseEvent *e)override;
 4     void mouseMoveEvent(QMouseEvent *e)override;
 5     void mouseReleaseEvent(QMouseEvent *e)override;
 6 
 7 private:
 8     Ui::MainWindow *ui;
 9     QWidget *w;     // 预览窗口
10     QPoint L = QPoint();
11     QPoint P2 = QPoint();
12     QPoint P3 = QPoint();
13     bool moveFlag = false;
.h

 

.cpp文件

PS:采用的是无边框窗口,所以标题栏是自己拉的widget。

 1 void MainWindow::paintMoveRect(QMouseEvent * e)
 2 {
 3     QSize size= this->size();
 4     w = new QWidget();
 5     w->resize(size);
 6     w->setWindowFlag(Qt::FramelessWindowHint);
 7     w->setWindowOpacity(0.5);
 8     w->setStyleSheet("background-color: rgb(160, 188, 255);");
 9 
10     w->move(this->pos());
11     w->show();
12 
13     P3 = e->globalPos();
14     P2 = w->geometry().topLeft();
15     L = P3 - P2;
16 }
17 
18 void MainWindow::mousePressEvent(QMouseEvent *e)
19 {
20     if(e->button() == Qt::LeftButton)
21     {
22         //  判断鼠标选中是否为标题栏
23         if(ui->widget == this->findChild<QWidget*>("widget"))
24         {
25             moveFlag = true;
26             paintMoveRect(e);
27         }
28     }
29     e->accept();
30 }
31 
32 void MainWindow::mouseMoveEvent(QMouseEvent *e)
33 {
34     if(moveFlag)
35     {
36         P3 = e->globalPos();
37         P2 = P3 - L;
38         w->move(P2);
39         e->accept();
40     }
41     e->accept();
42 }
43 
44 void MainWindow::mouseReleaseEvent(QMouseEvent *e)
45 {
46     if(moveFlag)
47     {
48         this->move(P2);
49         delete w;
50         w = nullptr;
51         moveFlag = false;
52     }
53     e->accept();
54 }
.cpp

 

预览gif

 

/*************************************************************************************/

2020-11-13更新(参考:https://blog.csdn.net/GoForwardToStep/article/details/77887777

画了一个简单的示意图,其实窗口拉伸也就这8块区域,当鼠标移动进入这8块区域时,需要判断当前进入了哪一块区域,然后显示什么样式。

 

 

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 #include<QDebug>
 6 
 7 QT_BEGIN_NAMESPACE
 8 namespace Ui { class MainWindow; }
 9 QT_END_NAMESPACE
10 
11 class MainWindow : public QMainWindow
12 {
13     Q_OBJECT
14 
15 private:
16     //  鼠标状态枚举
17     enum mousePositionState
18     {
19         NO_SELECT = 0,
20         LEFT_TOP_RECT,
21         TOP_BORDER,
22         RIGHT_TOP_RECT,
23         RIGHT_BORDER,
24         RIGHT_BOTTOM_RECT,
25         BOTTOM_BORDER,
26         LEFT_BOTTOM_RECT,
27         LEFT_BORDER
28     };
29 
30 public:
31     MainWindow(QWidget *parent = nullptr);
32     ~MainWindow();
33 
34 private slots:
35     void on_pushButton_clicked();
36 
37     void on_pushButton_3_clicked();
38 
39     void on_pushButton_4_clicked();
40 
41 private:
42     void paintMoveRect(QMouseEvent *e);
43     void mousePressEvent(QMouseEvent *e)override;
44     void mouseMoveEvent(QMouseEvent *e)override;
45     void mouseReleaseEvent(QMouseEvent *e)override;
46     bool event(QEvent *event) override;
47 
48     void calculateWindow();     //  计算8个Rect,每次拉伸都调用重新计算
49     mousePositionState getCursorState(QPoint pos);  //  获取鼠标状态
50     void updateMouseStyle(mousePositionState mouseState);   //  更新鼠标状态
51     void updateSize();      //  更新窗口尺寸
52 
53 private:
54     Ui::MainWindow *ui;
55     QWidget *w;     // 预览窗口
56     QPoint L = QPoint();
57     QPoint P2 = QPoint();
58     QPoint P3 = QPoint();
59     bool moveFlag = false;
60 
61     QRect m_leftTopRect;
62     QRect m_leftBottomRect;
63     QRect m_rightTopRect;
64     QRect m_rightBottomRect;
65 
66     QRect m_topBorderRect;
67     QRect m_rightBorderRect;
68     QRect m_bottomBorderRect;
69     QRect m_leftBorderRect;
70 
71     mousePositionState m_cursorState = NO_SELECT;
72     QPoint m_startPoint;    //  拉伸前的点
73     QPoint m_endPoint;      //  拉伸后的点
74     QRect m_beforSize;      //  鼠标按下事件之前的窗口尺寸
75     bool m_mousePressed = false;   //  鼠标按下状态
76     int m_minWidth;     // 原始窗口宽度
77     int m_minHeight;    //  原始窗口高度
78 };
79 
80 #endif // MAINWINDOW_H
.h
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QHoverEvent>
#include <QMouseEvent>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowFlag(Qt::FramelessWindowHint);

    this->setAttribute(Qt::WA_Hover, true);
    m_minWidth = this->size().width();      //  保存原始窗口宽度
    m_minHeight = this->size().height();    //  保存原始窗口高度
    calculateWindow();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintMoveRect(QMouseEvent * e)
{
    QSize size= this->size();
    w = new QWidget();
    w->resize(size);
    w->setWindowFlag(Qt::FramelessWindowHint);
    w->setWindowOpacity(0.5);
    w->setStyleSheet("background-color: rgb(160, 188, 255);");

    w->move(this->pos());
    w->show();

    P3 = e->globalPos();
    P2 = w->geometry().topLeft();
    L = P3 - P2;
}

void MainWindow::mousePressEvent(QMouseEvent *e)
{ 
    if(m_cursorState !=NO_SELECT && e->button() == Qt::LeftButton)
    {
        m_mousePressed = true;
        m_startPoint = this->mapToGlobal(e->pos());
        m_beforSize = this->geometry();
        e->accept();
    }

    if(m_cursorState ==NO_SELECT && e->button() == Qt::LeftButton)
    {
        //  判断鼠标选中是否为标题栏
        if(ui->widget == this->findChild<QWidget*>("widget"))
        {
            // 窗口最大化时候不能移动
            if(this->windowState() != (Qt::WindowMaximized | Qt::WindowFullScreen)
                    && this->windowState() != Qt::WindowMaximized)
                {
                    moveFlag = true;
                    paintMoveRect(e);
                }
        }
        e->accept();
    }
}

void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
    if(moveFlag)
    {
            P3 = e->globalPos();
            P2 = P3 - L;
            w->move(P2);
            e->accept();
    }
}

void MainWindow::mouseReleaseEvent(QMouseEvent *e)
{
    if(moveFlag)
    {
        this->move(P2);
        delete w;
        w = nullptr;
        moveFlag = false;
        e->accept();
    }
    m_mousePressed = false;
    calculateWindow();
}

bool MainWindow::event(QEvent *event)
{
    if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave || event->type() == QEvent::HoverMove)
        {
            QHoverEvent* pHoverEvent = static_cast<QHoverEvent*>(event);
            QPoint cursorPos = pHoverEvent->pos();
            if(!m_mousePressed)
            {   //  最大化时无法拉伸
                if(this->windowState() != (Qt::WindowMaximized | Qt::WindowFullScreen)
                        && this->windowState() != Qt::WindowMaximized)
                {
                // 根据当前鼠标的位置显示不同的样式;
                m_cursorState = getCursorState(cursorPos);
                updateMouseStyle(m_cursorState);
                }
            }
            else
            {
                m_endPoint = this->mapToGlobal(cursorPos);
                updateSize();
            }
        }
        return QWidget::event(event);
}

void MainWindow::calculateWindow()
{
    // 4个角Rect
    m_leftTopRect = QRect(0, 0, 4, 4);
    m_leftBottomRect = QRect(0, this->height() - 4, 4, 4);
    m_rightTopRect = QRect(this->width() - 4, 0, 4 , 4);
    m_rightBottomRect = QRect(this->width() - 4, this->height() - 4, 4, 4);

    // 4条边Rect
    m_topBorderRect = QRect(4, 0, this->width() - 8, 4);
    m_rightBorderRect = QRect(this->width() - 4, 4, 4, this->height() - 8);
    m_bottomBorderRect = QRect(4, this->height() - 4, this->width() - 8, 4);
    m_leftBorderRect = QRect(0,  4, 4, this->height() - 8);
}

MainWindow::mousePositionState MainWindow::getCursorState(QPoint pos)
{
    mousePositionState mouseState;
    if(m_leftTopRect.contains(pos))
        mouseState = LEFT_TOP_RECT;
    else if(m_rightTopRect.contains(pos))
        mouseState = RIGHT_TOP_RECT;
    else if(m_rightBottomRect.contains(pos))
        mouseState = RIGHT_BOTTOM_RECT;
    else if(m_leftBottomRect.contains(pos))
        mouseState = LEFT_BOTTOM_RECT;
    else if(m_topBorderRect.contains(pos))
        mouseState = TOP_BORDER;
    else if(m_bottomBorderRect.contains(pos))
        mouseState = BOTTOM_BORDER;
    else if(m_leftBorderRect.contains(pos))
        mouseState = LEFT_BORDER;
    else if(m_rightBorderRect.contains(pos))
        mouseState = RIGHT_BORDER;
    else
        mouseState = NO_SELECT;

    return mouseState;
}

void MainWindow::updateMouseStyle(MainWindow::mousePositionState mouseState)
{
    switch (mouseState)
    {
    case NO_SELECT:
        this->setCursor(Qt::ArrowCursor);
        break;
    case LEFT_TOP_RECT:
    case RIGHT_BOTTOM_RECT:
        this->setCursor(Qt::SizeFDiagCursor);
        break;
    case TOP_BORDER:
    case BOTTOM_BORDER:
        this->setCursor(Qt::SizeVerCursor);
        break;
    case RIGHT_TOP_RECT:
    case LEFT_BOTTOM_RECT:
        setCursor(Qt::SizeBDiagCursor);
        break;
    case LEFT_BORDER:
    case RIGHT_BORDER:
        setCursor(Qt::SizeHorCursor);
        break;
    default:
        setCursor(Qt::ArrowCursor);
        break;
    }
}

void MainWindow::updateSize()
{
    //  更新窗口尺寸
    QRect windowRect = m_beforSize;
    int delValue_X = m_startPoint.x() - m_endPoint.x();
    int delValue_Y = m_startPoint.y() - m_endPoint.y();

    if (m_cursorState == LEFT_BORDER)
    {
        QPoint topLeftPoint = windowRect.topLeft();
        topLeftPoint.setX(topLeftPoint.x() - delValue_X);
        windowRect.setTopLeft(topLeftPoint);
    }
    else if (m_cursorState == RIGHT_BORDER)
    {
        QPoint bottomRightPoint = windowRect.bottomRight();
        bottomRightPoint.setX(bottomRightPoint.x() - delValue_X);
        windowRect.setBottomRight(bottomRightPoint);
    }
    else if (m_cursorState == TOP_BORDER)
    {
        QPoint topLeftPoint = windowRect.topLeft();
        topLeftPoint.setY(topLeftPoint.y() - delValue_Y);
        windowRect.setTopLeft(topLeftPoint);
    }
    else if (m_cursorState == BOTTOM_BORDER)
    {
        QPoint bottomRightPoint = windowRect.bottomRight();
        bottomRightPoint.setY(bottomRightPoint.y() - delValue_Y);
        windowRect.setBottomRight(bottomRightPoint);
    }
    else if (m_cursorState == LEFT_TOP_RECT)
    {
        QPoint topLeftPoint = windowRect.topLeft();
        topLeftPoint.setX(topLeftPoint.x() - delValue_X);
        topLeftPoint.setY(topLeftPoint.y() - delValue_Y);
        windowRect.setTopLeft(topLeftPoint);
    }
    else if (m_cursorState == RIGHT_TOP_RECT)
    {
        QPoint topRightPoint = windowRect.topRight();
        topRightPoint.setX(topRightPoint.x() - delValue_X);
        topRightPoint.setY(topRightPoint.y() - delValue_Y);
        windowRect.setTopRight(topRightPoint);
    }
    else if (m_cursorState == RIGHT_BOTTOM_RECT)
    {
        QPoint bottomRightPoint = windowRect.bottomRight();
        bottomRightPoint.setX(bottomRightPoint.x() - delValue_X);
        bottomRightPoint.setY(bottomRightPoint.y() - delValue_Y);
        windowRect.setBottomRight(bottomRightPoint);
    }
    else if (m_cursorState == LEFT_BOTTOM_RECT)
    {
        QPoint bottomLeftPoint = windowRect.bottomLeft();
        bottomLeftPoint.setX(bottomLeftPoint.x() - delValue_X);
        bottomLeftPoint.setY(bottomLeftPoint.y() - delValue_Y);
        windowRect.setBottomLeft(bottomLeftPoint);
    }

    if(windowRect.width() < m_minWidth)
    {
        windowRect.setLeft(this->geometry().left());
        windowRect.setWidth(m_minWidth);
    }
    if (windowRect.height() < m_minHeight)
    {
        windowRect.setTop(this->geometry().top());
        windowRect.setHeight(m_minHeight);
    }

    this->setGeometry(windowRect);
}
.cpp

 

不知道为什么拉伸的时候,右边有点掉帧。。。。。

 

posted @ 2020-03-05 22:00  补码  阅读(1488)  评论(0编辑  收藏  举报