2014-02-02 15 views
4

Мое приложение отображает длинное научное вертикально-прокручиваемое изображение (1024 x 99999999 ... px) в виде последовательности QPixmap 1024x128 блоков. Это позволяет мне прокручивать изображение с минимальной стоимостью процессора, выбирая необходимые блоки из таблицы: block_id = y_coord/128. Кроме того, QPixmap является предпочтительным «пиксельным контейнером» для быстрого вывода экрана.Картинка в реальном времени в Qt

Но теперь у меня есть поток новых данных, поступающих в приложение, и вам нужны новые данные, которые нужно добавить и отобразить в нижней части длинного изображения. Минимальная часть: 1024x1 (линия). Кроме того, я хотел бы как можно скорее отобразить каждую новую строку (близко к реальному времени). Каждая новая часть из 128 строк будет «упакована» на QPixmap, но пока я не получу достаточно данных, я не могу построить целый блок.

Какой подход следует учитывать при отображении новых данных?

Это видео дает представление о том, «добавлении новых строк данных», за исключением того, в моем случае поток идет вверх: http://www.youtube.com/watch?v=Dy3zyQNK7jM

+0

Я думаю, вы можете просто добавить новые данные в какую-нибудь временную pixmap и нарисовать ее внизу рисунка и нарисовать остальные так же, как вы его сейчас нарисовываете (возможно, с некоторыми изменениями). Когда вы получили 128 строк, просто отбросьте временные файлы pixmap и pack. –

ответ

1

Вы можете просто, непосредственно, изменить нижнюю строку QPixmaps и update() окна (если нижняя строка находится в диапазоне).

Вы можете обнаружить, что использование QImage более эффективно для полупеченных строк, в зависимости от того, насколько быстро вы обновляете/перекрашиваете.

+2

Обновление QPixmap не из дешевых :) – pavelkolodin

+0

Нет, но обновление QImage дешевле, как я уже упоминал. Вы потеряете скорость в рендеринге, но, вероятно, не много. Вы могли бы сделать полосы 1024 * 16 или что-то вместо этого, что должно помочь. * Вы измерили это? * – spraff

0

Вот краткий пример, который я собрал. Я не знаю, если это является наиболее эффективным, но он показывает основную идею вы смотрите на:

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); 
} 

основной. каст

#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.

У вас может быть QImage, высота которого составляет 128 пикселей, но вы можете нарисовать только часть, которая уже была заполнена данными. Часть без данных либо не нарисована, либо висит ниже видимой области окна, и поэтому становится невидимой.

Смежные вопросы