qt - QML如何绘制与grabToImage()不同的图像

标签 qt qml

是否有任何可能的方法使 grabToImage() 缓冲区与 GUI 中显示的缓冲区不同?我在 GUI 中使用不带图例的 ChartView,并希望将其导出为带图例的 PNG。所以我尝试:

chartView.legend.visible = true
chartView.update()
chartView.grabToImage(function(result) {
    console.log("grabbed")

    var path = filename.toString().replace(/^(file:\/{2})/,"");
    console.log(path + result.saveToFile(path));
    chartView.legend.visible = false
    update();
});

但这两个更新仅在控件退出此函数后发生,因此我不会用 PNG 绘制图例。我还希望图例的外观不会被用户注意到。 QML 有什么方法可以做到这一点吗?

最佳答案

我不确定我的理解是否正确。

我的建议是,不要获取您显示的 Item,而是获取它的副本,然后根据需要进行修改。
这里的“复制”并不意味着您拥有同一个对象两次,而是通过使用ShaderEffectSource将其渲染两次。 。在将此 ShaderEffectSource 抓取到图像之前,您可以添加任何您喜欢的内容。

在我的示例中,我显示了一个带有漂亮渐变的简单矩形。我保存的是由文本“我是传奇”扩展的相同矩形。用户在任何时候都不会看到此文本出现在 View 中。

Rectangle {
    id: commonView
    width: 200
    height: 200
    gradient: Gradient {
        GradientStop { position: 0; color: 'steelblue' }
        GradientStop { position: 1; color: 'orange' }
    }
    MouseArea {
        anchors.fill: parent

        // don't grab the rectangle itself.
        onClicked: legendView.grabToImage(function(result) {
            console.log(result.saveToFile("something.png"));
        });
    }
}

ShaderEffectSource {
    id: legendView
    visible: false // Does not need to be shown.
    sourceItem: commonView
    width: 200
    height: 200
    Text {
        anchors {
            right: parent.right
            bottom: parent.bottom
        }
        text: 'I am legend'
    }
}

您可以通过仅激活 ShaderEffectSource 甚至在需要时创建来优化性能。

您可以使用 ShaderEffectSource.live 属性来禁用其更新。然后使用 scheduleUpdate() 触发更新。

这可能看起来像这样:

Rectangle {
    id: commonView
    width: 200
    height: 200
    gradient: Gradient {
        GradientStop { position: 0; color: 'steelblue' }
        GradientStop { id: gs1; position: 1; color: 'orange' }
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            gs1.position -= 0.1
            legendView.save()
        }
    }
}

ShaderEffectSource {
    id: legendView
    y: 200
    visible: false // Do not render it (will only be rendered when called grapToImage()
    sourceItem: commonView
    width: 200
    height: 200
    live: false // Will only be updated, when explicitly called for
    function save() {
        console.log('Schedule Save')
        scheduleUpdate() // explicitly update. grabToImage() will force rendering afterwards.
        legendView.grabToImage(function(result) {
                        console.log(result.saveToFile("something" +gs1.position.toFixed(1) + ".png"));
                    })
    }

    // Put additional stuff on it.
    Text {
        anchors {
            right: parent.right
            bottom: parent.bottom
        }
        text: 'I am legend!'
    }
}

关于qt - QML如何绘制与grabToImage()不同的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44120067/

相关文章:

c++ - Qt Connect 无法连接到插槽

c++ - 画椭圆延迟再画一个

c++ - 使用 QList<MyObject*> 调用 setContextProperty()

qt - 在 QML 中根据位置更新对 MapQuickItem 进行动画处理

c++ - 在 QML 文件中使用 C++ 类变量

c++ - 如何使用Qt实现三态按钮

c++ - Qt QTimeLine 跳过第一帧

python - Qt CSS 错误处理

qt - 在 QML 中动态重新调整对象的父级在初始加载时失败

c++ - 具有 qml 函数和 c++ 插槽的最佳方法,反之亦然