2011-06-13 89 views
0

我想创建一个的QGraphicsItem将从螺纹方式文件中提取数据,并将其显示在数据已被读取看哪代码:的QGraphicsItem子扔X错误和崩溃

#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 

而且在.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 = nBlocksY; 
    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])); 
      } 
     } 


} 

这将编译很好,但是当我尝试加载图像,我得到了一大堆X的错误,并且程序退出:

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

我做错了什么?当我建立单线程时,我能够做到这一点没有问题。

回答

2

由于QImage不是线程安全的,因此您的图像加载代码不是线程安全的。这应该是你崩溃的原因。

在paint()中,您也有泄漏,如在堆上创建并从未删除过的QPoint。只需在堆栈而不是堆上创建它。相同的图像:你泄漏它,不需要在堆上创建QImage。 (它们隐含共享,因此副本很便宜)。

+0

你确定吗?我认为QImage应该是线程安全的 - 我明确地转向它,因为我听说QPixmap不是线程安全的。 – Derek 2011-06-13 21:29:47

+0

QImage不是线程安全的 - 它可以在非UI线程中使用(无论是线程本地还是外部同步),而QPixmap根本不能用于非GUI线程。您可以将图像加载到另一个线程中,然后将完全加载的图像传递到主线程。 – 2011-06-13 21:32:01

+0

另外 - 我想因为我试图只创建我的QImage一次,当它第一次加载时,我需要保持它在堆上,而不是堆栈。 – Derek 2011-06-13 21:32:49