gpt4 book ai didi

c++ - 如何正确使用Qt QML Image Provider

转载 作者:太空宇宙 更新时间:2023-11-04 12:57:49 26 4
gpt4 key购买 nike

我正在开发一个跨平台应用程序,它在 C++ 端通过 REST API 接收图像,然后通过 ImageProvider 将它们发送到 QML,这似乎会导致内存泄漏。内存泄漏的速度与图像的大小和更新间隔成正比。

我尝试禁用 QML Image 的缓存但没有改变任何东西。我还尝试通过在图像更新时运行 gc() 来强制垃圾收集,但仍然没有成功。

为了完全确定这不是我的错误编码等造成的。我创建了一个最小的演示,它基于这个 Qt 示例: http://doc.qt.io/qt-5/qquickimageprovider.html

唯一的补充是我增加了图像尺寸并实现了将红色图像换成黄色图像的方法。运行该应用程序后,图像每秒都会改变颜色,并且内存会不断增加。该图像具有 10000x10000 尺寸,因此您可以清楚地看到增加量。即使图像是 10x10 或任何其他尺寸,内存泄漏仍然会发生。

我已经成功地在 Android 手机、Macbook 以及运行 Fedora 的 PC 上重现了这个问题。

如果您发现发生这种情况的任何原因,请告诉我,如果这是一个错误,我可以使用什么解决方法将图像发送到 QML。我需要在通过 REST API 收到这些图像后立即发送它们,因此通常约为 30FPS。

任何帮助将不胜感激!完整的解决方案如下。 Image 和 Pixmap 提供程序都会导致相同的问题。如果您想测试原始 Qt 代码,请在 main.cpp 中更改 QQuickImageProvider::Image QQuickImageProvider::Pixmap。

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QThread>

#include "imageProvider.h"

class MyThread : public QThread
{
public:
MyThread(QObject* object) : m_object(object)
{
}

virtual void run()
{
QVariant colour = "red";

while (isRunning())
{
QMetaObject::invokeMethod(
m_object, "updateViewport", Q_ARG(QVariant, colour));

if (colour == "red")
{
colour = "yellow";
}
else
{
colour = "red";
}

QThread::sleep(1);
}
}

private:
QObject* m_object;
};

int main(int argc, char* argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);

QQmlApplicationEngine engine;
engine.addImageProvider(QLatin1String("imageprovider"),
new ImageProvider(QQuickImageProvider::Image));
QQmlComponent component(&engine, "qrc:/main.qml");
QObject* object = component.create();
MyThread* myThread = new MyThread(object);
myThread->start();

return app.exec();
}

imageProvider.h

#ifndef IMAGE_PROVIDER_H
#define IMAGE_PROVIDER_H

#include <QQuickImageProvider>
#include <QPixmap>
#include <QPainter>

class ImageProvider : public QObject, public QQuickImageProvider
{
Q_OBJECT
public:
explicit ImageProvider(ImageType type, Flags flags = 0);
QPixmap requestPixmap(const QString& id,
QSize* size,
const QSize& requestedSize);
QImage requestImage(const QString& id,
QSize* size,
const QSize& requestedSize);
};
#endif // IMAGE_PROVIDER_H

imageProvider.cpp

#include "imageProvider.h"

using namespace std;

ImageProvider::ImageProvider(ImageType type, Flags flags)
: QQuickImageProvider(type, flags)
{
}

QPixmap ImageProvider::requestPixmap(const QString& id,
QSize* size,
const QSize& requestedSize)
{
int width = 10000;
int height = 10000;

if (size)
{
*size = QSize(width, height);
}

QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : width,
requestedSize.height() > 0 ? requestedSize.height() :
height);
pixmap.fill(QColor(id).rgba());
QPainter painter(&pixmap);
QFont f = painter.font();
f.setPixelSize(20);
painter.setFont(f);
painter.setPen(Qt::black);
if (requestedSize.isValid())
painter.scale(requestedSize.width() / width,
requestedSize.height() / height);
painter.drawText(QRectF(0, 0, width, height), Qt::AlignCenter, id);

return pixmap;
}

QImage ImageProvider::requestImage(const QString& id,
QSize* size,
const QSize& requestedSize)
{
return QImage(10000, 10000, QImage::Format_ARGB32);
}

ma​​in.qml

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("MemoryLeakDemo")

function updateViewport(colour) {
image.source = "image://imageprovider/" + colour;
}

Image {
id: image
cache: false
}
}

memoryLeakDemo.pro

QT += qml quick

CONFIG += c++11

SOURCES += main.cpp \
imageProvider.cpp

RESOURCES += qml.qrc

DEFINES += QT_DEPRECATED_WARNINGS

qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += imageProvider.h

最佳答案

Qt 已确认这是一个错误,因此希望它能尽快得到修复:

https://bugreports.qt.io/browse/QTBUG-62600

在此期间,您可以尝试应用补丁并从源代码编译框架:

https://codereview.qt-project.org/#/c/200715/

希望这对您有所帮助!

关于c++ - 如何正确使用Qt QML Image Provider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45755655/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com