gpt4 book ai didi

c++ - qml Canvas ,每次从c++调用js函数后都会重置上下文2d

转载 作者:太空宇宙 更新时间:2023-11-04 13:06:51 27 4
gpt4 key购买 nike

我有 Qt Quick Controls 2 应用程序。在 main.qml 中,除了 ScrollView 中的 Canvas 之外,我还有其他东西:

Rectangle {
id: graph
width: mainArea.width / 3 - 14;
height: mainArea.height - 20;
ScrollView{
anchors.fill: parent;
Canvas {
id:canvasGraph;
width: graph.width;
height: graph.height;
property bool paintB: false;

property string colorRect: "#FFFF40";
property string name: "ELF header";

property int paintX: 0;
property int paintY: 0;

property int widthP: 160;
property int heightP: 30;

property int textX: (paintX + (widthP / 2)) - 15/*func return int length of text*/;
property int textY: (paintY + (heightP / 2)) + 3;

onPaint:{
if (paintB){
var ctx = canvasGraph.getContext('2d');
ctx.beginPath();
ctx.font = "normal 12px serif";
ctx.fillStyle = colorRect;
ctx.strokeRect(paintX, paintY, widthP, heightP);
ctx.fillRect(paintX, paintY, widthP, heightP);
ctx.strokeText("ELF header", textX, textY);
ctx.closePath();
ctx.save();
}
}
MouseArea{
id: canvasArea;
anchors.fill: parent;
onPressed: {
paint(mouseX,mouseY,"aaa",1);
}
}
}
}
}

一开始我尝试通过js函数绘制到canvas中,这里:

function paint(x, y, name, type) {
canvasGraph.paintB = true;
canvasGraph.paintX = x;
canvasGraph.paintY = y;
canvasGraph.requestPaint();
}

此函数是通过在 Canvas 上按下鼠标来调用的。它工作得很好,它一个接一个地绘制矩形。但只有一个问题是,在调整应用程序窗口大小后,除了最后一个以外的所有矩形都丢失了。但这不是主要问题,因为它有效并且我可以稍后解决这个问题。

要绘制图表,我需要 C++ 库(ELFIO,用于读取 ELF 文件)。所以在 main.cpp 中我有两个对象。首先允许我从一些 C++ 类的 main.qml 函数中调用。第二个允许我从 C++ 调用 js 函数。这是 main.cpp:

QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);

QScopedPointer<elfFile> elfFileObj(new elfFile);

QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));

engine.rootContext()->setContextProperty("elfFileObj", elfFileObj.data()); //this is for calling c++ from qml

QObject *rof = engine.rootObjects().first();
elfFileObj.data()->rofS = rof; //this one is for calling js func from c++
return app.exec();

你怎么看,读取 ELF 文件是从对象 elfFileObj 管理的,其中是保存加载的 ELF 文件的公共(public)变量和保存访问 main 的对象的变量 rofS .qml 到 js 函数。

elfFileObj 中是 Q_INVOKABLE int loadELF(QString fileName); 其中 Q_INVOKABLE 是宏,它确保可以从 qml 文件调用此函数。功能:

int elfFile::loadELF(QString fileName)
{
string fileNameReal = (fileName).toStdString().substr(7);
if (!reader.load(fileNameReal.c_str())){
return -1;
}

QVariant x(30);
QVariant y(10);
QVariant name("ELF header");
QVariant type(1);

QMetaObject::invokeMethod(rofS, "paint", Q_ARG(QVariant,x), Q_ARG(QVariant,y), Q_ARG(QVariant,name), Q_ARG(QVariant,type));
y = QVariant(40);
QMetaObject::invokeMethod(rofS, "paint", Q_ARG(QVariant,x), Q_ARG(QVariant,y), Q_ARG(QVariant,name), Q_ARG(QVariant,type));
}

我尝试一个接一个地画两个矩形。 QMetaObject::invokeMethod 应该调用在 (x,y) 上绘制矩形的 js 函数。其他参数此时不可用。

主要问题:它在 Canvas 上绘制矩形,但每次调用 invokeMethod 后 Canvas 都会被清除。所以在 Canvas 上总是只留下最后一个矩形。

有人知道如何保存 Canvas 的实际状态吗?谢谢你的帮助。这不是漂亮的代码,但这是我第一次使用 qml。

最佳答案

作为命令式绘图 API 的 Canvas 只有一个像素数据的哑缓冲区。一旦绘制调用完成,它就没有矩形或其他任何对象的概念。因此,您对它通过您的 onPaint 处理程序显示的所有内容负责。它不会从一帧到另一帧清除 Canvas 内容(作为优化),但它会(必要时)在您调整窗口大小时清除它,因为它必须分配不同大小的缓冲区。

您可以在此处看到此行为:

import QtQuick 2.6

Canvas {
id: canvasGraph;
width: 500
height: 500
property int paintY: 10;

onPaint:{
var ctx = canvasGraph.getContext('2d');
ctx.beginPath();
ctx.font = "normal 12px serif";
ctx.fillStyle = "#ff0000";
ctx.strokeRect(10, paintY, 160, 30);
ctx.fillRect(10, paintY, 160, 30);
ctx.closePath();
ctx.save();
}

Timer {
interval: 16
running: true
repeat: true
onTriggered: {
canvasGraph.requestPaint();
canvasGraph.paintY += 10
if (canvasGraph.paintY > canvasGraph.height)
canvasGraph.paintY = 10
}
}
}

尝试使用 qmlscene 运行此示例并调整窗口大小。您会注意到所有内容在调整大小时都被清除,除了它绘制的一个矩形。

因此,如果您希望保留所有矩形,那么您需要每次都在 onPaint 处理程序中绘制它们(并使用 clearRect 或其他方法来填充背景以去除不存在的东西不再属于那里,如果你正在移动东西或让它们不可见)。

另一方面,我无法直接解释为什么 invokeMethod 会导致它清除,因为您没有真正提供足够的代码。可能是它正在调整 Canvas 的大小(导致缓冲区重新分配并被清除)。无论哪种方式,鉴于上述情况,我会说它并不是那么相关。

毕竟,虽然我不了解您正在制作的内容的完整背景,但我建议 Canvas 可能不是您想要做的事情的最佳工具。您可能想查看 QQuickPaintedItem,或者(更好)使用自定义 QQuickItem 来组合您的场景,该自定义 QQuickItem 定位其他 QQuickItems(或 QSGNodes)。 Canvas(和 QQuickPaintedItem)虽然易于使用,但性能不是特别好。

关于c++ - qml Canvas ,每次从c++调用js函数后都会重置上下文2d,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41825220/

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