Skip to content

Instantly share code, notes, and snippets.

@poptosic
Created March 16, 2017 11:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save poptosic/b341511d3a0a6b7f09278ce5da7e20e7 to your computer and use it in GitHub Desktop.
Save poptosic/b341511d3a0a6b7f09278ce5da7e20e7 to your computer and use it in GitHub Desktop.
Deadlock when endResetModel() triggers ImageProvider asynchronously
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QAbstractListModel
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import QVariant
from PyQt5.QtGui import QImage
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtQuick import QQuickImageProvider
from PyQt5.QtWidgets import QApplication
class TestObj:
def __init__(self, i):
self.i = i
@property
def avatar(self):
return self.i
class MyListModel(QAbstractListModel):
ROLE_NAMES = {
(Qt.UserRole + 1): b'avatar'
}
def __init__(self, parent=None):
self.storage = []
super().__init__(parent)
def rowCount(self, parent=None, *args, **kwargs):
return len(self.storage)
def data(self, index, role=None):
if index.row() < 0 or index.row() >= len(self.storage):
return QVariant()
obj = self.storage[index.row()];
if role == (Qt.UserRole + 1):
return obj.avatar
return QVariant()
def roleNames(self):
return self.ROLE_NAMES
@pyqtSlot()
def update(self):
print('Resetting')
self.beginResetModel()
self.storage = [TestObj(i) for i in range(10)]
self.endResetModel()
print('Done')
class TestImageProvider(QQuickImageProvider):
def __init__(self):
super().__init__(QQuickImageProvider.Image)
def requestImage(self, image_id, size):
return QImage('test.png'), size
application = QApplication(sys.argv)
provider = TestImageProvider()
model = MyListModel()
engine = QQmlApplicationEngine()
engine.addImageProvider('test', provider)
engine.rootContext().setContextProperty('testmodel', model)
engine.load('test.qml')
sys.exit(application.exec_())
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
id: root
visible: true
width: 640
height: 480
title: qsTr("ImageProvider test")
ListView {
id: listView
model: testmodel
anchors.fill: parent
anchors.bottomMargin: 50
anchors.topMargin: 50
spacing: 2
delegate: Rectangle {
width: parent.width
height: 10
Image {
source: "image://test/a" + avatar
onSourceChanged: console.log(source)
asynchronous: true
}
}
}
Rectangle {
width: 100
height: 50
anchors.bottom: parent.bottom
color: "#eeeeee"
Text {
text: "Click me"
}
MouseArea {
anchors.fill: parent
onClicked: {
testmodel.update()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment