Qt writing custom controls-water wave effect

I. Introduction

I have been thinking about writing this control a few years ago. When I was using C# 9 years ago, I saw someone else using C# to write a water wave effect control. It was quite interesting. At that time, I took a look at the two-dimensional array used in the code. To store the transformed image pixel data. Since I learned Qt, I have wanted to write a version with Qt several times. At that time, my skills were still shallow, and I tried but failed to write it. I remember that there was a dll written in assembly to provide calls. , which is very efficient, but the efficiency of drawing with CPU is relatively much lower. A while ago, a friend - Centrifugal Pump (QQ: 33522) happened to write one. I improved some functions on his basis and added some interface settings, such as providing parameters to control the disappearance speed of water waves, the speed of diffusion, and the speed of water waves. The size of the area and the depth of the water waves, etc.

2. Functions implemented

  • 1: The displayed image can be set
  • 2: The attenuation coefficient can be set to control the disappearance speed. The smaller the value, the faster the water wave disappears.
  • 3: The refractive index can be set to control the diffusion speed. The larger the value, the faster the water wave spreads.
  • 4: You can set the stone size and control the water wave area. The larger the value, the larger the water wave area.
  • 5: The weight of the stone can be set to control the depth of the water wave. The larger the value, the deeper the water wave will be.
  • 6: Currently, CPU computing and drawing are used. The smaller the picture, the smoother it will be.

3. Effect drawing

4. Header file code

#ifndef WAVEWATER_H
#define WAVEWATER_H

/**
 * 水波效果控件 作者:离心泵(QQ:33522) 整理:feiyangqingyun(QQ:517216493) 2019-10-03
 * 1:可设置显示的图像
 * 2:可设置衰减系数,控制消失速度,值越小水波消失越快
 * 3:可设置折射系数,控制扩散速度,值越大水波扩散越快
 * 4:可设置石头大小,控制水波面积,值越大水波面积越大
 * 5:可设置石头重量,控制水波深度,值越大水波深度越浪
 * 6:目前采用的是cpu运算和绘制,图片越小越流畅
 */

#include <QWidget>
#include <QMap>

#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif

class QDESIGNER_WIDGET_EXPORT WaveWater : public QWidget
#else
class WaveWater : public QWidget
#endif

{
    Q_OBJECT
    Q_PROPERTY(int damping READ getDamping WRITE setDamping)
    Q_PROPERTY(int refractive READ getRefractive WRITE setRefractive)
    Q_PROPERTY(int stoneSize READ getStoneSize WRITE setStoneSize)
    Q_PROPERTY(int stoneWeight READ getStoneWeight WRITE setStoneWeight)
    Q_PROPERTY(QPixmap image READ getImage WRITE setImage)

public:
    explicit WaveWater(QWidget *parent = 0);
    ~WaveWater();

protected:
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *);

private:
    int damping;            //波能衰减系数
    int refractive;         //波能折射系数
    int stoneSize;          //石头大小
    int stoneWeight;        //石头重量
    QPixmap image;          //渲染图片

    QImage imageRender;     //渲染像素图片
    QImage imageOrigin;     //渲染源
    QPixmap pixmap;         //渲染图片

    int	imageWidth;         //图片宽度
    int	imageHeight;        //图片高度
    int **waveBuffer1;		//波能缓冲区1
    int **waveBuffer2;		//波能缓冲区2

    bool isStoped;          //水波是否结束波动
    bool isPressed;         //鼠标是否按下
    QPoint lastPoint;       //鼠标按下出的坐标
    QTimer *timer;          //定时器绘制

private slots:
    //执行计算位图进行绘制
    void drawImage();
    //水波步进扩散
    void waveSpread();
    //渲染水波位图
    void waveRender();
    //扔石子
    void dropStone(int x, int y, int stoneSize, int stoneWeight);

public:
    int getDamping()        const;
    int getRefractive()     const;
    int getStoneSize()      const;
    int getStoneWeight()    const;
    QPixmap getImage()      const;

    QSize sizeHint()        const;
    QSize minimumSizeHint() const;

public Q_SLOTS:
    //设置衰减率系数
    void setDamping(int damping);
    //设置折射率系数
    void setRefractive(int refractive);
    //设置石头大小
    void setStoneSize(int stoneSize);
    //设置石头重量
    void setStoneWeight(int stoneWeight);
    //设置背景图片
    void setImage(const QPixmap &pixmap);
};

#endif // WAVEWATER_H


As a benefit for this article, you can receive a Qt development learning package and technical videos for free, including (C++ language basics, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project practice , QT embedded development, Quick module, etc.) ↓↓↓↓↓↓See below↓↓Click at the bottom of the article to receive the fee↓↓

5. Core code

void WaveWater::paintEvent(QPaintEvent *)
{
    if(image.isNull()) {
        return;
    }

    QPainter painter(this);
    painter.setRenderHints(QPainter::SmoothPixmapTransform);

    //如果停止阶段则绘制原图,否则绘制渲染图
    if (isStoped) {
        painter.drawPixmap(0, 0, image);
    } else {
        painter.drawPixmap(0, 0, pixmap);
    }
}

void WaveWater::drawImage()
{
    if(isStoped) {
        timer->stop();
    } else {
        this->waveRender();
        this->update();
    }
}

void WaveWater::waveSpread()
{
    quint32 counter = 0;
    // 波能渐变
    for(int h = 1; h < imageHeight - 1; h++) {
        for(int w = 1; w < imageWidth - 1; w++) {
            //波能扩散
            waveBuffer2[w][h] = ((waveBuffer1[w - 1][h] + waveBuffer1[w + 1][h] + waveBuffer1[w][h - 1] + waveBuffer1[w][ h + 1]) >> 1) - waveBuffer2[w][h];
            //波能衰减
            waveBuffer2[w][h] -= (waveBuffer2[w][h] >> damping);
            //判断波动释放结束
            if(waveBuffer1[w][h] - waveBuffer2[w][h]) {
                counter++;
            }
        }
    }

    //交换缓冲区
    int **temp = waveBuffer1;
    waveBuffer1 = waveBuffer2;
    waveBuffer2 = temp;

    //设置释放完成
    isStoped = counter ? false : true;
}

void WaveWater::waveRender()
{
    //先改变波纹振幅
    waveSpread();
    if(isStoped) {
        return;
    }

    int offsetX = 0;
    int offsetY = 0;

    //扫描位图
    for(int y = 1; y < imageHeight - 1; y++) {
        for(int x = 1; x < imageWidth - 1; x++) {
            //根据波幅计算位图数据偏移值,渲染点(x,y)对应原始图片(offsetX,offsetY)
            offsetX = x + ((waveBuffer1[x - 1][y] - waveBuffer1[x + 1][y]) >> refractive);
            offsetY = y + ((waveBuffer1[x][y - 1] - waveBuffer1[x][y + 1]) >> refractive);
            //复制象素
            if(0 <= offsetX && offsetX < imageWidth - 1 && 0 <= offsetY && offsetY < imageHeight - 1) {
                QRgb color = imageOrigin.pixel(offsetX, offsetY);
                imageRender.setPixel(x, y, color);
            }
        }
    }

    pixmap.convertFromImage(imageRender);
}

void WaveWater::dropStone(int x, int y, int stoneSize, int stoneWeight)
{
    isStoped = false;
    int posX = 0;
    int posY = 0;

    for(int h = -stoneSize; h < stoneSize; h++) {
        for(int w = -stoneSize; w < stoneSize; w++) {
            posX = x + w;
            posY = y + h;

            //控制范围,不能超出图片
            if(posX < 0 || posX >= imageWidth || posY < 0 || posY >= imageHeight) {
                continue;
            }

            //点(w,h)在一个圆形区域内,初始化波能缓冲区1
            if(h * h + w * w <= stoneSize * stoneSize) {
                waveBuffer1[posX][posY] = -stoneWeight;
            }
        }
    }
}

6. Control introduction

  1. More than 160 exquisite controls, covering various dashboards, progress bars, progress balls, compasses, curves, rulers, thermometers, navigation bars, navigation bars, flatui, highlight buttons, sliding selectors, lunar calendar, etc. Far exceeds the number of controls integrated by qwt.
  2. Each class can be independently formed into a separate control, with zero coupling. Each control has a header file and an implementation file, and does not rely on other files. It is convenient for a single control to be integrated into the project in the form of source code, with less code. The control classes of qwt are interlocking and highly coupled. If you want to use one of the controls, you must include all the code.
  3. All written in pure Qt, drawn by QWidget+QPainter, supports any Qt version from Qt4.6 to Qt5.13, supports compilers such as mingw, msvc, gcc, etc., and supports any operating system such as windows+linux+mac+embedded linux, etc., without garbled code , can be directly integrated into Qt Creator and used like the built-in controls. Most effects only need to set a few properties, which is extremely convenient.
  4. Each control has a corresponding separate DEMO containing the source code of the control for easy reference and use. It also provides an integrated DEMO used by all controls.
  5. The source code of each control has detailed Chinese comments and is written in accordance with unified design specifications, making it easy to learn how to write custom controls.
  6. The default color matching of each control and the color matching corresponding to the demo are very exquisite.
  7. More than 130 visible controls and 6 invisible controls.
  8. Some controls provide multiple style choices and multiple indicator style choices.
  9. All controls adapt to form stretch changes.
  10. Integrated custom control attribute designer, supports drag and drop design, WYSIWYG, supports import and export of xml format.
  11. Comes with activex control demo, all controls can be run directly in the IE browser.
  12. Integrate fontawesome graphic fonts + hundreds of graphic fonts collected by Alibaba iconfont, and enjoy the fun brought by graphic fonts.
  13. All controls finally generate a dynamic library file (dll or so, etc.), which can be directly integrated into qtcreator for drag and drop design.
  14. There is already a qml version, and a pyqt version will be considered later if there is great demand from users.
  15. The custom control plug-in is open to dynamic library use (free forever), without any backdoors or restrictions, so please feel free to use it.
  16. Currently, 32 versions of dll have been provided, among which the version qt_5_7_0_mingw530_32 will always be guaranteed to be the latest and complete.
  17. Controls are added and improved from time to time, and the SDK is updated from time to time. Suggestions are welcome, thank you!
  18. For introductory Qt books, we recommend Huo Yafei's "Quick Start with Qt Creator" and "Introduction to Qt5 Programming". For advanced Qt books, we recommend the official "C++ GUI Qt4 Programming".
  19. I highly recommend the series of self-cultivation and planning books for programmers, "The Big Talk Programmer", "Programmer's Growth Course", and "The Worry-Relieving Programmer", which will benefit you a lot and will last a lifetime!
  20. SDK address: https://gitee.com/feiyangqingyun/QUCSDK https://github.com/feiyangqingyun/qucsdk

Original link: https://www.cnblogs.com/feiyangqingyun/p/11636757.html

As a benefit for this article, you can receive a Qt development learning package and technical videos for free, including (C++ language basics, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project practice , QT embedded development, Quick module, etc.) ↓↓↓↓↓↓See below↓↓Click at the bottom of the article to receive the fee↓↓

Guess you like

Origin blog.csdn.net/hw5230/article/details/132910547