扁平窗口实现(一) 无边框可拖拽控件

扁平窗口实现之无边框可拖拽控件

开发步骤

  • QWidget去标题栏,变成无边框窗口
  • 重写鼠标事件,实现可拖拽移动

QWidget去标题栏

这个步骤比较简单,调用setWindowFlag(),然后设置Qt::FramelessWindowHint枚举值就可以实现扁平化,当然,如果需要有很窗口状态需要设置可以使用setWindowFlags()然后将多个枚举变量用|将状态合并。

如果是自定义widget控件可以直接在初始化父类时直接在初始化列表中设置状态,代码如下:

// .h
namespace jq {

    class JQFlatBase
            : public QWidget {
    public:
        explicit JQFlatBase(QWidget* _parent = nullptr);
        ~JQFlatBase() override;
    };

} 

// .cpp
namespace jq {
    JQFlatBase::~JQFlatBase() {

    }
    JQFlatBase::JQFlatBase(QWidget *_parent)
        : QWidget(_parent, Qt::FramelessWindowHint){

    }
}

可设置的状态标志有很多可以在帮助文档中搜索Qt::WindowType查看,大致如下:

在这里插入图片描述

重写鼠标信号

没有标题栏的窗口是无法移动的因此需要进行重写鼠标事件,需要重写的鼠标事件包括:mousePressEvent(QMouseEvent *event)鼠标按下mouseReleaseEvent(QMouseEvent *event)鼠标松开mouseMoveEvent(QMouseEvent *event)鼠标移动

定义一个标志位变量在mousePressEvent(QMouseEvent *event)mouseReleaseEvent(QMouseEvent *event)中记录是否鼠标左键被点击(一般是点中鼠标左键移动窗口)。

定义一个点变量在mousePressEvent(QMouseEvent *event)中记录鼠标按下的位置。

结合标志位和记录的最后点击位置,在mouseMoveEvent(QMouseEvent *event)中计算移动的距离,通过move(const QPoint &)更新窗口位置,代码如下:

// .h
namespace jq {

    class JQFlatBase
            : public QWidget {
    public:
        explicit JQFlatBase(QWidget* _parent = nullptr);
        ~JQFlatBase() override;

    protected:
        void mousePressEvent(QMouseEvent *event) override;
        void mouseReleaseEvent(QMouseEvent *event) override;
        void mouseMoveEvent(QMouseEvent *event) override;

    private:
        bool                            is_mouse_press_;
        QPoint                          last_mouse_point_;
    };
}

// .cpp
namespace jq {
    JQFlatBase::~JQFlatBase() {

    }

    JQFlatBase::JQFlatBase(QWidget *_parent)
        : QWidget(_parent, Qt::FramelessWindowHint)
        , is_mouse_press_(false)
        , last_mouse_point_(0, 0) {

    }

    void JQFlatBase::mousePressEvent(QMouseEvent *event) {
        if (event->button() != Qt::LeftButton) {
            /* 不是鼠标左键则退出 */
            return QWidget::mousePressEvent(event);
        }
        is_mouse_press_ = true;
        last_mouse_point_ = event->pos();
    }

    void JQFlatBase::mouseReleaseEvent(QMouseEvent *event) {
        if (event->button() != Qt::LeftButton) {
            /* 不是鼠标左键则退出 */
            return QWidget::mouseReleaseEvent(event);
        }
        is_mouse_press_ = false;
    }

    void JQFlatBase::mouseMoveEvent(QMouseEvent * event) {
        if (is_mouse_press_)
            move(event->pos() - last_mouse_point_ + pos());
        else
            return QWidget::mouseMoveEvent(event);
    }
} 

计算原理:

  • 记录鼠标最后一次点击时,相对于控件本身位置点。
  • 鼠标移动中计算
    • 鼠标档期位置(相对控件本身) - 记录的点的位置 = 移动的距离
    • 新窗口位置 = 移动的距离 + 当前窗口位置(使用控件本身的pos()函数获取)

由于都是相对于控件本身的位置做计算,因此,每次移动距离的点的计算结果基本是(±1~2, ±1~2)

件本身) - 记录的点的位置 = 移动的距离

  • 新窗口位置 = 移动的距离 + 当前窗口位置(使用控件本身的pos()函数获取)

由于都是相对于控件本身的位置做计算,因此,每次移动距离的点的计算结果基本是(±1~2, ±1~2)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值