使用QtConcurrent加载Pixmap并绘制它

使用QtConcurrent加载Pixmap并绘制它

本文介绍了使用QtConcurrent加载Pixmap并绘制它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个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()<<加载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中的视图时才调用。因此,通过加载我的瓷砖内的油漆,我基本上可以创建一个应用程序加载磁砖只有当他们进入视野。
这么多工作到目前为止。



为了使用户体验更好我使用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);
}

此代码应该可以工作,但在运行时会一直崩溃。添加断点后,我把问题缩小到 temp-> tileItem-> paint(painter,option,widget); ,这会导致崩溃。



我得到的输出是

 加载Pixmap 
几乎加载Pixmap
Visualizer.exe中0x6526174a(QtGuid4.dll)的第一次异常:0xC0000005:访问冲突读取位置0xc88bffe1。
在Visualizer.exe中的0x6526174a(QtGuid4.dll)未处理的异常:0xC0000005:访问冲突读取位置0xc88bffe1。

任何人都可以帮助我,让我知道为什么lastline / paint方法崩溃。

解决方案



修改代码以更新更改

>我解决了这个问题,通过避免绘制,而不是使用更新功能。从任何文档,我已经阅读更新间接调度绘画调用。
所以最后我的代码看起来像这样

  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);
}

这将导致我重载的paint函数第二次被调用,时间if条件为假,它进入其他的涂料。不是一个最佳的解决方案,但它现在工作。


I'm trying to create a Tile rendering program. Heres some basic code.

Header

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);
}

I'm trying to make a application that will paste tiles of a big image onto a QGraphicsScene. But loading all the tiles at once is time consuming and takes up a lot of memory. So I'm subclassing QGraphicsItem and overriding paint. The paint method in the QGraphicsItem class is only called when a it comes into view inside the QGraphicsView. So by loading up my tile inside paint, I can basically create an application that loads tiles only when they come into view.This much is working so far.

To make the user experience better I'm use QtConcurrent to try an load the tiles up in a seperate thread.SO here's the changes I've made.

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 function:

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);
}

This code should work but it keeps crashing at runtime as soon as paint gets called. After adding breakpoints I narrowed the problem down to temp->tileItem->paint(painter,option,widget); which causes the crash.

The output that I get is

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.

Could anyone help me and let me know why the lastline/paint method crashes. How can I fix it?

EDITED CODE TO UPDATE CHANGES

解决方案

I solved the issue by avoiding paint and instead using the update function. From whatever documentation I've read update indirectly schedules a paint call.So in the end my code looks like this

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);
}

This will cause my overloaded paint function to get called for a second time but this time the if condition is false and it goes into else which paints. Not exactly an optimum solution but it works for now.

这篇关于使用QtConcurrent加载Pixmap并绘制它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 14:30