qt 无边框窗口,可拖动,可拉伸

qt的无边框窗口可以很方便的设置样式,但是窗口设置成无边框后就无法拖动和拉伸了,之前参考过一些晚上的教程,大体方向是对的,但是细节上有很多问题,这里分享我写的无边框窗口。

新建一个QT工程,主界面是QWidget,命名为frameless

frameless的构造函数里添加 setWindowFlag(Qt::FramelessWindowHint);

现在运行就成无边框模式了,但是你会发现现在没有关闭按键,并且无法拖动拉伸。

我们先实现拖动功能。重载鼠标事件,增加一个变量记录上一次的位置,一个bool值标记左键被按下

#include <QtWidgets/QMainWindow>
#include "ui_frameless.h"
#include <QMouseEvent>

class frameless : public QMainWindow
{
    Q_OBJECT

private:
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *);
    void mousePressEvent(QMouseEvent *event);

public:
    frameless(QWidget *parent = Q_NULLPTR);

private:
    Ui::framelessClass ui;

    QPoint                  last_point_;             //记录放大之前的位置
    QPoint                  last_position_;          //窗口上一次的位置
    bool                      left_button_pressed_ = false;   //鼠标左键按下

};

增加鼠标事件的实现

void frameless::mouseMoveEvent(QMouseEvent * event)
{
    if ((event->buttons() == Qt::LeftButton) && left_button_pressed_)
    {
        move(event->globalPos() - last_position_);
    }
}

void frameless::mouseReleaseEvent(QMouseEvent *)
{
    left_button_pressed_ = false;
}

void frameless::mousePressEvent(QMouseEvent * event)
{
    if (event->buttons() == Qt::LeftButton) {
        left_button_pressed_ = true;
        last_position_ = event->globalPos() - pos();
    }
}

现在运行,可以拖动自如了。

接下来实现拉伸功能。思路如下,将窗口分成九个部分,

   左上角(1,1)、中上(1,2)、右上角(1,3)

    左中  (2,1)、 中间(2,2)、右中  (2,3)

    左下角(3,1)、中下(3,2)、 右下角(3,3)

    1.当鼠标移动时候,首先判断这个光标处于哪个区域

    2.当鼠标移动到不同区域,鼠标的形状是不同变化的。

    3.根据(2,2)之外的区域,计算初鼠标移动的偏移量,来重新设置窗口的坐标。

代码如下

namespace {
    const int kMouseRegionLeft = 10;
    const int kMouseRegionTop = 10;
    const int kMouseRegionButtom = 10;
    const int kMouseRegionRight = 10;
}
 

void frameless::mouseMoveEvent(QMouseEvent * event)
{
    //最大化状态时不能拉伸
    if (isMaximized())
    {
        return;
    }
    //根据位置设置鼠标样式
    SetMouseCursor(event->pos().x(), event->pos().y());

    if ((event->buttons() == Qt::LeftButton) && left_button_pressed_)
    {
        QPoint point_offset = event->globalPos() - last_position_;
        if (mouse_press_region_ == kMousePositionMid)
        {
            setCursor(Qt::ArrowCursor);
            move(point_offset + last_point_);
        }
        else
        {
            QRect rect = geometry();
            switch (mouse_press_region_)
            {
            case kMousePositionLeftTop:
                rect.setTopLeft(rect.topLeft() + point_offset);
                break;
            case kMousePositionTop:
                rect.setTop(rect.top() + point_offset.y());
                break;
            case kMousePositionRightTop:
                rect.setTopRight(rect.topRight() + point_offset);
                break;
            case kMousePositionRight:
                rect.setRight(rect.right() + point_offset.x());
                break;
            case kMousePositionRightButtom:
                rect.setBottomRight(rect.bottomRight() + point_offset);
                break;
            case kMousePositionButtom:
                rect.setBottom(rect.bottom() + point_offset.y());
                break;
            case kMousePositionLeftButtom:
                rect.setBottomLeft(rect.bottomLeft() + point_offset);
                break;
            case kMousePositionLeft:
                rect.setLeft(rect.left() + point_offset.x());
                break;
            default:
                break;
            }
            setGeometry(rect);
            last_position_ = event->globalPos();
        }
    }
}

void frameless::mouseReleaseEvent(QMouseEvent *)
{
    left_button_pressed_ = false;
}

void frameless::mousePressEvent(QMouseEvent * event)
{
    if (event->buttons() == Qt::LeftButton) {
        left_button_pressed_ = true;
        last_point_ = pos();
        last_position_ = event->globalPos();
        mouse_press_region_ = GetMouseRegion(event->pos().x(), event->pos().y());
    }
}

void frameless::SetMouseCursor(int x, int y)
{
    Qt::CursorShape cursor;
    int region = GetMouseRegion(x, y);
    switch (region)
    {
    case kMousePositionLeftTop:
    case kMousePositionRightButtom:
        cursor = Qt::SizeFDiagCursor; break;
    case kMousePositionRightTop:
    case kMousePositionLeftButtom:
        cursor = Qt::SizeBDiagCursor; break;
    case kMousePositionLeft:
    case kMousePositionRight:
        cursor = Qt::SizeHorCursor; break;
    case kMousePositionTop:
    case kMousePositionButtom:
        cursor = Qt::SizeVerCursor; break;
    case kMousePositionMid:
        cursor = Qt::ArrowCursor; break;
    default:
        break;
    }
    setCursor(cursor);
}

int frameless::GetMouseRegion(int x, int y)
{
    int region_x = 0, region_y = 0;
    if (x < kMouseRegionLeft)
    {
        region_x = 1;
    }
    else if (x > (width() - kMouseRegionRight))
    {
        region_x = 3;
    }
    else
    {
        region_x = 2;
    }
    if (y < kMouseRegionTop)
    {
        region_y = 1;
    }
    else if (y > (height() - kMouseRegionButtom))
    {
        region_y = 3;
    }
    else
    {
        region_y = 2;
    }
    return region_y * 10 + region_x;
}

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_frameless.h"
#include <QMouseEvent>

class frameless : public QMainWindow
{
    Q_OBJECT

public:
    frameless(QWidget *parent = Q_NULLPTR);

private:
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *);
    void mousePressEvent(QMouseEvent *event);
    /**
    * @brief  根据鼠标的设置鼠标样式,用于拉伸
    */
    void SetMouseCursor(int x, int y);
    /**
    * @brief  判断鼠标的区域,用于拉伸
    */
    int GetMouseRegion(int x, int y);
private:
    /**
    * @brief  鼠标区域,将窗口分成了9个部分
    */
    enum MousePosition
    {
        kMousePositionLeftTop = 11,
        kMousePositionTop = 12,
        kMousePositionRightTop = 13,
        kMousePositionLeft = 21,
        kMousePositionMid = 22,
        kMousePositionRight = 23,
        kMousePositionLeftButtom = 31,
        kMousePositionButtom = 32,
        kMousePositionRightButtom = 33,
    };

    Ui::framelessClass      ui;
    QPoint                  last_point_;             //记录放大之前的位置
    QPoint                  last_position_;          //窗口上一次的位置
    bool                    left_button_pressed_;   //左键按下

    int                     mouse_press_region_ = kMousePositionMid; //鼠标点击的区域
};
 

现在已经可以实现拉伸了,但是我们会发现鼠标样式的改变不灵敏,解决这个问题很简单

构造函数里添加如下代码

    //设置鼠标追踪
    setMouseTracking(true);

设置之前,mouseMoveEvent只会在有按键按下的时候触发,设置这个函数之后,mouseMoveEvent会触发的更频繁,能够进准的监控鼠标的移动。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值