将具有多个状态的 QtQuick 项目保存到 .png 文件

Saving QtQuick Items with multiple states to .png files

我正在尝试将具有多个状态的视觉项目保存为 .png 图像(每个状态一个 png)

我在 onStateChanged 信号处理程序中调用项目的 grabToImage() 方法,但图像仅在最后一次状态更改发生后才保存,只创建一个与项目的最后设置状态对应的图像。

我还尝试在 python 端调用 saveToFile() 但这会导致运行时错误(请参阅 python 代码中的注释)

grab_states.py

from PySide2.QtCore import QUrl
from PySide2.QtWidgets import QApplication
from PySide2.QtQuick import QQuickView


app = QApplication([])

view = QQuickView()
view.setSource(QUrl('grab_states.qml'))
view.show()

rect = view.rootObject()
rect.setState('off')
rect.setState('on')

# RuntimeError: Internal C++ object (PySide2.QtQuick.QQuickItemGrabResult) already deleted.
# rect.grabToImage().data().saveToFile(rect.property('state') + ".png")

app.exec_()

grab_states.qml

import QtQuick 2.0

Rectangle {
  id: rect
  width: 100
  height: 100

  color: "black"

  states: [
      State {name: "off"; PropertyChanges{target: rect; color: "red"}},
      State {name: "on";  PropertyChanges{target: rect; color: "green"}}
  ]

  onStateChanged: {
    print('stateChaged: ' + state)
    rect.grabToImage(function(result){
      print("saveToFile: " + rect.state);
      result.saveToFile(state + '.png');
      }
    )
  }
}

saveToFile 函数按预期调用了两次,但仅在所有状态更改发生后才调用,因此我只得到一张显示最后状态并覆盖第一张图像的图像。如果我使用不同的文件名来防止覆盖,那么我会得到两张图片,都显示最终状态。

如何为项目的每个状态保存相应的图像?

您有 2 个错误:

  • 您正在更改您的状态,但没有确保您已经保存了图像。

  • 通过上述操作,grabToImage 中的状态值将被更新并指向之前的状态。

在这两种情况下,解决方案都是确保保存图像以更改状态。综合以上,解决方案如下:

*.py

from PySide2 import QtCore, QtGui, QtQuick

if __name__ == '__main__':
    import sys
    app = QtGui.QGuiApplication(sys.argv)
    view = QtQuick.QQuickView()
    view.setSource(QtCore.QUrl('grab_states.qml'))
    view.show()
    rect = view.rootObject()
    rect.setProperty("currentIndex", 0)
    sys.exit(app.exec_())

*.qml

import QtQuick 2.0

Rectangle {
    id: rect
    width: 100
    height: 100
    color: "black"
    property int currentIndex: -1
    onCurrentIndexChanged: if(currentIndex >= 0 && currentIndex < states.length) state = states[currentIndex].name
    states: [
        State {name: "off"; PropertyChanges{target: rect; color: "red"}},
        State {name: "on";  PropertyChanges{target: rect; color: "green"}}
    ]

    onStateChanged: {
        rect.grabToImage(function(result){
            result.saveToFile(state + ".png");
            currentIndex+= 1;
            console.log(filename);
        })
    }
}