我的应用程序显示一个长的科学垂直滚动图片(1024 x 99999999 ... px)作为QPixmap
1024x128块的序列。这允许我通过从表中选择所需的块来以最小的CPU成本滚动图片:block_id = y_coord/128
。此外,QPixmap
是用于快速屏幕输出的首选“像素容器”。
但是现在我有一个新数据流进入应用程序,需要添加新数据并显示在长图的底部。最小部分:1024x1
(一行)。此外,我想尽快显示每一个新行(接近实时)。 128行的每个新部分将被“打包”到QPixmap
,但在我收到足够数据之前,我无法构建整个块。
我应该考虑采用什么方法来显示新数据?
此视频提供了“添加新数据行”的概念,但在我的情况下,流量会上升:http://www.youtube.com/watch?v=Dy3zyQNK7jM
答案 0 :(得分:1)
您可以直接修改QPixmaps的底行和update()
窗口(如果底行在范围内)。
您可能会发现使用QImage对于半成品行更有效,具体取决于您更新/重绘的速度。
答案 1 :(得分: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);
}
的main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.showMaximized();
return a.exec();
}
答案 2 :(得分:0)
在当代Qt上,当使用光栅后端时,QPixmap
与QImage
相比没有任何好处。所有内容都呈现给一个大的QImage
后备缓冲区,然后缓冲到屏幕上。所以只需使用QImage
。
您可以拥有128像素高的QImage
,但您只绘制已填充数据的部分。没有数据的部分要么没有绘制,要么悬挂在窗口的可见区域下面,因此实际上是不可见的。