I am trying to create a QGraphicsItem that will pull data from a file in a threaded fashion, and display it when the data has been read in. Behold the code:
#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( int nBlocksX, int nBlocksY, int xoffset, int yoffset, int nXBlockSize, int nYBlockSize, int A_BPP,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;
int nBlocksX, nBlocksY, nBlockXSize, nBlockYSize, tilePosX, tilePosY, A_BPP;
signals:
public slots:
void updateSceneSlot();
};
#endif // TILE_H
And the .cpp
#include "tile.h"
Tile::Tile(QGraphicsItem *parent) : QGraphicsItem(parent)
{
}
Tile::~Tile()
{
}
Tile::Tile(int nBlocksX, int nBlocksY, int xoffset, int yoffset, int nXBlockSize, int nYBlockSize, int A_BPP,QGraphicsItem *parent)
: QGraphicsItem(parent)
{
//set some flags and size parameters related to reading from the file on disk. All instances of this QGraphicsItem read from the same file
this->nBlocksX = nBlocksX;
this->nBlocksY = nBl开发者_Python百科ocksY;
this->nBlockXSize = nXBlockSize;
this->nBlockYSize = nYBlockSize;
this->tilePosX =xoffset;
this->tilePosY = yoffset;
this->A_BPP = A_BPP;
setCacheMode(NoCache);
setFlag(QGraphicsItem::ItemIsMovable,false);
setActive(true);
this->setAcceptHoverEvents(true);
this->setFlag(QGraphicsItem::ItemIsFocusable);
this->image = NULL;
this->future = new QFuture<void>;
this->watcher = new QFutureWatcher<void>;
connect(watcher,SIGNAL(finished()),this,SLOT(updateSceneSlot()));
}
QRectF Tile::boundingRect() const
{
if(image == NULL)
return(QRectF(0,0,0,0));
return(QRectF(0,0,image->width(),image->height()));
}
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)
{
TilePainter=painter;
TileOption=option;
TileWidget=widget;
qDebug()<<"Paint Thread id "<< QThread::currentThread();
*future=QtConcurrent::run(this, &Tile::LoadTilePixmap);
watcher->setFuture(*future);
}
QPointF *p = new QPointF(0.0,0.0);
painter->drawImage(*p, *image);
}
void Tile::LoadTilePixmap()
{
/*...populate floatData with data from file...*/
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]));
}
}
}
This will compile fine,but when I try to load an image, i get a whole bunch of X errors, and the program quits:
.
.
.
X Error: BadGC (invalid GC parameter) 13
Major opcode: 60 (X_FreeGC)
Resource id: 0x1c002bb
X Error: RenderBadPicture (invalid Picture parameter) 181
Extension: 156 (RENDER)
Minor opcode: 7 (RenderFreePicture)
Resource id: 0x1c002ba
X Error: BadPixmap (invalid Pixmap parameter) 4
Major opcode: 54 (X_FreePixmap)
Resource id: 0x1c002b9
X Error: BadAlloc (insufficient resources for operation) 11
Major opcode: 53 (X_CreatePixmap)
Resource id: 0x1c002bc
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Extension: 156 (RENDER)
Minor opcode: 4 (RenderCreatePicture)
Resource id: 0x1c002bc
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 55 (X_CreateGC)
Resource id: 0x1c002bc
X Error: BadGC (invalid GC parameter) 13
Major opcode: 56 (X_ChangeGC)
Resource id: 0x1c002be
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 70 (X_PolyFillRectangle)
Resource id: 0x1c002bc
X Error: BadGC (invalid GC parameter) 13
Major opcode: 60 (X_FreeGC)
Resource id: 0x1c002be
X Error: RenderBadPicture (invalid Picture parameter) 181
Extension: 156 (RENDER)
Minor opcode: 7 (RenderFreePicture)
Resource id: 0x1c002bd
X Error: BadPixmap (invalid Pixmap parameter) 4
Major opcode: 54 (X_FreePixmap)
Resource id: 0x1c002bc
Paint Thread id QThread(0x105feac0)
The program has unexpectedly finished.
What am I doing wrong? When I had this set up single-threaded, I was able to do this no problem.
Your image loading code is not thread-safe as QImage is not thread-safe. That should be the reason for your crashes.
You also have leaks, like the QPoint created on the heap and never deleted, in paint(). Just create it on the stack instead of the heap. Same for the image: You leak it, no need to create QImage's on the heap either. (they are implicitely shared so copies are cheap).
精彩评论