Bootsie123
Bootsie123

Reputation: 161

QML: Setting "source" property for image causes it to disappear

What I'm trying to do is update the source of an image with QML in PyQt5. When I use element.setProperty("source", "./testImage.png") to change the image I get the following error message.

QML Image: Protocol "" is unknown

Any idea on how to fix this?

I've looked at other ways to interact with QML elements and if possible I'd like to stick with changing the image through Python code rather then through just QML.

main.py

from PyQt5.QtWidgets import *
from PyQt5.QtQml import *
from PyQt5.QtCore import *
from PyQt5.QtQuick import *
from PyQt5 import *

import sys
import resource_rc

class MainWindow(QQmlApplicationEngine):
    def __init__(self):
        super().__init__()
        self.load("main.qml")
        self.rootContext().setContextProperty("MainWindow", self)

        self.window = self.rootObjects()[0]

        self.cardLeft = self.window.findChild(QObject, "cardLeft")

    @pyqtSlot()
    def changeImage(self):
        self.cardLeft.setProperty("source", "./images/3_of_clubs.png")

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = MainWindow()

    sys.exit(app.exec_())

main.qml

import QtQml 2.11
import QtQuick 2.3
import QtQuick.Controls 2.1
import QtQuick.Window 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.11

ApplicationWindow{
    id: screen
    width:  720
    height: 490
    visible: true
    Material.theme: Material.Dark

    Item {
      id: cards
      width: parent.width
      height: parent.height - toolBar.height
      anchors {
        top: parent.top;
        bottom: toolBar.top;
        bottomMargin: 10
      }

      RowLayout {
        anchors.fill: parent
        spacing: 20

        Image {
          objectName: "cardLeft"
          id: cardLeft
          Layout.fillWidth: true
          Layout.maximumHeight: 250
          Layout.minimumHeight: parent.height
          Layout.margins: 20

          source: "./testImage.png"
          fillMode: Image.PreserveAspectFit
        }
      }
    }

    Button {
      Layout.alignment: Qt.AlignHCenter
      Layout.fillWidth: true
      Layout.fillHeight: true
      Layout.maximumHeight: 100
      Layout.maximumWidth: 300
      Layout.margins: 20

      text: qsTr("Change Image")

      highlighted: true
      Material.accent: Material.color(Material.LightGreen)

      onClicked: MainWindow.changeImage()
    }
}

Upvotes: 1

Views: 1276

Answers (1)

eyllanesc
eyllanesc

Reputation: 243983

You have to pass a QUrl for it you must use QUrl::fromLocalFile():

import os
import sys
from PyQt5 import QtCore, QtGui, QtQml
# import resource_rc

dir_path = os.path.dirname(os.path.realpath(__file__))


class MainWindow(QtQml.QQmlApplicationEngine):
    def __init__(self):
        super().__init__()
        self.load(QtCore.QUrl.fromLocalFile(os.path.join(dir_path, "main.qml")))
        self.rootContext().setContextProperty("MainWindow", self)

        if self.rootObjects():
            self.window = self.rootObjects()[0]
            self.cardLeft = self.window.findChild(QtCore.QObject, "cardLeft")

    @QtCore.pyqtSlot()
    def changeImage(self):
        if self.cardLeft:
            url = QtCore.QUrl.fromLocalFile(os.path.join(dir_path, "images/3_of_clubs.png"))
            self.cardLeft.setProperty("source", url)


if __name__ == '__main__':
    app = QtGui.QGuiApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

Upvotes: 2

Related Questions