Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用QtConcurrent加载Pixmap并绘制它_C++_Multithreading_Qt_Qpainter_Qtconcurrent - Fatal编程技术网

C++ 使用QtConcurrent加载Pixmap并绘制它

C++ 使用QtConcurrent加载Pixmap并绘制它,c++,multithreading,qt,qpainter,qtconcurrent,C++,Multithreading,Qt,Qpainter,Qtconcurrent,我正在尝试创建一个平铺渲染程序。这里有一些基本代码 标题 class Tile: public QGraphicsItem { public: Tile(void); ~Tile(void); QGraphicsPixmapItem *tileItem; void update(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget); protected: QRectF boundingRect()

我正在尝试创建一个平铺渲染程序。这里有一些基本代码

标题

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:

谁能帮我一下,让我知道lastline/paint方法崩溃的原因。我怎样才能修好它

编辑代码以更新更改

只有主线程(也称为GUI)可以在屏幕上绘制。 LoadTilePixmap()函数的下面一行,我相信是在单独的线程中运行的,它试图在屏幕上绘制pixmap项目的内容

temp->tileItem->paint(painter,option,widget);

在线程中,您应该只加载并准备图像,当线程完成时,向主线程发出信号,表明图像已准备就绪,并从主线程进行绘图。

您发布的代码不清楚,但您是否正在初始化
tileItem
的构造函数中的
tileItem
为空?如果没有,这可能是您看到的崩溃的原因。

我通过避免绘制而使用更新功能解决了问题。从我读过的任何文档中,update间接地安排了一个绘画调用。 所以最后我的代码是这样的

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条件为false,它将进入绘制的else。虽然不是一个最佳的解决方案,但它目前仍然有效。

这不是问题所在。我设置了一个信号槽机制。但该程序仍然崩溃。我做了一个快速获取当前线程,以找到哪个线程调用paint。主线称为绘画。我还是会犯同样的错误<代码>Visualizer.exe中0x65256977(QtGuid4.dll)处未处理的异常:0xC0000005:访问冲突读取位置0x00000080。我得到一个弹出框,其中提供了两个选项“中断”或“继续”。单击“中断”后,我将进入
qpainter.cpp的第7130行或
qglobal.h的第2194行。知道发生了什么吗?这是主要问题,但不是唯一的问题。Steffen看到了一个可能,这是另一个。不能像这样创建指向QGraphicsPixmapItem的指针。您必须传递对指针的引用,然后LoadTilePixmap()函数将获取指向指针的指针。事实上,我认为如果LoadTilePixmap()函数没有任何参数,就更清楚了,只需在其中创建一个QGraphicsPixmapItem并返回一个指向该对象的指针,然后将该指针分配给tileItem成员。我也试过了。仍然面临同样的问题。斯蒂芬的建议不是问题。如果我不使用多线程(前两个代码段),同样的代码可以完美地工作。但是Qt足够聪明,因为它不可见,所以不会对它做任何事情。一旦它变得可见,我就会加载一个可以看到的pixmap。这很好用。事实上,前两段代码正是这样。我已经测试了很多次,效果非常好。当我添加多线程并尝试绘制它时,唯一的问题出现了。如果我注释掉最后一行,我的代码就可以了。我认为您遇到了一般的并发性问题。您在多个线程中尝试访问的变量没有任何同步。您必须考虑在启动未来之后,呼叫立即返回。当另一个线程工作时,可以多次调用Paint。你怎么知道1)你还没有安排好工作,2)工作已经完成了?Paint()只是测试指针是否为null,但是它如何真正知道另一个线程已经完成了呢?GUI线程可能在创建pixmap的过程中被切换。这是我第一次尝试多线程,所以我真的不知道我是否做对了。根据Qt并发文档,Qt应该负责变量的同步。第二,我甚至尝试了一种使用排队插槽的信号插槽机制。因此,基本上在线程完成执行后,它会发出一个信号,并将其放入队列中。然后依次调用该插槽(称为“绘制”)。我认为这应该解决并发问题,但我不知道。我现在通过调用update而不是paint解决了这个问题。更新计划绘制调用。它起作用了。
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);
}
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.
temp->tileItem->paint(painter,option,widget);
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);
}