我正在尝试创建一个Tile渲染程序。这是一些基本代码。
标题
class Tile: public QGraphicsItem
{
public:
Tile(void);
~Tile(void);
QGraphicsPixmapItem *tileItem;
void update(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
protected:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
};
CPP:
.Constructor etc
.
.
void Tile::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
if(tileItem==NULL)
{
qDebug()<<"Loading Pixmap";
QPixmap p("c:\\qt\\tile\\tile0-0.png");
tileItem=new QGraphicsPixmapItem;
tileItem->setPixmap(p);
}
tileItem->paint(painter,option,widget);
}
我正在尝试制作一个将大图像的图块粘贴到QGraphicsScene上的应用程序。但是一次加载所有磁贴都很耗时并占用大量内存。所以我是继承QGraphicsItem并重写油漆。 QGraphicsItem类中的paint方法仅在它进入QGraphicsView内的视图时被调用。因此,通过在tile中加载我的tile,我基本上可以创建一个仅在它们进入视图时加载tile的应用程序。 到目前为止,这一点很有用。
为了让用户体验更好,我使用QtConcurrent尝试在单独的线程中加载磁贴。 这就是我所做的改变。
CPP
connect(&watcher,SIGNAL(finished()),this,SLOT(updateSceneSlot()));
void Tile::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
if(tileItem==NULL)
{
TilePainter=painter;
TileOption=option;
TileWidget=widget;
qDebug()<<"Paint Thread id "<< QThread::currentThread();
future=QtConcurrent::run(LoadTilePixmap,this);
watcher.setFuture(future);
}
else
tileItem->paint(painter, option, widget);
}
LoadTilePixmap函数:
void LoadTilePixmap(Tile *temp,QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
qDebug()<<"Loading Pixmap";
QPixmap p("c:\\qt\\tile\\tile0-0.png");
temp->tileItem=new QGraphicsPixmapItem;
temp->tileItem->setPixmap(p);
qDebug()<<"Loaded Pixmap";
}
void Tile::updateSceneSlot()
{
qDebug()<<"updateSceneSlot Thread id "<< QThread::currentThread();
tileItem->paint(TilePainter, TileOption, TileWidget);
}
此代码应该可以工作但是一旦调用paint就会在运行时崩溃。添加断点后,我将问题缩小到temp->tileItem->paint(painter,option,widget);
,导致崩溃。
我得到的输出是
Loading Pixmap
Almost Loaded Pixmap
First-chance exception at 0x6526174a (QtGuid4.dll) in Visualizer.exe: 0xC0000005: Access violation reading location 0xc88bffe1.
Unhandled exception at 0x6526174a (QtGuid4.dll) in Visualizer.exe: 0xC0000005: Access violation reading location 0xc88bffe1.
任何人都可以帮助我,让我知道为什么lastline / paint方法崩溃了。我该如何解决?
编辑代码以更新更改
答案 0 :(得分:1)
只有主(也称为GUI)线程可以在屏幕上绘制。 我相信,你在一个单独的线程中运行的LoadTilePixmap()函数的下一行试图在屏幕上绘制pixmap项目的内容。
temp->tileItem->paint(painter,option,widget);
在线程中你应该只加载并准备图像,当线程完成后,向主线程发出信号,告知图像已准备就绪,并从主线程中进行绘图。
答案 1 :(得分:1)
从您发布的代码中不清楚,但是您是否在tileItem
的构造函数中将Tile
初始化为NULL?如果没有,这将是您所看到的崩溃的可能解释。
答案 2 :(得分:0)
我通过避免绘画而不是使用更新功能解决了这个问题。从我读过的任何文档更新间接调度绘制调用。 所以最后我的代码看起来像这个
void LoadTilePixmap(Tile *temp)
{
QPixmap p("c:\\qt\\tile\\tile0-0.png");
temp->tileItem=new QGraphicsPixmapItem;
temp->tileItem->setPixmap(p);
temp->update(0,0,511,511);
}
这将导致我的第二次调用我的重载绘制函数,但这次if条件为false并且它进入其中绘制的else。这不是一个最佳解决方案,但现在可以使用。