qt 无边框窗口拉伸,可能是全网最精简的代码

从CSDN过来的兄弟们有福了,调了2天无私奉献,CPP一共130行,看还有精简的地方吗?

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QRubberBand>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
#define DEFAULT_CURSOR Qt::ArrowCursor
class MainWindow : public QMainWindow
{
    Q_OBJECT
    Q_PROPERTY(int m_borderWidth READ borderWidth WRITE setBorderWidth)
    Q_PROPERTY(bool m_dragEnable READ dragEnable WRITE setDragEnable)
    Q_PROPERTY(bool m_bottomRightResizeEnable READ bottomRightResizeEnable WRITE setBottomRightResizeEnable)
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    enum Edge {
            None = 0x0,
            Left = 0x1,
            Top = 0x2,
            Right = 0x4,
            Bottom = 0x8,
            TopLeft = Top|Left,
            TopRight = Top|Right,
            BottomLeft = Bottom|Left,
            BottomRight = Bottom|Right,
        };
    Q_DECLARE_FLAGS(Edges, Edge)

protected:
    bool eventFilter(QObject *o, QEvent *e) override;
    void leaveEvent(QEvent *event);
    void mousePressEvent(QMouseEvent*e);
    void hoverMoveEvent(QHoverEvent*);
    void mouseReleaseEvent(QMouseEvent*);
private:
    Qt::CursorShape calculateCursorPosition(const QPoint &, const QRect &, Edges &);
    void setBorderWidth(int w) {m_borderWidth = w;}
    int borderWidth() const {return m_borderWidth;}
    void setDragEnable(bool w) {m_dragEnable = w;}
    bool dragEnable() const {return m_dragEnable;}
    void setBottomRightResizeEnable(bool w) {m_bottomRightResizeEnable = w;}
    bool bottomRightResizeEnable() const {return m_bottomRightResizeEnable;}
private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
    void on_pushButton_3_clicked();

private:
    Ui::MainWindow *ui;

    QRect m_startRect;
    bool m_leftButtonPressed;
    Edges m_edgeOnMousePress = Edge::None;
    int m_borderWidth = 6;

    QPoint m_dragPos;
    bool m_dragStart = false,m_dragEnable = true;
    bool m_bottomRightResizeEnable = true;
};

#endif // MAINWINDOW_H

CPP:

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

#include <QMouseEvent>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow),
      m_leftButtonPressed(false),
      m_dragPos(QPoint())
{
    ui->setupUi(this);

    setWindowFlag(Qt::FramelessWindowHint);
    installEventFilter(this);
}

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

bool MainWindow::eventFilter(QObject *o, QEvent *e)
{
    if (e->type()==QEvent::HoverMove && o==this) {
        hoverMoveEvent(static_cast<QHoverEvent*>(e));
        return true;
    }
    return QMainWindow::eventFilter(o, e);
}

void MainWindow::leaveEvent(QEvent *event)
{
    Q_UNUSED(event);
    if (!m_leftButtonPressed)
        unsetCursor();
}

void MainWindow::mousePressEvent(QMouseEvent *e)
{
    if (e->button() & Qt::LeftButton) {
        m_leftButtonPressed = true;
        if (calculateCursorPosition(e->globalPos(), geometry(), m_edgeOnMousePress) != DEFAULT_CURSOR)
            m_startRect = geometry();
        if (this->rect().marginsRemoved(QMargins(borderWidth(), borderWidth(), borderWidth(), borderWidth())).contains(e->pos())) {
            m_dragStart = true;
            m_dragPos = e->pos();
        }
    }
}

void MainWindow::mouseReleaseEvent(QMouseEvent *e)
{
    if (e->button() & Qt::LeftButton) {
        m_leftButtonPressed = false;
        m_dragStart = false;
        if(!m_edgeOnMousePress.testFlag(Edge::None))
            unsetCursor();
    }
}

void MainWindow::hoverMoveEvent(QHoverEvent *e)
{
    Edges currentEdge = Edge::None;
    static bool _cursorchanged = false;

    if (this->isFullScreen() || this->isMaximized()) {

        // 一般不来这里,除非拖拉同时按快捷键最大化
        if (_cursorchanged){
            unsetCursor();
            _cursorchanged = false;
        }
        return;
    }
    if(!m_leftButtonPressed){
        auto shape = calculateCursorPosition(mapToGlobal( e->pos() ), geometry(), currentEdge);
        if (!currentEdge.testFlag(Edge::None)){
            setCursor(shape);
            _cursorchanged = true;
        }else if (_cursorchanged) {
            unsetCursor();
            _cursorchanged = false;
        }
    }else{
        if (m_dragStart) {
            move(geometry().topLeft() + (e->pos() - m_dragPos));
        }else if (!m_edgeOnMousePress.testFlag(Edge::None)) {
            auto curPos = mapToGlobal( e->pos() );
            if(m_edgeOnMousePress&(Edge::Top))
                m_startRect.setTop(curPos.y());
            if(m_edgeOnMousePress&(Edge::Bottom))
                m_startRect.setBottom(curPos.y());
            if(m_edgeOnMousePress&(Edge::Left))
                m_startRect.setLeft(curPos.x());
            if(m_edgeOnMousePress&(Edge::Right))
                m_startRect.setRight(curPos.x());
            QTimer::singleShot(0,this,[=](){
                setGeometry(m_startRect);
            });
        }
    }
}

#define EDGE_RET2(rect,pos,out,edg,cursor) do{if(rect.contains(pos,true)){out=edg;return cursor;}}while(0)
Qt::CursorShape MainWindow::calculateCursorPosition(const QPoint &pos, const QRect &framerect, Edges &_edge)
{
    QRect recL(framerect.x(),framerect.y()+m_borderWidth,m_borderWidth,framerect.height()-2*m_borderWidth);
    EDGE_RET2(recL,pos,_edge,Edge::Left,Qt::SizeHorCursor);
    QRect recR(framerect.right()-m_borderWidth,framerect.y()+m_borderWidth,m_borderWidth,framerect.height()-2*m_borderWidth);
    EDGE_RET2(recR,pos,_edge,Edge::Right,Qt::SizeHorCursor);
    QRect recB(framerect.x()+m_borderWidth,framerect.bottom()-m_borderWidth,framerect.width() - 2*m_borderWidth,m_borderWidth);
    EDGE_RET2(recB,pos,_edge,Edge::Bottom,Qt::SizeVerCursor);
    QRect recT(framerect.x()+m_borderWidth,framerect.y(),framerect.width() - 2*m_borderWidth,m_borderWidth);
    EDGE_RET2(recT,pos,_edge,Edge::Top,Qt::SizeVerCursor);

    QRect recBL(framerect.x(),framerect.bottom()-m_borderWidth,m_borderWidth,m_borderWidth);
    EDGE_RET2(recBL,pos,_edge,Edge::BottomLeft,Qt::SizeBDiagCursor);
    if(m_bottomRightResizeEnable){
        QRect recBR(framerect.right()-m_borderWidth,framerect.bottom()-m_borderWidth,m_borderWidth,m_borderWidth);
        EDGE_RET2(recBR,pos,_edge,Edge::BottomRight,Qt::SizeFDiagCursor);
    }
    QRect recTR(framerect.right()-m_borderWidth,framerect.y(),m_borderWidth,m_borderWidth);
    EDGE_RET2(recTR,pos,_edge,Edge::TopRight,Qt::SizeBDiagCursor);
    QRect recTL(framerect.x(),framerect.y(),m_borderWidth,m_borderWidth);
    EDGE_RET2(recTL,pos,_edge,Edge::TopLeft,Qt::SizeFDiagCursor);
    _edge = Edge::None;
    return DEFAULT_CURSOR;
}


void MainWindow::on_pushButton_clicked()
{
    resize(400,300);
}

void MainWindow::on_pushButton_2_clicked()
{
    static bool isMax = true;
    if(isMax)
        showMaximized();
    else
        showNormal();
    isMax = !isMax;
}

void MainWindow::on_pushButton_3_clicked()
{
    close();
}


实现是实现了,不过呢,用原生的resize / move / setGeometry 函数频繁了会导致边缘抖动,这个应该是QT内部没有做好。

要解决这个问题,有2个方法,请看下篇文章。

本文为3YL原创,转载无需联系,但请注明来自labisart.com。

原创文章不易,如果觉得有帮助,可打赏或点击右侧广告支持:

查看打赏记录

发表评论请遵守党国法律!后台审核后方可显示!
  • 最新评论
  • 总共0条评论
  • Blog v1.1© 2024 labisart.com 版权所有 | 联系:labartwork@163.com