使用 QtConcurrent 加载 Pixmap 并绘制它
Using QtConcurrent to load a Pixmap and paint it
>我正在尝试创建一个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 并覆盖油漆。类中的 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);
}
加载图皮图函数:
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.
谁能帮我,让我知道为什么最后一行/油漆方法崩溃。我该如何解决它?
编辑代码以更新更改
只有主(也称为GUI)线程可以在屏幕上绘制。我相信,来自 LoadTilePixmap() 函数的以下行,您在单独的线程中运行,尝试在屏幕上绘制像素图项目的内容。
temp->tileItem->paint(painter,option,widget);
在线程中,您应该只加载和准备图像,当线程完成后,向主线程发出图像已准备就绪的信号,并从主线程进行绘制。
从您发布的代码中不清楚,但是您是否在Tile
的构造函数中将tileItem
初始化为NULL?如果没有,那将是你所看到的崩溃的可能解释。
我通过避免绘画而是使用更新功能来解决这个问题。从我读过的任何文档中,更新都间接安排了油漆调用。所以最后我的代码看起来像这样
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,它会进入其他绘制。不完全是最佳解决方案,但它目前有效。
- QuadTree只在窗口的右上角绘制
- 绘制旋转的三角形
- flutter:即使shouldRepaint()返回true,自定义画家也不会重新绘制
- 如何在QT中的自定义视频小工具t上绘制矩形
- 如何在Visual Basic中使用矩形函数OpenGL绘制矩形
- 无法使用VAO和EBO(openGL)绘制多个对象
- 为什么我的点没有在 OpenGL 中绘制鼠标所在的位置?
- 绘制顺时针三角形,重新排序点
- 在顶点着色器中使用 OpenGl 的未声明标识符,我在顶点着色器中绘制三角形时遇到问题
- SFML 文本未绘制在窗口上
- 如何在快板的屏幕中显示子位图的绘制?
- 如何绘制自定义形状的元素?
- QPainter 将 QBrush 设置为 在 QT/C++ 中绘制文本
- 除非重新绘制大小,否则SDL_Texture在调整大小后呈现黑色
- 绘制文本问题
- 在 QT C++中绘制/操作多边形
- 如何在 Gnuplot 中分别绘制 2 个文件数据?我有一个文件"sin.txt",另一个文件"cos.txt",我想将它们分别绘制在一个图表上
- 在现代OpenGL中,绘制GL_TRIANGLE奇怪的z轴行为的填充圆
- OpenGL 着色器不绘制任何东西 - 糟糕的精灵类
- 使用 QtConcurrent 加载 Pixmap 并绘制它