PDA

View Full Version : Loading new QGraphicsItems with QtConcurrent



dcole
13th June 2011, 20:20
Hello,

I am trying to create a QGraphicsItem that pulls data from the disk in a threaded manner. In my case, the images are very large, so I am creating Tiles that will each pull a section from the same data source.

Here is the code from my Tile.cpp class that is subclassing QGraphicsitem


#include "tile.h"

Tile::Tile(QGraphicsItem *parent) : QGraphicsItem(parent)
{
}

Tile::~Tile()
{
}
Tile::Tile(QGraphicsItem *parent)
: QGraphicsItem(parent)
{


this->image = NULL;

this->future = new QFuture<void>;
this->watcher = new QFutureWatcher<void>;
connect(watcher,SIGNAL(finished()),this,SLOT(updat eSceneSlot()));
}
QRectF Tile::boundingRect() const
{
if(image == NULL)
return(QRectF(0,0,0,0));

return(QRectF(image->rect()));
}

void Tile::updateSceneSlot()
{
qDebug("updateSceneSlot Thread id %i", QThread::currentThread());
this->paint(TilePainter, TileOption, TileWidget);
}

void Tile::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{


if(image==NULL)
{
qDebug("Image is null");
TilePainter=painter;
TileOption=option;
TileWidget=widget;
qDebug()<<"Paint Thread id "<< QThread::currentThread();
*future=QtConcurrent::run(this, &Tile::LoadTilePixmap);
watcher->setFuture(*future);

}else
{
qDebug("Image is not null");
QPointF *p = new QPointF(0.0,0.0);
painter->drawImage(*p, *image);

}
}

void Tile::LoadTilePixmap()
{
qDebug("Loading Pixmap");
/*...go out to disk here, and populate floatData...*/

image = new QImage(nXSize, nYSize, QImage::Format_RGB32);
for (int i = 0 ; i < nYSize ; i++)
{
for (int j = 0 ; j < nXSize ; j++)
{
image->setPixel(j,i,qRgb((unsigned char)floatData[i*nXSize+j],(unsigned char)floatData[i*nXSize+j],(unsigned char)floatData[i*nXSize+j]));
}
}

qDebug("Image complete loading");
if(image != NULL)
qDebug("Image not null");

}

Here is the header file:


#ifndef TILE_H
#define TILE_H

#include <QGraphicsItem>
#include <QThread>
#include <QFutureWatcher>
#include <QtConcurrentRun>
#include "gdal_priv.h"
#include <QPainter>

class Tile : public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)

public:
Tile(QGraphicsItem *parent = 0);
~Tile();
void LoadTilePixmap();

protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
QRectF boundingRect() const;

private:
QFutureWatcher<void> *watcher;
QFuture<void> *future;
QImage *image;
const QStyleOptionGraphicsItem *TileOption;
QPainter *TilePainter;
QWidget *TileWidget;


signals:

public slots:
void updateSceneSlot();

};

#endif // TILE_H

i have tried to just simply load 4 tiles from the disk in my main method, and my code is crashing with the following output:

Image is null
Paint Thread id QThread(0x6288ac0)
Image is null
Paint Thread id QThread(0x6288ac0)
Loading Pixmap
Image is null
Loading Pixmap
Paint Thread id QThread(0x6288ac0)
Image is null
Paint Thread id QThread(0x6288ac0)
Loading Pixmap
Loading Pixmap

X Error: BadAlloc (insufficient resources for operation) 11
Major opcode: 53 (X_CreatePixmap)
Resource id: 0x1e00293
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Extension: 156 (RENDER)
Minor opcode: 4 (RenderCreatePicture)
Resource id: 0x1e00293
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 55 (X_CreateGC)
Resource id: 0x1e00293
X Error: BadGC (invalid GC parameter) 13
Major opcode: 56 (X_ChangeGC)
Resource id: 0x1e00295
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 70 (X_PolyFillRectangle)
Resource id: 0x1e00293
X Error: BadGC (invalid GC parameter) 13
Major opcode: 60 (X_FreeGC)
Resource id: 0x1e00295
X Error: RenderBadPicture (invalid Picture parameter) 181
Extension: 156 (RENDER)
Minor opcode: 7 (RenderFreePicture)
Resource id: 0x1e00294
X Error: BadPixmap (invalid Pixmap parameter) 4
Major opcode: 54 (X_FreePixmap)
Resource id: 0x1e00293
X Error: BadAlloc (insufficient resources for operation) 11
Major opcode: 53 (X_CreatePixmap)
Resource id: 0x1e00296
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Extension: 156 (RENDER)
Minor opcode: 4 (RenderCreatePicture)
Resource id: 0x1e00296
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 55 (X_CreateGC)
Resource id: 0x1e00296
X Error: BadGC (invalid GC parameter) 13
Major opcode: 56 (X_ChangeGC)
Resource id: 0x1e00298
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 70 (X_PolyFillRectangle)
Resource id: 0x1e00296
X Error: BadGC (invalid GC parameter) 13
Major opcode: 60 (X_FreeGC)
Resource id: 0x1e00298
X Error: RenderBadPicture (invalid Picture parameter) 181
Extension: 156 (RENDER)
Minor opcode: 7 (RenderFreePicture)
Resource id: 0x1e00297
X Error: BadPixmap (invalid Pixmap parameter) 4
Major opcode: 54 (X_FreePixmap)
Resource id: 0x1e00296
X Error: BadAlloc (insufficient resources for operation) 11
Major opcode: 53 (X_CreatePixmap)
Resource id: 0x1e00299
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Extension: 156 (RENDER)
Minor opcode: 4 (RenderCreatePicture)
Resource id: 0x1e00299
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 55 (X_CreateGC)
Resource id: 0x1e00299
X Error: BadGC (invalid GC parameter) 13
Major opcode: 56 (X_ChangeGC)
Resource id: 0x1e0029b
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 70 (X_PolyFillRectangle)
Resource id: 0x1e00299
X Error: BadGC (invalid GC parameter) 13
Major opcode: 60 (X_FreeGC)
Resource id: 0x1e0029b
X Error: RenderBadPicture (invalid Picture parameter) 181
Extension: 156 (RENDER)
Minor opcode: 7 (RenderFreePicture)
Resource id: 0x1e0029a
X Error: BadPixmap (invalid Pixmap parameter) 4
Major opcode: 54 (X_FreePixmap)
Resource id: 0x1e00299
X Error: BadAlloc (insufficient resources for operation) 11
Major opcode: 53 (X_CreatePixmap)
Resource id: 0x1e0029c
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Extension: 156 (RENDER)
Minor opcode: 4 (RenderCreatePicture)
Resource id: 0x1e0029c
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 55 (X_CreateGC)
Resource id: 0x1e0029c
X Error: BadGC (invalid GC parameter) 13
Major opcode: 56 (X_ChangeGC)
Resource id: 0x1e0029e
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 70 (X_PolyFillRectangle)
Resource id: 0x1e0029c
X Error: BadGC (invalid GC parameter) 13
Major opcode: 60 (X_FreeGC)
Resource id: 0x1e0029e
X Error: RenderBadPicture (invalid Picture parameter) 181
Extension: 156 (RENDER)
Minor opcode: 7 (RenderFreePicture)
Resource id: 0x1e0029d
X Error: BadPixmap (invalid Pixmap parameter) 4
Major opcode: 54 (X_FreePixmap)
Resource id: 0x1e0029c
Image complete loading
Image not null
updateSceneSlot Thread id 103320256
Image is not null
The program has unexpectedly finished.


What do these errors mean? What am I doing wrong here?

Thanks

wysota
13th June 2011, 21:37
Your updateSceneSlot() should be:

void Tile::updateSceneSlot()
{
image = future.result();
prepareGeometryChange();
}

and the concurrent call should be:

future = QtConcurrent::run(this, &Tile::LoadTilePixmap);
with LoadTilePixmap being:

QImage Tile::LoadTilePixmap() {
QImage img = ...;
for(...) { img.setPixel(...); }
return img;
}

otherwise you're modifying the image member variable from another thread at the same time using this variable from within the main thread. The concurrent call should return a ready image and only then you can assign it to the member variable and inform graphics view it might use it (with prepareGeometryChange() as your boundingRect changes).

dcole
14th June 2011, 00:57
Excellent. This did seem to work. It is my first time trying to use QtConcurrent, so its a little bewildering to me still yet.