022-Third generation software development-QCustomPlot core migration

Header image

Third generation software development-QCustomPlot core migration

Article directory

  • Third generation software development-QCustomPlot core migration
    • Project Introduction
    • Let’s talk about GitHub Copilot first.
    • QCustomPlot core migration
      • QQuickPaintedItem
      • XXX_QCustomChart


Keywords:
Qt
Qml
QCustomPlot
GitHub Copilo
Keyword 5

Project introduction

Welcome to our QML & C++ project! This project combines the power of QML (Qt Meta-Object Language) and C++ to develop excellent user interfaces and high-performance backend logic.

In the project, we leveraged QML’s declarative syntax and visual design capabilities to create a modern user interface. Through intuitive coding and reusable components, we can quickly develop rich and diverse interface effects and animation effects. At the same time, we use QML’s powerful integration capabilities to easily integrate the underlying logic and data model of C++ into the front-end interface.

On the backend side, we use C++ to write high-performance algorithms, data processing, and computational logic. C++ is a powerful programming language that offers excellent performance and scalability. Our team is committed to optimizing code and reducing resource consumption to ensure that our projects run efficiently on a variety of platforms and devices.

Whether you’re interested in QML and C++ development or need us to build complex user interfaces and backend logic for you, we’re ready to support you. Please feel free to contact us and let’s build a modern, high-performance QML & C++ project together!

Important?

?The price of this column will increase after the third generation soft development update.

Let’s talk about GitHub Copilot first

Why are we nagging him again? In the last article, we briefly experienced GitHub Copilot and roughly defined it as a slightly smarter smart completion tool. But this is superficial. Today I finally saw it. The great thing about it.

Before, our data needed to be filtered. How we did it before was to simulate it in MATLAB, export an array, and implement the code. This process should be followed by everyone. Let’s see what the future will look like, tremble, babies, below is the actual demonstration. You can see that the class names are all from our project, there is no adulteration at all.

Here we have to talk about a question: Can VC6.0 in our traditional universities still meet the current needs? Theory is very important, but the tools of the new era are an indispensable part. I remember when I was working, I learned The first thing turned out to be SVN. I had never encountered it in college, let alone Git. Putting aside my personal initiative issues, is it that the university is a bit far away from reality?

QCustomPlot core migration

Let’s get back to our topic. Today we’ll talk about putting QCustomPlot into QML. Why waste this effort? Qt doesn’t have QChart anymore. This is already a historical issue, because in the first and second generations, we all used QCustomPlot to draw curves, and QChar passed our testing under QWidget. It doesn’t meet the needs, or we can’t control it. Coupled with the training of the first and second generations, we have a little bit of experience with this QCustomPlot, so we just use it directly. But, with our IQ, how can we know this kind of thing? Just ask Baidu for help and copy the homework.

QQuickPaintedItem

Here we need to introduce a class QQuickPaintedItem

QQuickPaintedItem is a class in the Qt Quick framework, which is used for custom painting in the Qt Quick interface. It allows developers to use their own drawing code to create items that can be displayed in Qt Quick scenes.

QQuickPaintedItem is a subclass of QQuickItem, which inherits the features and functions of QQuickItem. Unlike other QQuickItems, QQuickPaintedItem implements custom painting by overriding the virtual functions of its parent class. The main drawing function is void QQuickPaintedItem::paint(QPainter *painter). In this function, developers can use the QPainter object to perform 2D drawing operations, such as drawing graphics, text, and images.

Using QQuickPaintedItem, developers can create custom Qt Quick components using their own drawing algorithms and techniques. For example, you can use QPainter to draw dynamic graphics, data visualizations, or customized UI elements. Because QQuickPaintedItem provides direct access to the underlying drawing API (QPainter), it is more flexible than using pure Qt Quick elements in some situations.

To use QQuickPaintedItem in the Qt Quick interface, you can add it as a child to the QML layout and set its properties, signal slots, etc. At the same time, you can customize more drawing behaviors and functions by inheriting the QQuickPaintedItem class.

It should be noted that since QQuickPaintedItem directly operates the underlying drawing API, it should be used with caution in scenarios with high performance requirements and avoid performing overly complex or frequent drawing operations to ensure a good user experience.

The language of the machine is always stiff and makes people feel no warmth at all. Let’s take a look at the blogs of real bloggers to see which unlucky guy we caught copying homework today.

https://blog.csdn.net/LIJIWEI0611/article/details/124103346

? image-20230727221811629

This blogger and the robot jointly mentioned a problem, that is, should be used with caution in scenarios with high performance requirements Axi, although you can tell me, besides this method, what other methods will Improve performance. Because that’s how I wrote it. The following internal quotations are from the above blog

The core of Qt Quick is Scene Graph, which can be retrieved using the keyword “Scene Graph” in the index mode of Qt Help. The design idea of Scene Graph is similar to the QGraphicsView/QGraphicsScene framework. In one scene, many graphics elements are placed in the scene. The difference is the drawing of Item. The QGraphicsView framework drives the drawing of Item through the drawing event of View. QGraphicsItem has a paint() virtual function. As long as the Item you inherit from QGraphicsItem implements this paint() function, you can It is drawn on QPaintDevice, and the logic is straightforward; while Qt Quick’s drawing actually has another rendering thread. The Item in the Scene does not have an intuitive drawing function like paint(), and only has an updatePaintNode() method that allows you to construct your Item. Geometric representation, when the program turns to the rendering loop, the rendering loop takes out the QSGNode trees of all Items and draws them.

updatePaintNode() This drawing method is very unintuitive. It comes from the drawing mode of OpenGL or Direct 3D: you construct the geometric representation of the primitive, and others will draw it for you at a certain moment based on the materials you provide, just like you throw a It feels like bringing a bag of garbage to the door, and after a while someone will come and collect it for you. Developers who are used to Qt Widgets and QPainter may not adapt to this method, so Qt Quick provides a method that is compatible with old habits: introducing QQuickPaintedItem and using QPainter to draw.

Generally, you can understand it like this: QQuickPaintedItem uses the usual 2D drawing method in Qt Widgets to draw the lines, pictures, text, etc. you want to a QImage in memory, and then put this QImage there as a QSGNode, etc. Let Qt Quick’s rendering thread take it and draw it into the actual scene. According to this understanding, QQuickPaintedItem will undergo multiple drawing steps, resulting in performance losses! However, for the sake of development convenience, sometimes this little performance loss is acceptable – as long as your application can still run smoothly.

QQuickPaintedItem is the base class for all Qt Quick Items that want to use QPainter to draw. It has a pure virtual function – paint(QPainter * painter). Your customized Item only needs to implement the paint() virtual function.

QQuickPaintedItem is a derived class of QQuickItem. The boundingRect() method of QQuickItem returns a rectangle of Item, and you can draw your Item based on it. fillColor() returns the Item’s fill color (transparent by default), which Qt Quick will use to draw the background of your Item before the paint() method is called. setFillColor() can change the fill color.

Qt Quick provides a “Scene Graph – Painted Item” example to demonstrate the usage of QQuickPaintedItem, you can refer to it.

XXX_QCustomChart

#include <QQuickPaintedItem>
#include <QObject>
#include <QtQuick>
class QCustomPlot;
class QCPAbstractPlottable;

class XXX : public QQuickPaintedItem
{
    Q_OBJECT
public:
    explicit XXXX(QQuickItem *parent = nullptr);

    virtual ~XXXX();

    void paint(QPainter *painter) override;

    virtual void initChartUI(){};

    QCustomPlot *getPlot();

protected:
    virtual void hoverMoveEvent(QHoverEvent *event) override;

    virtual void mousePressEvent( QMouseEvent* event ) override;

    virtual void mouseReleaseEvent( QMouseEvent* event ) override;

    virtual void mouseMoveEvent( QMouseEvent* event ) override;

    virtual void mouseDoubleClickEvent( QMouseEvent* event ) override;

    virtual void wheelEvent( QWheelEvent *event ) override;

    void routeMouseEvents( QMouseEvent* event );

    void routeWheelEvents( QWheelEvent* event );

public slots:
    void graphClicked( QCPAbstractPlottable* plottable );

    void onChartViewReplot();

    void updateChartViewSize();

private:
    QCustomPlot* m_customPlot = nullptr;
};



#endif //
#include "QCustomPlot/qcustomplot.h"
#include <QDebug>
XXX::XXX(QQuickItem *parent): QQuickPaintedItem(parent),m_customPlot(new QCustomPlot())
{
    setFlag(QQuickItem::ItemHasContents, true); //Indicates that the item has visual content and should be rendered by the scene view
    setAcceptedMouseButtons(Qt::AllButtons); // Set accepted mouse buttons
    setAcceptHoverEvents(true); //Accept mouse hover events
    m_customPlot->setOpenGl(false); // Open using OpenGL rendering
    connect(this, & amp;QQuickPaintedItem::widthChanged,
            this, & amp;XXXX::updateChartViewSize); // Update window
    connect(this, & amp;QQuickPaintedItem::heightChanged,
            this, & amp;XXXX::updateChartViewSize); // Update window

// m_customPlot->setBackground(QBrush(QColor(255,255,255,255))); // Set the background color
    // m_customPlot->xAxis->setVisible(false); // Do not display the abscissa
    // m_customPlot->yAxis->setVisible(false); // Do not display the ordinate
    // m_customPlot->setInteractions( QCP::iRangeDrag | QCP::iRangeZoom ); // You can zoom in and out, slide up, down, left and right
    // m_customPlot->setSelectionRectMode(QCP::SelectionRectMode::srmZoom); // Frame selection zoom

}

XXX::~XXX()
{
    delete m_customPlot;
}

void XXXX::paint(QPainter *painter)
{
    if (!painter->isActive())
        return;
    QPixmap picture( boundingRect().size().toSize() );
    QCPPainter qcpPainter( & amp;picture );
    m_customPlot->toPainter( & amp;qcpPainter);
    painter->drawPixmap(QPoint(), picture);

}

QCustomPlot *XXXX::getPlot()
{
    return m_customPlot;
}

void XXXX::hoverMoveEvent(QHoverEvent *event)
{
    Q_UNUSED(event)
}

void XXXX::mousePressEvent(QMouseEvent *event)
{
    routeMouseEvents(event);
}

void XXXX::mouseReleaseEvent(QMouseEvent *event)
{
    routeMouseEvents(event);
}

void XXXX::mouseMoveEvent(QMouseEvent *event)
{
    routeMouseEvents(event);
}

void XXXX::mouseDoubleClickEvent(QMouseEvent *event)
{
    routeMouseEvents(event);
}

void XXXX::wheelEvent(QWheelEvent *event)
{
    routeWheelEvents( event );
}

void XXXX::routeMouseEvents(QMouseEvent *event)
{
    QMouseEvent* newEvent = new QMouseEvent(event->type(), event->localPos(), event->button(), event->buttons(), event->modifiers());
    QCoreApplication::postEvent(m_customPlot, newEvent);
}

void XXXX::routeWheelEvents(QWheelEvent *event)
{
    QWheelEvent* newEvent = new QWheelEvent(event->pos(), event->delta(), event->buttons(), event->modifiers(), event->orientation());
    QCoreApplication::postEvent(m_customPlot, newEvent);
}

void XXXX::graphClicked(QCPAbstractPlottable *plottable)
{
    qDebug() << Q_FUNC_INFO << QString( "Clicked on graph '%1 " ).arg( plottable->name() );
}

void XXXX::onChartViewReplot()
{
    update();
}

void XXXX::updateChartViewSize()
{
    m_customPlot->setGeometry(0, 0, (int)width(), (int)height());
    m_customPlot->setViewport(QRect(0, 0, (int)width(), (int)height()));
}

Blog Signature 2021