Issue
I tried to implement an own model representing a tree for making it possible for a QT view to access my database entities (its not possible for me to use QT's SQL support so I have to deal with models). It worked perfectly as I only used a table but by now I am struggling with adapting it for a tree model.
There are entities of one type 'A' and every of them has any amount of child entities (another entity type / table) here called 'B'.
In the beginning the tree view displayed nothing but when I used a table view for the same model at least empty cells were displayed. Now the program shuts more or less down direct after start.
I want to use my own delegates (a delete button in first column that works for the old table model) and I don't want to use QStandardItemModel because I would have to manage an item for each column per entity.
I've researched and was pretty sure that it would work if I implement:
columnCount
rowCount
index
parent
data
flags
headerData
where the first act different depending on the parent index so that for example rowCount for top level (QModelIndex()
) returns the count of A entities and for any index of an A entity the number of sub B entities.
I think the main problem is in my overloads of index
and parent
. I use the internal pointer of the index to store the parent index which I return in the parent method.
I tried a very simple example with a specified amount of rows and columns where the data method returns for Qt.DisplayRole
only a string of formatted row and column.
When I start my example for a few seconds a table is shown with my data and then the application shuts down without traceback.
Process finished with exit code -1073741819 (0xC0000005)
Regardless if I run the program in terminal or in PyCharm no traceback is generated.
QAbstractItemModelTest
also didn't displayed anything.
import typing
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTreeView, QTableView, QHBoxLayout
from PyQt5.QtCore import QModelIndex, Qt, QAbstractItemModel
# Logging also doesn't help
import logging
logger = logging.getLogger(__name__)
logger.addHandler(stream := logging.StreamHandler())
logger.setLevel(logging.DEBUG)
stream.setLevel(logging.DEBUG)
class Model(QAbstractItemModel):
def __init__(self, parent):
super(Model, self).__init__(parent)
def columnCount(self, parent: QModelIndex = ...) -> int:
# only for tests
return 1
def rowCount(self, parent: QModelIndex = ...) -> int:
# only for tests
return 2
def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex:
# maybe this is method is false
if not self.hasIndex(row, column, parent):
return QModelIndex()
return self.createIndex(row, column, parent)
def parent(self, child: QModelIndex) -> QModelIndex:
# calling child.parent() causes immediate shutdown
if not child.isValid():
return QModelIndex()
return child.internalPointer() or QModelIndex()
def data(self, index: QModelIndex, role: int = ...) -> typing.Any:
if role == Qt.DisplayRole:
return f"{index.row()} {index.column()}"
pass
def flags(self, index: QModelIndex) -> Qt.ItemFlags:
return super(Model, self).flags(index) | Qt.ItemIsEnabled | Qt.ItemIsSelectable
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
# For displaying needed headers
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return f"Header {section}"
pass
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.model = Model(self)
self.table = QTableView(self)
self.tree = QTreeView(self) # the real needed
self.table.setModel(self.model)
# self.tree.setModel(self.model) causes not even displaying the window
self.main_layout = QHBoxLayout()
self.main_layout.addWidget(self.table)
self.main_layout.addWidget(self.tree)
self.setLayout(self.main_layout)
# Standard startup
if __name__ == "__main__":
app = QApplication(sys.argv)
wdg = Window()
wdg.show()
sys.exit(app.exec_())
Versions in venv:
- Python: 3.10.8
- pip: 23.2.1
- PyQt5 5.15.9
- PyQt5-Qt5: 5.15.2
- PyQt5-sip: 12.12.2
This is only a simple example and I don't know if the rest works if this works. I thought a QT tree model would be easier. I also tried to adopt https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html but I didn't find something that was in an iluminating way different.
Solution
The solution was to use an own tree item class with references to the other items like it is used in the documentation https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html. I first didn't understand why an own class is needed and why this isn't done by QT but as the comment explains it doesn't work to use the internalPointer to save an index. Therefore an own class is better.
Answered By - h-c
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.