Qt实现 可移动的无边框窗口

日常开发中,因为需要自定义标题栏来实现更好的效果,所以经常需要隐藏窗口自带的标题栏。

在Qt中,通过setWindowFlags(Qt::FramelessWindowHint)函数对当前窗口设置无边框,但是这样存在一个问题,

就是窗口无法被鼠标拖动了,所以这时候就需要重写一下事件,来实现窗口的移动。

先看代码实现:

#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->setWindowFlags(Qt::FramelessWindowHint);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mouseMoveEvent(QMouseEvent *e)
{
    QPoint y = e->globalPos();
    QPoint x= y - m_zPos;
    this->move(x);
}

void Widget::mousePressEvent(QMouseEvent *e)
{
    QPoint y = e->globalPos();
    QPoint x = this->geometry().topLeft();
    m_zPos = y-x;
}

void Widget::mouseReleaseEvent(QMouseEvent *e)
{
    m_zPos = QPoint();
}


void Widget::on_btn_clos_clicked()
{
    this->close();
}

void Widget::on_btn_max_clicked()
{
    if(this->isMaximized())
    {
        this->showNormal();
        return;
    }
    this->showMaximized();
}

void Widget::on_btn_min_clicked()
{
    this->showMinimized();
}

我们需要在头文件中重写以下3个鼠标事件,

//鼠标移动事件
void mouseMoveEvent(QMouseEvent *event);

//鼠标释放事件
void mouseReleaseEvent(QMouseEvent *event);

//鼠标按下事件
void mousePressEvent(QMouseEvent *event);

通过鼠标按下,进入mousePressEvent函数,获取到当前相对窗口的坐标,

当鼠标拖动时,在mouseMoveEvent会进行响应,然后通过调用move函数,来实现窗口的移动。

当拖动结束后,鼠标释放,不再按下,会进入mouseReleaseEvent,这时候将上次鼠标按下的坐标赋值置空。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt实现边框窗口移动、拉伸、缩放需要使用QWidget的一些事件和函数。具体实现步骤如下: 1.设置无边框窗口 在QWidget中通过设置setWindowFlags函数来实现边框窗口。例如: ``` setWindowFlags(Qt::FramelessWindowHint); ``` 2.移动窗口 在QWidget中通过重写鼠标按下、移动、释放事件来实现窗口移动。例如: ``` void mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_isPressed = true; m_startPoint = event->globalPos() - this->geometry().topLeft(); } } void mouseMoveEvent(QMouseEvent *event) { if (m_isPressed) { this->move(event->globalPos() - m_startPoint); } } void mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_isPressed = false; } } ``` 其中m_isPressed记录鼠标左键是否按下,m_startPoint记录鼠标按下时的位置与窗口左上角的距离,this->move函数实现窗口移动。 3.拉伸窗口 在QWidget中通过重写鼠标按下、移动、释放事件来实现窗口拉伸。例如: ``` void mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_isPressed = true; m_startPoint = event->globalPos(); m_startGeometry = this->geometry(); } } void mouseMoveEvent(QMouseEvent *event) { if (m_isPressed) { QPoint diff = event->globalPos() - m_startPoint; if (m_resizeDir == RESIZE_DIR_LEFT_TOP) { this->setGeometry(m_startGeometry.x() + diff.x(), m_startGeometry.y() + diff.y(), m_startGeometry.width() - diff.x(), m_startGeometry.height() - diff.y()); } else if (m_resizeDir == RESIZE_DIR_RIGHT_TOP) { this->setGeometry(m_startGeometry.x(), m_startGeometry.y() + diff.y(), m_startGeometry.width() + diff.x(), m_startGeometry.height() - diff.y()); } else if (m_resizeDir == RESIZE_DIR_LEFT_BOTTOM) { this->setGeometry(m_startGeometry.x() + diff.x(), m_startGeometry.y(), m_startGeometry.width() - diff.x(), m_startGeometry.height() + diff.y()); } else if (m_resizeDir == RESIZE_DIR_RIGHT_BOTTOM) { this->setGeometry(m_startGeometry.x(), m_startGeometry.y(), m_startGeometry.width() + diff.x(), m_startGeometry.height() + diff.y()); } } } void mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_isPressed = false; } } ``` 其中m_isPressed记录鼠标左键是否按下,m_startPoint记录鼠标按下时的位置,m_startGeometry记录窗口拉伸前的位置和大小,m_resizeDir记录拉伸方向(左上、右上、左下、右下),this->setGeometry函数实现窗口拉伸。 4.缩放窗口 在QWidget中通过重写wheelEvent事件来实现窗口缩放。例如: ``` void wheelEvent(QWheelEvent *event) { QPoint pos = event->pos(); if (event->delta() > 0) { this->resize(this->width() * 1.2, this->height() * 1.2); } else { this->resize(this->width() * 0.8, this->height() * 0.8); } QPoint newPos = this->mapFromGlobal(this->mapToGlobal(pos)); QPoint diff = newPos - pos; this->move(this->x() - diff.x(), this->y() - diff.y()); } ``` 其中event->delta()为正表示向上滚动,为负表示向下滚动,this->resize函数实现窗口缩放,this->mapFromGlobal和this->mapToGlobal函数用于将鼠标位置从全局坐标系转换为窗口坐标系,diff记录窗口缩放前后鼠标位置的差值,this->move函数实现窗口位置的调整。 以上就是在Qt实现边框窗口移动、拉伸、缩放的方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值