【自制软件】PDF学习宝-开发日记3--鼠标拖动窗口

262 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情


📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!


鼠标拖动窗口

前言

由于我去掉了原始的标题栏采用自定义的标题栏,原始标题栏自带的窗口拖动功能也就不能用了。通常桌面软件或浏览器都可以鼠标点击标题栏(最上方的边框)按住不放移动鼠标进行拖动。

本节就来实现一下与原始标题栏的窗口拖动功能不同的拖动窗口功能。自定义的窗口拖动功能可以识别窗口是否最大化,在窗口最大化的状态下无法拖动。并且在还原状态下无论拖动到哪个位置,再次还原窗口会回到初始位置。

鼠标拖动窗口的实现

在Qt中一般涉及鼠标功能的很多都是QMouseEvent类的鼠标事件。本节想要实现的鼠标拖拽功能就是典型的鼠标事件。利用QMouseEvent类可以知道鼠标左键还是右键按下,双击还是单击,鼠标的位置在哪等等一系列鼠标的操作。

通常用重定义鼠标事件处理函数来进行一些自定义的操作。主要使用如下几个函数:

mousePressEvent鼠标左键按下时触发的处理函数,当鼠标左键按下意味着拖拽开始,这里可以使用此函数记录下鼠标位置和窗口的位置。

mouseReleaseEvent鼠标左键松开时触发的处理函数,当鼠标左键松开就意味着拖拽停止。

mouseMoveEvent鼠标移动时触发的处理函数,鼠标在按下时移动坐标发生变化,被拖动的窗口坐标也跟着一起发生变化就会产生拖动的效果。

在widget.h头文件中添加:

protected:
    //重写后检测到鼠标按下左键时记录按下的point的坐标以及拖拽的窗口的坐标point
    void mousePressEvent(QMouseEvent *event);
    //重写后在鼠标左键放下后判断拖拽结束
    void mouseReleaseEvent(QMouseEvent *event);
    //重写后判断若是在拖动状态,记录鼠标移动的位置差,即目前的位置减去鼠标原来的位置,
    //并将窗口move到窗口的坐标point加上目前的位置差的最新位置
    void mouseMoveEvent(QMouseEvent *event);
    
private:
    bool is_drag = false;               //拖动标志位
    QPoint mouse_start_point;           //鼠标起始位置
    QPoint window_start_point;          //窗口初始位置

在widget.cpp源文件中实现相应函数:

void Widget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton && winFlag == false)
    {
        is_drag = true;
        //获得鼠标的初始位置
        mouse_start_point = event->globalPosition().toPoint();
        //获得窗口的初始位置
        window_start_point = this->frameGeometry().topLeft();
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    //放下左键即停止移动
    if (event->button() == Qt::LeftButton && winFlag == false)
    {
        is_drag = false;
    }
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    //判断是否在拖拽移动
    if (is_drag && winFlag == false)
    {
        //获得鼠标移动的距离
        QPoint move_distance = event->globalPosition().toPoint() - mouse_start_point;
        //改变窗口的位置
        this->move(window_start_point + move_distance);
    }
}

在函数实现过程中,我增加了窗口最大化标志位判断。如果winFlag == false也就是窗口未最大化,则鼠标拖动功能可以使用,否则将无法使用。这样做因为窗口最大化以后再进行拖动会很影响PDF阅读体验。

窗口位置还原

另外一个功能点是还原后的窗口总是回到初始位置。我的做法是先将窗口原始位置进行记录,每次点击还原按钮就将窗口移动到初始位置,以此来实现窗口的位置还原。

在widget.h中添加:

QPoint win_pos;                     //窗口位置

在构造函数中添加:

    //窗口位置
    win_pos = this->pos();

改造最大化/还原按钮响应函数:

void Widget::on_btn_max_clicked()
{
    if(winFlag)
    {        
        setWindowState(Qt::WindowNoState);
        btn_max->setIcon(QIcon(":/images/images/black-zuidahua.svg"));
        winFlag = false;
        this->move(win_pos);//将还原的窗口移动到初始位置
    }else{
        setWindowState(Qt::WindowMaximized);
        btn_max->setIcon(QIcon(":/images/images/black-huanyuan.svg"));
        winFlag = true;
    }
}