How to reimplement QTextDocument.createObject
?
this method plays a role in making QTextFrame
, QTextList
, QTextTable
or other QTextObject
.
According to woboq, I think my reimplementation is the same.
But kernel stops.
Why? What is my code short of?
from PySide2 import QtWidgets
from PySide2 import QtGui
from PySide2 import QtCore
import PySide2
import sys
import os
dirname = os.path.dirname(PySide2.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path
class TextEdit(QtWidgets.QTextEdit):
def __init__(self, parent=None):
super(TextEdit, self).__init__(parent=None)
document = TextDocument(self)
self.setDocument(document)
class TextDocument(QtGui.QTextDocument):
def __init__(self, parent=None):
super(TextDocument, self).__init__(parent=None)
self.setParent(parent)
def createObject(self, f):
obj = QtGui.QTextObject(self)
if f.isListFormat():
obj = QtGui.QTextList(self)
elif f.isTableFormat():
obj = QtGui.QTextTable(self)
elif f.isFrameFormat():
obj = QtGui.QTextFrame(self)
return obj
def main():
if QtWidgets.QApplication.instance() is not None:
app = QtWidgets.QApplication.instance()
else:
app = QtWidgets.QApplication([])
mainwindow = TextEdit()
mainwindow.show()
sys.exit(QtWidgets.QApplication.exec_())
if __name__ == "__main__":
main()
It seems to me that it is a bug (I have tested it with PyQt5 and it works correctly), the problem to be the life cycle of the QTextObject since as in C++ the life cycle is undefined since it is a pointer but being a child of QTextDocument So its life cycle is that of the QTextDocument, but in python it seems that it considers it an object of limited scope(local variable) not respecting the ownership that the QTextDocument has over this since it is its parent. A workaround seems to be making obj an member of the class:
def createObject(self, f):
self.obj = QtGui.QTextObject(self)
if f.isListFormat():
self.obj = QtGui.QTextList(self)
elif f.isTableFormat():
self.obj = QtGui.QTextTable(self)
elif f.isFrameFormat():
self.obj = QtGui.QTextFrame(self)
return self.obj
Or using a container that is a member of the class.
class TextDocument(QtGui.QTextDocument):
def __init__(self, parent=None):
super(TextDocument, self).__init__(parent)
self.objs = []
def createObject(self, f):
obj = QtGui.QTextObject(self)
if f.isListFormat():
obj = QtGui.QTextList(self)
elif f.isTableFormat():
obj = QtGui.QTextTable(self)
elif f.isFrameFormat():
obj = QtGui.QTextFrame(self)
self.objs.append(obj)
return obj
I prefer the second workaround since in the case of the first one you could generate problems if you create several QTextObject since the previous one would be deleted.
Finally I recommend reporting the bug.
The handling of the life cycle of some objects seems a persistent bug in PySide2.