Qt源码分享(一)-- 圆角+阴影+可移动+大小可变

  1. Qt源码分享(一)– 圆角+阴影+可移动+大小可变

Qt源码分享(一)– 圆角+阴影+可移动+大小可变

关注微信公众号在菜单栏获取源码

image

由于自己项目的需要,主界面需要实现圆角+阴影+可移动+拖拽可变大小。一看到这样的功能,立马就开始百度。结果百度了快一天都没有找到合适的,虽然能够实现圆角或者阴影的,但是实现的方式总觉得不太合适。最后还是高人赵哥把源码给我了,我又在网络上搜索了一番加上拖拽可变大小的功能。

好,我们先看下效果:
image

为了对原作者的尊重,头文件的作者我就保留了下。

拖拽可变大小我是参考这里的:https://www.cnblogs.com/xufeiyang/p/3313104.html

头文件的实现:

/*!
 * @file     mainwindow.h
 * @author   ZhaoYanbo
 * @date     2019-10-29
 * @details  ...
 * @version  v1.0.0
 */
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QDialog>
#include <QWidget>

class MainWindow : public QWidget
{
    Q_OBJECT

enum Direction{
    UP = 0,
    DOWN,
    LEFT,
    RIGHT,
    LEFTTOP,
    LEFTBOTTOM,
    RIGHTBOTTOM,
    RIGHTTOP,
    NONE
};

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public:    
    void SetResizeable(bool isResize);
    bool IsResizeable() const;

    void SetRadius(bool radius);
    int GetRadius() const;

protected:
    void resizeEvent(QResizeEvent *) override;
    void paintEvent(QPaintEvent *) override;
    void mouseReleaseEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);

private:
    void region(const QPoint &cursorPoint);

    /*!
     * \brief 绘制带尖的图片
     * \param w      图片宽度
     * \param h      图片高度
     * \param tip_w  尖的宽度
     * \param tip_h  尖的高度
     * \param radius 矩形圆角半径
     * \param margin 边距
     * \return
     */
    QPixmap drawTip(const int w, const int h, const int tip_w, const int tip_h,
                    const int radius, const int margin);

private:
    QPixmap     m_pixmap;
    bool        mIsLeftPressDown;
    QPoint      mDragPosition;
    Direction   mDirec;
    bool        mResizeable;
    int         mRadius;

};

#endif // MAINWINDOW_H

实现的部分cpp文件:

#include "mainwindow.h"

#include <QGraphicsBlurEffect>
#include <QPainter>
#include <QResizeEvent>

static const int SHADOW_WIDTH = 16;

#define PADDING     18
#define PADDING_TOP 29

MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
    mIsLeftPressDown    = false;
    this->mResizeable   = true;
    this->mDirec        = NONE;
    this->mRadius       = 4;
    this->setMouseTracking(true);

    QGraphicsDropShadowEffect* pShadowEffect = new QGraphicsDropShadowEffect(this);
    pShadowEffect->setOffset(0, 0);
    pShadowEffect->setColor(Qt::lightGray);
    pShadowEffect->setBlurRadius(SHADOW_WIDTH);
    this->setGraphicsEffect(pShadowEffect);

    this->setAttribute(Qt::WA_TranslucentBackground, true);
    this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);
}

MainWindow::~MainWindow()
{}

void MainWindow::SetResizeable(bool isResize)
{
    mResizeable = isResize;
}

bool MainWindow::IsResizeable() const
{
    return mResizeable;
}

void MainWindow::SetRadius(bool radius)
{
    mRadius = radius;
}

int MainWindow::GetRadius() const
{
    return mRadius;
}

void MainWindow::resizeEvent(QResizeEvent *e)
{
    const QSize s = e->size();
    int w = s.width();
    int h = s.height();
    if(w > 1 && h > 1) {
        m_pixmap = drawTip(w, h, 18, 12, mRadius, SHADOW_WIDTH);
    }
}

void MainWindow::paintEvent(QPaintEvent *)
{
    if(m_pixmap.isNull())
        return;

    QPainter p;
    p.begin(this);
    p.drawPixmap(this->rect(), m_pixmap);
    p.end();
}

void MainWindow::region(const QPoint &cursorGlobalPoint)
{
    QRect rect = this->rect();
    QPoint tl = mapToGlobal(rect.topLeft());
    QPoint rb = mapToGlobal(rect.bottomRight());
    int x = cursorGlobalPoint.x();
    int y = cursorGlobalPoint.y();

    if(tl.x() + PADDING_TOP >= x && tl.x() <= x && tl.y() + PADDING_TOP >= y && tl.y() <= y) {
        // 左上角
        mDirec = LEFTTOP;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));
    } else if(x >= rb.x() - PADDING && x <= rb.x() && y >= rb.y() - PADDING && y <= rb.y()) {
        // 右下角
        mDirec = RIGHTBOTTOM;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));
    } else if(x <= tl.x() + PADDING && x >= tl.x() && y >= rb.y() - PADDING && y <= rb.y()) {
        //左下角
        mDirec = LEFTBOTTOM;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    } else if(x <= tl.x() + PADDING && x >= tl.x()) {
        // 左边
        mDirec = LEFT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    } else if( x <= rb.x() && x >= rb.x() - PADDING) {
        // 右边
        mDirec = RIGHT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    }else if(y >= tl.y() && y <= tl.y() + PADDING_TOP){
        // 上边
        mDirec = UP;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    } else if(y <= rb.y() && y >= rb.y() - PADDING) {
        // 下边
        mDirec = DOWN;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    }else {
        // 默认
        mDirec = NONE;
        this->setCursor(QCursor(Qt::ArrowCursor));
    }
}

QPixmap MainWindow::drawTip(const int w, const int h, const int tip_w, const int tip_h, const int radius, const int margin)
{
    const int w2 = w - margin * 2 - radius * 2 - tip_w;

    QPainterPath path;

    // TODO 关注微信公众号:cpp手艺人

    return pixmap;
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton) {
        mIsLeftPressDown = false;
        if(mDirec != NONE) {
            this->releaseMouse();
            this->setCursor(QCursor(Qt::ArrowCursor));
        }
    }
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    switch(event->button()) {
    case Qt::LeftButton:
        mIsLeftPressDown = true;
        if(mDirec != NONE) {
            this->mouseGrabber();
        } else {
            mDragPosition = event->globalPos() - this->frameGeometry().topLeft();
        }
        break;
    default:
        QWidget::mousePressEvent(event);
    }
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    QPoint gloPoint = event->globalPos();
    QRect rect = this->rect();
    QPoint tl = mapToGlobal(rect.topLeft());
    QPoint rb = mapToGlobal(rect.bottomRight());

    if(!mIsLeftPressDown) {
        if (mResizeable) {
            this->region(gloPoint);
        }
    } else {

        if(mDirec != NONE && mResizeable) {
            QRect rMove(tl, rb);

            switch(mDirec) {
            case LEFT:
                if(rb.x() - gloPoint.x() <= this->minimumWidth())
                    rMove.setX(tl.x() - SHADOW_WIDTH);
                else
                    rMove.setX(gloPoint.x() - SHADOW_WIDTH);
                break;
            case RIGHT:
                rMove.setWidth(gloPoint.x() - tl.x() + SHADOW_WIDTH);
                break;
            case UP:
                if(rb.y() - gloPoint.y() <= this->minimumHeight())
                    rMove.setY(tl.y() - PADDING_TOP);
                else
                    rMove.setY(gloPoint.y() - PADDING_TOP);
                break;
            case DOWN:
                rMove.setHeight(gloPoint.y() - tl.y() + SHADOW_WIDTH);
                break;
            case LEFTTOP:
                if(rb.x() - gloPoint.x() <= this->minimumWidth())
                    rMove.setX(tl.x() - PADDING);
                else
                    rMove.setX(gloPoint.x() - PADDING);
                if(rb.y() - gloPoint.y() <= this->minimumHeight())
                    rMove.setY(tl.y() - PADDING_TOP);
                else
                    rMove.setY(gloPoint.y() - PADDING_TOP);
                break;
            default:
                break;
            }
            this->setGeometry(rMove);
        } else {
            move(event->globalPos() - mDragPosition);
            event->accept();
        }
    }
    QWidget::mouseMoveEvent(event);
}

大家拿到了源码,自己在封装封装,加入到自己的类库中,为以后的开发绝对节省不少时间。

关注微信公众号:菜单-》Qt源码分享


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 635672377@qq.com

文章标题:Qt源码分享(一)-- 圆角+阴影+可移动+大小可变

文章字数:1.1k

本文作者:刘世雄

发布时间:2020-06-02, 19:07:09

最后更新:2020-06-02, 11:09:17

原始链接:http://lsxcpp.com/2020/06/03/Qt%E6%BA%90%E7%A0%81%E5%88%86%E4%BA%AB%EF%BC%88%E4%B8%80%EF%BC%89-%E5%9C%86%E8%A7%92-%E9%98%B4%E5%BD%B1-%E5%8F%AF%E7%A7%BB%E5%8A%A8-%E5%A4%A7%E5%B0%8F%E5%8F%AF%E5%8F%98/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录