qt无边框窗口移动

三种方法实现qt无边框窗口移动

方法一:

通过鼠标点击事件和鼠标移动事件来实现无边框窗口的移动。

#include <QApplication>
#include<QWidget>
#include<QEvent>
#include<QMouseEvent>
class Widget:public QWidget
{
public:
    Widget(QWidget* parent=nullptr):QWidget(parent)
    {
        this->resize(640,480);
        this->setWindowFlag(Qt::FramelessWindowHint,true);//设置窗口无边框
    }
    ~Widget()
    {

    }
protected:
    //鼠标点击事件
    void mousePressEvent(QMouseEvent* ev)override
    {
        if(ev->button()==Qt::LeftButton)//这里判断,是否是鼠标左键按下,只有左键按下窗口才能移动
        {
            pos=ev->pos();//用成员变量记录下按下左键时鼠标的坐标
        }
    }
    //鼠标移动事件
    void mouseMoveEvent(QMouseEvent*ev)override
    {
        if(ev->buttons()==Qt::LeftButton)//注意,这里用的是buttons,因为buttons里存储了之前的按键信息
        {
            int x,y;
            x=ev->pos().x()-pos.x();
            y=ev->pos().y()-pos.y();
            this->move(this->x()+x,this->y()+y);
        }
    }

protected:
    QPoint pos;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

方法二:

同过事件分发函数来处理。

在此之前我们要明白一点,就是事件分发函数,是处理所有事件的总函数,函数原型为 bool event(QEvent *ev); 返回值为bool类型,用于判断该事件是否完成,如果完成返回true,反之返回false.

这里我们主要通过时间的类型来判断,通过方法一我们得知,主要用到的事件就是mousePressEvent和mouseMoveEvent,所以这里我们就可以自定义这两个事件。

#include <QApplication>
#include<QWidget>
#include<QEvent>
#include<QMouseEvent>
class Widget:public QWidget
{
public:
    Widget(QWidget* parent=nullptr):QWidget(parent)
    {
        this->resize(640,480);
        this->setWindowFlag(Qt::FramelessWindowHint,true);//设置窗口无边框
    }
    ~Widget()
    {

    }
protected:
    bool event(QEvent* ev) override
    {
        switch (ev->type()) //这里更具事件的类型来判断,
        {
        case QEvent::Type::MouseButtonPress:
        {
            QMouseEvent* e=static_cast<QMouseEvent*>(ev);//因为后续要访问鼠标的按键类型和位置,而父类QEvent是没有这些成员的,所以要强转
            if(e->button()==Qt::LeftButton)
            {
                pos=e->pos();//记录此时的鼠标左键点击位置
            }
        }
            break;
        case QEvent::Type::MouseMove:
        {
             QMouseEvent* e=static_cast<QMouseEvent*>(ev);//因为后续要访问鼠标的按键类型和位置,而父类QEvent是没有这些成员的,所以要强转
             if(e->buttons()==Qt::LeftButton)
             {
                 int x,y;
                 x=e->pos().x()-pos.x();
                 y=e->pos().y()-pos.y();
                 this->move(this->x()+x,this->y()+y);
             }
        }
            break;
        default:
            break;
        }
        return QWidget::event(ev);//注意,因为event是事件分发的总函数,所以其他的事件仍然用父类中给我们定义好的event函数。
    }

protected:
    QPoint pos;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

方法三:

通过事件过滤器来处理无边框窗口的移动

首先我们要明白自定义事件的发送过程,当我们使用sendEvent或者是postEvent来发送我们自定义的事件的时候,并不是直接发送给对象的,而是有一个过程。

 当我们发送自定义的事件时,首先是先通过QCoreApplication的notify函数来通知这个事件,之后由事件过滤器eventFilter(前提是有事件过滤器,如果没有则跳过此步骤)对该事件进行过滤,过滤后,再交给enent事件分发函数,最后在由分发函数来选选择由哪个事件处理函数来处理该事件。

所谓的事件过滤器,就是我们提前对传送来的事件进行我们自定义的处理

#include <QApplication>
#include<QWidget>
#include<QEvent>
#include<QMouseEvent>
class Widget:public QWidget
{
public:
    Widget(QWidget* parent=nullptr):QWidget(parent)
    {
        this->resize(640,480);
        this->setWindowFlag(Qt::FramelessWindowHint,true);//设置窗口无边框
        //安装事件过滤器
        installEventFilter(this);//根据我们自定义的事件过滤器所在的对象来填写,如我们重写的事件过滤器就是Widget的成员函数,所以填写this即可
    }
    ~Widget()
    {

    }
protected:
    //自定义事件过滤器
bool eventFilter(QObject *obj,QEvent* ev)override
{

    if(ev->type()==QEvent::Type::MouseButtonPress)//判断是否有鼠标点击事件
    {
        QMouseEvent* e=static_cast<QMouseEvent*> (ev);
        if(e->button()==Qt::LeftButton)//判断是否是左键点击
        {

            pos=e->pos();
        }
    }
    else if(ev->type()==QEvent::Type::MouseMove)//判断是否有鼠标移动事件
    {
        QMouseEvent* e=static_cast<QMouseEvent*> (ev);
        if(e->buttons()==Qt::LeftButton)//判断历史点击是否是左键点击
        {
            int x,y;
            x=e->pos().x()-pos.x();
            y=e->pos().y()-pos.y();
            this->move(this->x()+x,this->y()+y);
        }
    }
}
protected:
    QPoint pos;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

通过以上方法,我们不能发现,无边框移动的本质算法是一致的,只是我们有多种实现的方法,在实际开发中,我们也可以根据当时的实际情况来选择不同的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码商道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值