Real-time drawing in Qt

My application displays a long scientific vertically scrollable image (1024 x 99999999 ... px) in the form of a sequence of QPixmap1024x128 blocks. This allows me to scroll the image with the lowest cost processor, choosing the appropriate units from the table: block_id = y_coord/128. It QPixmapis also the preferred “pixel container” for quick display.

But now I have a stream of new data coming into the application, and you need new data that needs to be added and displayed at the bottom of the long image. Minimum part: 1024x1(string). In addition, I would like to display each new line (close to real time) as soon as possible. Each new piece of 128 lines will be "packed" on QPixmap, but until I get enough data, I can not build the whole block.

What approach should be considered for displaying new data?

This video gives an idea of ​​“adding new rows of data”, except that in my case the stream goes up: http://www.youtube.com/watch?v=Dy3zyQNK7jM

+4
source share
3

QPixmaps update() ( ).

, , QImage , , /.

+1

, . , , , :

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QVector>
#include <QGraphicsScene>
#include <QTimerEvent>

#define TILE_HEIGHT 128
#define TILE_WIDTH 1024

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QPixmap generateLine();
public slots:
    void timerEvent(QTimerEvent *);
private:
    QGraphicsView * m_view;
    QGraphicsScene * m_scene;
    QVector <QGraphicsPixmapItem *> m_tiles;
    QVector <QGraphicsPixmapItem *> m_lineBuffer;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

#include <QPixmap>
#include <QtGlobal>
#include <QDateTime>
#include <QTimer>
#include <QPaintEngine>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->setFixedWidth(TILE_WIDTH);
    this->setCentralWidget(m_view = new QGraphicsView());
    m_scene = new QGraphicsScene;
    m_view->setScene(m_scene);

    QPixmap p(TILE_WIDTH, TILE_HEIGHT);
    p.fill(Qt::black);
    m_tiles.append(new QGraphicsPixmapItem(p));
    m_tiles.last()->setPos(0,0);
    m_scene->addItem(m_tiles.last());

    qsrand(QDateTime::currentMSecsSinceEpoch());

    this->startTimer(0);
}

MainWindow::~MainWindow()
{

}

void MainWindow::timerEvent(QTimerEvent *)
{
    // if your generated data is on another thread, you may want to do some thread
    // synchronization with a Mutex and a Mutex Locker so you don't stomp on your
    // buffers

    // static bool busy = false;
    // static int skipCount = 0;
    // if(busy)
    // { 
    //    skipCount++;
    //     qDebug() << "Skipped Line count =" << skipCount;
    //     return;
    // }
    // busy = true;

    // grab a new line
    QPixmap linePix = generateLine();
    int y = m_tiles.size()*TILE_HEIGHT + m_lineBuffer.size()*1;

    // append it to the line buffer
    m_lineBuffer.append(new QGraphicsPixmapItem(linePix));

    // add it to the scene
    m_scene->addItem(m_lineBuffer.last());
    m_lineBuffer.last()->setPos(0, y);

    // scroll it into view
    m_view->ensureVisible(m_lineBuffer.last());

    if(m_lineBuffer.size() >= TILE_HEIGHT)
    {
        // when the line buffer is "full"
        // or ready to be made into a tile

        // compile all the qpixmaps into a single "tile"
        static QRectF source(0,0, TILE_WIDTH, 1);
        QPixmap tile(TILE_WIDTH, TILE_HEIGHT);
        QPainter painter;
        painter.begin(&tile);
        for(int i = 0; i < m_lineBuffer.size(); i++)
        {
            painter.drawPixmap(QRectF(0, i, TILE_WIDTH, 1),
                               m_lineBuffer.at(i)->pixmap(),
                                       source);
        }
        painter.end();

        // add it into the tiles list
        m_tiles.append(new QGraphicsPixmapItem(tile));

        // add it to the scene
        m_tiles.last()->setPos(0, (m_tiles.size() - 1)*TILE_HEIGHT);
        m_scene->addItem(m_tiles.last());

        // scroll it into view
        m_view->ensureVisible(m_tiles.last());

        // Clean up the line buffer
        foreach(QGraphicsPixmapItem * pi, m_lineBuffer)
        {
            m_scene->removeItem(pi);
            delete pi;
        }
        m_lineBuffer.clear();
    }
    // busy = false;
}

QPixmap MainWindow::generateLine()
{
    // create a random pixmap of TILE_WIDTH x 1
    static int img_width = TILE_WIDTH;
    QImage img(img_width,1, QImage::Format_RGB16);
    for(int i = 0; i< img_width; i++)
    {
        img.setPixel(i, 0, qrand()%65536);
    }
    return QPixmap::fromImage(img);
}

main.cpp

#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.showMaximized();

    return a.exec();
}
0

Qt QPixmap QImage. QImage, . QImage.

You may have a QImageheight of 128 pixels, but you only draw the part that is already filled with data. The part without data is either not drawn or hangs under the visible area of ​​the window, and therefore is effectively invisible.

0
source

Source: https://habr.com/ru/post/1524973/


All Articles