【Qt】主窗体设置无边框拖动修改尺寸


前言

主窗体设置无边框无法拖动修改尺寸,可以和自定义标题栏一样重写,搭配自定义标题栏一起使用,这里写的QMainWindow,如果是无边框QDialog,直接把QMainWindow对应的改为QDialog即可。


提示:以下是本篇文章正文内容,下面案例可供参考

1.头文件

代码如下(示例):

#ifndef VARIABLESIZEMAINWINDOW_H
#define VARIABLESIZEMAINWINDOW_H

#include <QMainWindow>
#include <QObject>
#include <QMouseEvent>
#ifdef Q_OS_WIN
#include "Windows.h"
#endif

class VariableSizeMainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit VariableSizeMainWindow(QWidget *parent = nullptr);
    ~VariableSizeMainWindow();
    enum Direction { DOWN = 0, LEFT, RIGHT, LEFTBOTTOM, RIGHTBOTTOM, NONE };
public:
    void initData();
    QRectF boundingRect() const;
    QRectF leftBorder() const;
    QRectF rightBorder() const;
    QRectF topBorder() const;
    QRectF bottomBorder() const;
    void setMousePressCursorShape(const QPointF& pt);

protected:
    bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#ifdef Q_OS_WIN
    bool winEvent(MSG *message, long *result);
#endif

private:
    qreal       borderSize;                                             //边界尺寸
    bool        isLeftPressDown;                                        //判断左键是否按下
    Direction   dir;                                                    //窗口大小改变时,记录改变方向
    QDateTime	dateTimeLastModify;

private:
    void mousePressEvent(QMouseEvent *event);                           //鼠标点击事件
    void mouseMoveEvent(QMouseEvent *event);                            //鼠标移动事件
    void mouseReleaseEvent(QMouseEvent *event);                         //鼠标离开事件
    bool eventFilter(QObject *obj, QEvent *event);                      //事件过滤器
};

#endif // VARIABLESIZEMAINWINDOW_H


2.函数实现

代码如下(示例):

#include "variablesizemainwindow.h"

VariableSizeMainWindow::VariableSizeMainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    initData();
}

VariableSizeMainWindow::~VariableSizeMainWindow()
{

}

void VariableSizeMainWindow::initData()
{
    //设置窗体标题栏隐藏
    setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint| Qt::WindowMinimizeButtonHint| Qt::WindowMaximizeButtonHint);
    //设置接受拖拽事件
    setAcceptDrops(true);
    this->setMouseTracking(true);
    this->setAttribute(Qt::WA_Hover, true);
    this->installEventFilter(this);
    borderSize = 10;
    isLeftPressDown = false;
    this->dir = NONE;
    //#if _DEBUG
        startTimer(1000);
    //#endif
}

//主窗体实现函数
bool VariableSizeMainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    if (eventType == "windows_generic_MSG") {
#ifdef Q_OS_WIN
        MSG *msg = static_cast<MSG *>(message);
        //qDebug() << TIMEMS << msg->message;
        if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
            //系统休眠的时候自动最小化可以规避程序可能出现的问题
            this->showMinimized();
            qDebug()<<"系统休眠中,最小化窗口!";
        } else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
            //休眠唤醒后自动打开
            this->showNormal();
            qDebug()<<"系统已唤醒,恢复窗口!";
        }
#endif
    } else if (eventType == "NSEvent") {
#ifdef Q_OS_MACOS
#endif
    }
    return false;
}

#ifdef Q_OS_WIN
bool VariableSizeMainWindow::winEvent(MSG *message, long *result)
{
    return nativeEvent("windows_generic_MSG", message, result);
}
#endif

void VariableSizeMainWindow::mousePressEvent(QMouseEvent *event)
{
    isLeftPressDown = true;
    setMousePressCursorShape(event->pos());
    if (dir != NONE) {
        this->mouseGrabber();
    }
    qDebug() << "dir = " << dir;
}

QRectF VariableSizeMainWindow::boundingRect() const
{
    return QRectF(QPointF(0, 0), geometry().size());
}

QRectF VariableSizeMainWindow::leftBorder() const
{
    return QRectF(0, 0, 3, boundingRect().height());
}

QRectF VariableSizeMainWindow::rightBorder() const
{
    return QRectF(boundingRect().width() - borderSize, 0, borderSize, boundingRect().height());
}

QRectF VariableSizeMainWindow::topBorder() const
{
    return QRectF(0, 0, boundingRect().width(), borderSize);
}

QRectF VariableSizeMainWindow::bottomBorder() const
{
    return QRectF(0, boundingRect().height() - borderSize, boundingRect().width(), borderSize);
}

void VariableSizeMainWindow::setMousePressCursorShape(const QPointF& pt)
{
    QCursor cursor = Qt::ArrowCursor;
    if (rightBorder().contains(pt) && bottomBorder().contains(pt))    // 右下角
    {
        dir = RIGHTBOTTOM;
        cursor = Qt::SizeFDiagCursor;
    }
    else if (leftBorder().contains(pt) && bottomBorder().contains(pt))      // 左下角
    {
        dir = LEFTBOTTOM;
        cursor = Qt::SizeBDiagCursor;
    }
    else if (rightBorder().contains(pt))        // 右边
    {
        dir = RIGHT;
        cursor = Qt::SizeHorCursor;
    }
    else if (bottomBorder().contains(pt))       // 底边
    {
        dir = DOWN;
        cursor = Qt::SizeVerCursor;
    }
    else if (leftBorder().contains(pt))         // 左边
    {
        dir = LEFT;
        cursor = Qt::SizeHorCursor;
    }
    else
    {
        dir = NONE;
        cursor = Qt::ArrowCursor;
    }
    setCursor(cursor);
}
void VariableSizeMainWindow::mouseMoveEvent(QMouseEvent *event)
{
    QPoint gloPoint = event->globalPos();
    QRect rect = this->rect();
    QPoint tl = mapToGlobal(rect.topLeft());
    QPoint rb = mapToGlobal(rect.bottomRight());
    if (!isLeftPressDown) {
        setMousePressCursorShape(gloPoint);
    }
    else {

        if (dir != NONE) {
            QRect rMove(tl, rb);

            switch (dir) {
            case LEFT:
                if (rb.x() - gloPoint.x() <= this->minimumWidth())
                    rMove.setX(tl.x());
                else
                    rMove.setX(gloPoint.x());
                break;
            case RIGHT:
                rMove.setWidth(gloPoint.x() - tl.x());
                break;
            case DOWN:
                if((this->y() + gloPoint.y() - tl.y()) <= QApplication::desktop()->availableGeometry().height())
                    rMove.setHeight(gloPoint.y() - tl.y());
                break;
            case LEFTBOTTOM:
                    if (rb.x() - gloPoint.x() <= this->minimumWidth())
                        rMove.setX(tl.x());
                    else
                        rMove.setX(gloPoint.x());
                    if((this->y() + gloPoint.y() - tl.y()) <= QApplication::desktop()->availableGeometry().height())
                        rMove.setHeight(gloPoint.y() - tl.y());
                break;
            case RIGHTBOTTOM:
                    rMove.setWidth(gloPoint.x() - tl.x());
                    if((this->y() + gloPoint.y() - tl.y()) <= QApplication::desktop()->availableGeometry().height())
                        rMove.setHeight(gloPoint.y() - tl.y());
                break;
            default:
                break;
            }
            this->setGeometry(rMove);
        }
    }
    QMainWindow::mouseMoveEvent(event);
}

void VariableSizeMainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    isLeftPressDown = false;
    if (dir != NONE) {
        dir = NONE;
        this->releaseMouse();
        this->setCursor(QCursor(Qt::ArrowCursor));
    }
}

bool VariableSizeMainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == this)
    {
        if (event->type() == QMouseEvent::HoverEnter)
        {
            QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
            setMousePressCursorShape(_mouseEvent->pos());
        }
        if (event->type() == QMouseEvent::HoverMove)
        {
            QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
            if (!isLeftPressDown)
                setMousePressCursorShape(_mouseEvent->pos());
        }
        if (event->type() == QMouseEvent::HoverLeave)
        {
            unsetCursor();
        }
    }
    return QMainWindow::eventFilter(obj, event);
}


3.使用

.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "variablesizemainwindow.h"
namespace Ui {
class MainWindow;
}

class MainWindow : public VariableSizeMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    static MainWindow *getInstance() {
            static QMutex mutex;
            if (!instance) {
                QMutexLocker locker(&mutex);
                if (!instance) {
                    instance = new MainWindow;
                }
            }
            return instance;
        }
private:
    Ui::MainWindow *ui;
    static MainWindow *instance;
};

#endif // MAINWINDOW_H

.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow *MainWindow::instance = Q_NULLPTR;
MainWindow::MainWindow(QWidget *parent) :
    VariableSizeMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

}

4.效果展示

请添加图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值