Qt Writing Custom Control 60-Sound Waveform Diagram

Posted by aspbyte on Wed, 25 Sep 2019 05:14:23 +0200

I. Preface

This control originates from a music player. When writing the music player, it needs to convert the audio data into corresponding spectrum display. The third-party library of Fmod is used to process it (fmod sound system is a revolutionary audio engine for game developers, very powerful and powerful). Fmod is responsible for getting the number of audio. According to the corresponding sampled spectrum data, and then passed to the control for drawing, the master of the control need to focus on drawing, so Fmod corresponding to the encapsulated class focused on audio acquisition and other processing, to achieve isolation, modification and increase function is more convenient, voice waveform control in addition to the depth of sampling can be set, It also supports three data style display, line style, column style and smooth style. In order to locate directly to a certain position and jump directly to the audio position, a number of lines are drawn.

II. Functions of Realization

  • 1: Sampling depth can be set
  • 2: Current position line width/line color can be set
  • 3: Foreground/Background Colors can be set
  • 4: Data display style, line style/column style/smooth style can be set

III. EFFECT CHARACTERISTICS

Header file code

#ifndef WAVEDATA_H
#define WAVEDATA_H

/**
 * Author of Volume Sampling Value Waveform Control: feiyangqingyun(QQ:517216493) 2017-9-10
 * 1:Sampling depth can be set
 * 2:Line width/line color at current position can be set
 * 3:Settable foreground/background colors
 * 4:Data display style, line style/column style/smooth style can be set
 */

#include <QWidget>

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

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

{
    Q_OBJECT
    Q_ENUMS(WaveStyle)
    Q_PROPERTY(double deep READ getDeep WRITE setDeep)
    Q_PROPERTY(bool showLine READ getShowLine WRITE setShowLine)
    Q_PROPERTY(int lineWidth READ getLineWidth WRITE setLineWidth)
    Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor)
    Q_PROPERTY(QColor foreground READ getForeground WRITE setForeground)
    Q_PROPERTY(QColor background READ getBackground WRITE setBackground)
    Q_PROPERTY(WaveStyle waveStyle READ getWaveStyle WRITE setWaveStyle)

public:
    enum WaveStyle {
        WaveStyle_Line = 0,     //Line style
        WaveStyle_Smooth = 1,   //Smooth style
        WaveStyle_Bar = 2       //Columnar style
    };

    explicit WaveData(QWidget *parent = 0);

protected:
    void mousePressEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *);
    void drawBg(QPainter *painter);
    void drawData(QPainter *painter);
    void drawLine(QPainter *painter);

private:    
    double deep;                //Acquisition depth
    bool showLine;              //Display line
    int lineWidth;              //Line width
    QColor lineColor;           //line color
    QColor foreground;          //Foreground color
    QColor background;          //Background color
    WaveStyle waveStyle;        //Data style

    int length;                 //Sample point length
    int position;               //current location
    QVector<float> data;        //Sampling point data

public:    
    double getDeep()            const;
    bool getShowLine()          const;
    int getLineWidth()          const;
    QColor getLineColor()       const;
    QColor getForeground()      const;
    QColor getBackground()      const;
    WaveStyle getWaveStyle()    const;

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

public slots:
    //Set depth
    void setDeep(double deep);

    //Set whether to display lines
    void setShowLine(bool showLine);
    //Set line width
    void setLineWidth(int lineWidth);
    //Setting Line Colors
    void setLineColor(const QColor &lineColor);

    //set foreground color
    void setForeground(const QColor &foreground);
    //Setting Background Colors
    void setBackground(const QColor &background);

    //Setting Data Styles
    void setWaveStyle(const WaveStyle &waveStyle);

    //Set the total length
    void setLength(int length);
    //Set the current location
    void setPosition(int position);

    //Setting current data
    void setData(const QVector<float> &data);
    //wipe data
    void clearData();

signals:
    void positionChanged(int position);
};

#endif // WAVEDATA_H


V. Core Code

void WaveData::paintEvent(QPaintEvent *)
{
    //Drawing preparation, enabling anti-aliasing
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing);

    //Drawing background
    drawBg(&painter);
    //Drawing data
    drawData(&painter);
    //Draw the current position line
    drawLine(&painter);
}

void WaveData::drawBg(QPainter *painter)
{
    painter->save();
    painter->fillRect(this->rect(), background);
    painter->restore();
}

void WaveData::drawData(QPainter *painter)
{
    if (data.count() == 0) {
        return;
    }

    painter->save();

    //Get the maximum and minimum
    float max = data.at(0);
    float min = data.at(0);
    int count = data.count();

    for (int i = 1; i < count; i++) {
        if (max < data.at(i)) {
            max = data.at(i);
        }

        if (min > data.at(i)) {
            min = data.at(i);
        }
    }

    //Convert to the internal coordinate size of the current screen
    max += deep;
    min -= deep;

    //Automatic conversion of data to screen coordinates
    QVector<QPointF> points;
    for (int i = 0; i < count; i++) {
        double x = i * width() / count;
        double y = height() - (((data.at(i) - min) / (max - min)) * height());
        points.append(QPointF(x, y));
    }

    //Draw different styles
    if (waveStyle == WaveStyle_Line) {
        painter->setPen(foreground);
        for (int i = 0; i < count - 1; i++) {
            painter->drawLine(points.at(i), points.at(i + 1));
        }
    } else if (waveStyle == WaveStyle_Smooth) {
        painter->setPen(foreground);
        QPainterPath path = SmoothCurveCreator::createSmoothCurve(points);
        painter->drawPath(path);
    } else if (waveStyle == WaveStyle_Bar) {
        double penWidth = width() / (count * 1.6);
        QPen pen;
        pen.setColor(foreground);
        pen.setWidthF(penWidth);
        pen.setCapStyle(Qt::RoundCap);
        painter->setPen(pen);

        for (int i = 0; i < count; i++) {
            QPointF point = points.at(i);
            double x = point.x() + penWidth / 1.2;
            painter->drawLine(QPointF(x, point.y()), QPointF(x, height()));
        }
    }

    painter->restore();
}

void WaveData::drawLine(QPainter *painter)
{
    if (!showLine || position > length || data.count() <= 0) {
        return;
    }

    painter->save();

    QPen pen;
    pen.setWidth(lineWidth);
    pen.setColor(lineColor);
    painter->setPen(pen);

    //Calculate the coordinates corresponding to the current position
    int x = ((double)position / length) * width();
    painter->drawLine(x, 0, x, height());

    painter->restore();
}

Introduction of Control

  1. More than 150 exquisite controls, covering a variety of dashboards, progress bars, progress balls, compasses, curves, rulers, thermometers, navigation bars, navigation bars, flatui, highlighted buttons, sliding selectors, lunar calendar, etc. Far more controls than qwt integrates.
  2. Each class can be separated into a separate control, zero-coupling, each control has a header file and an implementation file, independent of other files, to facilitate the integration of a single control in the form of source code into the project, less code. The control classes of qwt are interlinked and highly coupled. If you want to use one of the controls, you must include all the code.
  3. All pure Qt writing, QWidget+QPainter drawing, support any Qt version from Qt4.6 to Qt5.13, support mingw, msvc, gcc and other compilers, support any operating system such as windows+linux+mac + embedded linux, no scrambling, can be directly integrated into Qt Creator, as with its own controls, most of the effects as long as set up. Several attributes can be used, which is very convenient.
  4. Each control has a corresponding separate DEMO containing the source code of the control, which is convenient for reference. It also provides an integrated DEMO for all controls.
  5. The source code of each control has detailed Chinese annotations, which are compiled in accordance with the unified design specifications. It is convenient to learn how to compile custom controls.
  6. Each control's default color matching and demo's corresponding color matching are very beautiful.
  7. More than 130 visible controls and 6 invisible controls.
  8. Some controls provide a variety of style choices, a variety of indicator style choices.
  9. All controls adapt to form stretching changes.
  10. Integrate custom control property designer, support drag design, WYSIWYG, support import and export xml format.
  11. With activex control demo, all controls can run directly in ie browser.
  12. Integrate fontawesome graphic fonts + hundreds of graphic fonts collected by Alibaba iconfont to enjoy the fun of graphic fonts.
  13. All controls eventually generate a dynamic library file (dll or so, etc.) that can be directly integrated into the qtcreator to drag the design to use.
  14. At present, there is a version of qml, pyqt version will be considered later, if the user demand is large.
  15. Custom Control Plug-in Open Dynamic Library (permanently free), without any backdoor and restrictions, please feel free to use.
  16. At present, 26 versions of dll have been provided, including qt5.12.3 MSVC 2017 32 + 64 MinGW 32 + 64.
  17. Increase control and improve control from time to time, update SDK from time to time. Welcome to make suggestions. Thank you!
  18. Qt introductory books recommend Hoyafei's Quick Start to Qt Creator, Qt5 Programming Introduction, and Qt advanced books recommend the official C++ GUI Qt4 Programming.
  19. I strongly recommend programmers'self-cultivation and planning series "Talking about Programmers", "Programmers' Growth Course" and "Solution Programmers". They benefit a lot and benefit a lifetime!
  20. SDK Download Link: https://pan.baidu.com/s/1A5Gd77kExm8Co5ckT51vvQ Extraction code: 877p

Topics: Qt Qt5 Linux SDK