PyQt: How Can I set row heights of QTreeView

喜你入骨 提交于 2019-12-08 22:14:45

问题


In PyQt, I am looking for a way to set the height of rows in a QTreeView (similarly to QTableView.setRowHeight(row, row_height), but QTreeView does not have this function). QAbstractItemModel is used to set the tree model. I read some suggestions here using and sub-classing QAbstractItemDelegate.sizeHint(option, index) but I don't know exactly how to call them correctly within my tree model.

Any minimal code or suggestion would be greatly appreciated. Thanks.


回答1:


The QTreeView works out a height for each row based on the data and size hints returned for each item. I think you probably just need to return size hints, either for all your items, or at least the first row (if you have setUniformRowHeights(True)). Incidentally this can significantly improve performance and so you should set it if you can.

So you just need to implement your AbstractItemModel.data() method to return a size hint in the SizeHintRole. Something like this:

def data(self, index, role = QtCore.Qt.DisplayRole):
    #  Check the index, possibly return None
    if role == QtCore.Qt.DisplayRole:
        # Return the data
    elif role == QtCore.Qt.SizeHintRole:
        return QtCore.QSize(item_width,item_height)
    # Other roles - maybe return None if you don't use them.

EDIT: Big example

You say you are still having trouble so here is a complete working example, based on the standard QT itemviews example. Try varying the QSize returned in the data method to see how the view changes:

import sys
from PySide import QtCore,QtGui

class TreeItem(object):
    def __init__(self, data, parent=None):
        self.parentItem = parent
        self.data = data
        self.childItems = []

    def appendChild(self, item):
        self.childItems.append(item)

    def row(self):
        if self.parentItem:
            return self.parentItem.childItems.index(self)
        return 0


class TreeModel(QtCore.QAbstractItemModel):
    def __init__(self, parent=None):
        super(TreeModel, self).__init__(parent)
        self.rootItem = TreeItem(None)
        for i,c in enumerate("abcdefg"):
            child = TreeItem([i,c],self.rootItem)
            self.rootItem.appendChild(child)
        parent = self.rootItem.childItems[1]
        child = TreeItem(["down","down"],parent)
        parent.appendChild(child)

    def columnCount(self, parent):
        return 2

    def data(self, index, role):
        if not index.isValid():
            return None
        if role == QtCore.Qt.DisplayRole:
            item = index.internalPointer()
            return item.data[index.column()]
        elif role == QtCore.Qt.SizeHintRole:
            print "giving size hint"
            return QtCore.QSize(40,40)

        return None


    def flags(self, index):
        if not index.isValid():
            return QtCore.Qt.NoItemFlags
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def headerData(self, section, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return ["A","B"][section]
        return None

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()

        childItem = parentItem.childItems[row]
        if childItem:
            return self.createIndex(row, column, childItem)
        else:
            return QtCore.QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()
        parentItem = index.internalPointer().parentItem
        if parentItem == self.rootItem:
            return QtCore.QModelIndex()
        return self.createIndex(parentItem.row(), 0, parentItem)

    def rowCount(self, parent):
        if parent.column() > 0:
            return 0
        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()
        return len(parentItem.childItems)



if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    model = TreeModel()

    view = QtGui.QTreeView()
    view.setModel(model)
    view.setWindowTitle("Simple Tree Model")
    view.show()
    sys.exit(app.exec_())



回答2:


Don't know about Python, but C++ code would be like this:

model->setData(model->index(/*your index*/), QSize(20, 20), Qt::SizeHintRole);

And you need to set it for all items in your tree.

If you want use QItemDelegate - you no need to call this function, you just set your delegate to view, like this (C++ code again, but main idea is the same):

treeView->setItemDelegate(new MyDelegate(this));

Than view will use it when it need it.




回答3:


For the PySide bindings, here's the Python code for the custom delegate on the AbstractItemModel.

from PySide import QtCore, QtGui

tree = QTreeView()
tree.model = QtGui.QAbstractItemModel()
tree.setModel(tree.model)

size = QtCore.QSize(20, 20)
index = tree.model.index(row, col)   # row, col are your own
tree.model.setData(index, size, QtCore.Qt.SizeHintRole)

delegate = MyDelegate()
tree.setItemDelegate(delegate)

This is just translating the code from @RazrFalcon to Python, and was requested by another user.




回答4:


It's pretty simple to do this with stylesheet :

self.setStyleSheet("QTreeView::item { padding: 10px }")


来源:https://stackoverflow.com/questions/32229314/pyqt-how-can-i-set-row-heights-of-qtreeview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!