欢迎访问宙启技术站
智能推送

Qt如何实现通用无边框拖动拉伸

发布时间:2023-05-15 01:26:49

Qt 是一个跨平台的 C++ 应用程序开发框架,提供了丰富的工具和函数库,支持开发各种类型的应用程序。在 Qt 的窗口应用程序中,通常需要实现窗口的拖动和拉伸功能,来满足用户界面的交互需求。本文将介绍如何使用 Qt 实现通用无边框拖动拉伸功能。

一、无边框窗口的实现

在实现无边框拖动拉伸功能之前,需要先了解如何实现无边框窗口。Qt 提供了一个 QWidget 类,可以用来实现窗口的基本功能,但默认情况下该类自带边框。为了实现无边框窗口,需要将 QWidget 类中的边框样式设置为 Qt::FramelessWindowHint。

setWindowFlags(Qt::FramelessWindowHint);

以上代码将边框样式设置为无边框。使用该方法创建的窗口将没有标题栏、任务栏和边框,用户需要自行实现这些和相关的功能。下面将介绍如何使用 Qt 实现通用无边框拖动拉伸功能。

二、窗口的拖动功能实现

拖动窗口功能是窗口应用程序中最基本的交互功能,用户可以通过拖动窗口中的空白区域来移动整个窗口。为了实现该功能,需要处理窗口鼠标按下、移动和释放事件。

首先,在 QWidget 类中重载 mousePressEvent 函数,该函数会在鼠标按下事件发生时被调用。在该函数中,需要记录下鼠标按下的位置,以便后续计算窗口的偏移量。

void MyWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_offset = event->globalPos() - this->frameGeometry().topLeft();
        event->accept();
    }
}

接下来,在 QWidget 类中重载 mouseMoveEvent 函数,该函数会在鼠标移动事件发生时被调用。在该函数中,需要计算出鼠标移动的距离,以及窗口目前的位置。然后,根据新的位置计算出窗口需要移动的位置,并将窗口移动到该位置。

void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        QPoint pos = event->globalPos() - m_offset;
        move(pos);
        event->accept();
    }
}

最后,在 QWidget 类中重载 mouseReleaseEvent 函数,该函数会在鼠标释放事件发生时被调用。在该函数中,需要清空记录的偏移量。

void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
    m_offset = QPoint();
    event->accept();
}

现在,用户可以通过拖动窗口中的空白区域来移动整个窗口。

三、窗口的拉伸功能实现

窗口的拉伸功能是窗口应用程序的另一个常用交互功能,用户可以通过拉伸边框来调整窗口的大小。为了实现该功能,需要处理窗口的鼠标按下、移动和释放事件。

首先,在 QWidget 类中重载 mousePressEvent 函数,该函数会在鼠标按下事件发生时被调用。在该函数中,需要判断用户是点击了窗口的哪个边框,并记录下该边框的位置和大小。

void MyWidget::mousePressEvent(QMouseEvent *event)
{
    int borderWidth = 5;
    int xPos = event->x();
    int yPos = event->y();

    // 判断是否点击了左边框
    if (xPos <= borderWidth) {
        m_leftPressed = true;
        m_offset.setX(this->width() - xPos);
        event->accept();
    }
    // 判断是否点击了右边框
    else if (xPos >= this->width() - borderWidth) {
        m_rightPressed = true;
        m_offset.setX(xPos);
        event->accept();
    }
    // 判断是否点击了上边框
    if (yPos <= borderWidth) {
        m_topPressed = true;
        m_offset.setY(this->height() - yPos);
        event->accept();
    }
    // 判断是否点击了下边框
    else if (yPos >= this->height() - borderWidth) {
        m_bottomPressed = true;
        m_offset.setY(yPos);
        event->accept();
    }
}

接下来,在 QWidget 类中重载 mouseMoveEvent 函数,该函数会在鼠标移动事件发生时被调用。在该函数中,需要计算出鼠标移动的距离和移动的方向,并根据方向计算出窗口需要移动的位置和大小,然后对窗口进行移动或调整大小操作。

void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (m_leftPressed) {
        QPoint pos = event->globalPos() - m_offset;
        QSize size = QSize(this->x() - pos.x() + this->width(), this->height());
        resize(size);
        move(pos);
        event->accept();
    }
    else if (m_rightPressed) {
        QPoint pos = event->globalPos() - m_offset;
        QSize size = QSize(pos.x() - this->x(), this->height());
        resize(size);
        event->accept();
    }
    else if (m_topPressed) {
        QPoint pos = event->globalPos() - m_offset;
        QSize size = QSize(this->width(), this->y() - pos.y() + this->height());
        resize(size);
        move(pos);
        event->accept();
    }
    else if (m_bottomPressed) {
        QPoint pos = event->globalPos() - m_offset;
        QSize size = QSize(this->width(), pos.y() - this->y());
        resize(size);
        event->accept();
    }
}

最后,在 QWidget 类中重载 mouseReleaseEvent 函数,该函数会在鼠标释放事件发生时被调用。在该函数中,需要清空记录的状态。

void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
    m_leftPressed = false;
    m_rightPressed = false;
    m_topPressed = false;
    m_bottomPressed = false;
    event->accept();
}

现在,用户可以通过拖动窗口的边框来调整窗口的大小。需要注意的是,在计算窗口需要移动的位置和大小时,需要使用全局坐标来计算。否则,窗口在移动或调整大小时会出现不对齐的问题。

四、总结

本文介绍了如何使用 Qt 实现通用的无边框拖动拉伸功能。实现该功能需要处理窗口鼠标按下、移动和释放事件,以及计算窗口需要移动的位置和大小。需要注意的是,在计算窗口需要移动的位置和大小时需要使用全局坐标来计算。实现该功能后,用户可以通过拖动窗口的空白区域或边框来移动或调整窗口的大小。