QTreeWidget - 重新计算每行内容的行高?

Posted

技术标签:

【中文标题】QTreeWidget - 重新计算每行内容的行高?【英文标题】:QTreeWidget - re-calculate row height per row content? 【发布时间】:2017-03-22 21:44:57 【问题描述】:

这是一个快速的。我在我可以展开-收缩的每个 QTreeWidgetItem 中放置了一个布局包含 10 个按钮的 QWidget。

如果我收缩 QWidget(hide),那么该行将保持相同的高度。它应该被调整为小很多,只包含取消隐藏按钮。该行占用的空间仍然是空的。只有当我添加一个新的小部件时。行的高度被重新计算。扩展也是如此。如果我展开小部件,它的高度仍然是 17 像素。只有当我添加一个新的小部件时,才会重新计算行的高度。

我可以调用 QTreeWidget 中的内置函数来更新其行高 - 内容,还是需要循环遍历每个项目并手动调整其高度?

在 QTreeWidgetItem 中放置一个包含布局和许多小部件的 QWidget 也是一个好主意吗?如果我想说 500 个 QtreeWidgetItems,每个 QTreeWidget 都有 20 个 Buttons/etc 项目?

问候 大流士

编辑1。

我花了很多时间在上面。尝试了不同的路径,但到目前为止没有运气。我附上了我的粗略代码来显示这个问题。只需单击隐藏 1-2 次即可查看会发生什么。我很难理解“sizeHint”thini 是如何工作的......

在下面附上我的测试。

import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

sys._excepthook = sys.excepthook


def my_exception_hook(exctype, value, traceback):
    # print(exctype, value, traceback)
    sys._excepthook(exctype, value, traceback)
    sys.exit(1)


sys.excepthook = my_exception_hook


class myWidget(QWidget):
    def __init__(self, parent, something):
        super(QWidget, self).__init__()
        self.MW = parent
        self.MWa = something
        self.lay_main = QGridLayout()
        self.setLayout(self.lay_main)

        self.le_lineA = QLineEdit()
        self.btn_a = QPushButton("Hey")
        self.btn_a.clicked.connect(self.hideunhide)
        self.subWidget = QWidget()
        self.subLay = QGridLayout()
        self.subWidget.setLayout(self.subLay)

        self.btn_b = QPushButton("Boo")
        self.lay_main.addWidget(self.btn_a)
        self.lay_main.addWidget(self.subWidget)
        self.subLay.addWidget(self.le_lineA)
        self.subLay.addWidget(self.btn_b)
        print("Im created :- )")
        self.size = False

    def hideunhide(self):
        if self.subWidget.isHidden():
            self.subWidget.show()
            self.size = True
            self.MW.sizeHint(1)
            self.MW.setSizeHint(0, QSize(0, 0))

        else:
            self.subWidget.hide()
            self.size = False
            self.MW.sizeHint(1)
            self.MW.setSizeHint(0, QSize(0, 0))


class widgetItemDictUpdate(QTreeWidgetItem):
    def __init__(self, parent, MW, title, dicId):
        super(QTreeWidgetItem, self).__init__(parent)
        self.MW = MW
        self.dicId = dicId


class myDelegate(QItemDelegate):
    def __init__(self, mw):
        self.MW = mw
        super(QItemDelegate, self).__init__()

    def sizeHint(self, option, index):
        print("myDelegate", option, index)
        if self.MW.itemFromIndex(index).layer.size:
            return QSize(100, 100)
        return QSize(100, 30)


class treeWidget(QTreeWidget):
    def __init__(self, MW):
        QTreeWidget.__init__(self)
        self.setUniformRowHeights(False)
        self.MW = MW
        self.itemClicked.connect(self.printClick)
        self.setHeaderItem(QTreeWidgetItem(["Name", "ProgressBar", "extra", "", "", "", "", "", "", "", ""]))
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.dragItems = []

        self.lastHidenItemsArray = []
        self.hiddenItemsSet = []

        self.delg = myDelegate(self)
        self.setItemDelegate(self.delg)
        self.addItems(self.invisibleRootItem())

    def printClick(self, item, column):
        print("Clicked")

    def addItems(self, parent):
        testParent = self.addSlave(parent, 'RandomA', 50)
        testParent = self.addSlave(parent, 'RandomB', 60)
        testParent = self.addSlave(parent, 'RandomBX', 60)
        testParent = self.addSlave(parent, 'RandomBcvas', 60)

    def addSlave(self, parent, title, id, expanded=True, visible=True):
        item = widgetItemDictUpdate(parent, self, title, id)
        myLayer = myWidget(item, self)
        item.setText(0, title)
        item.layer = myLayer
        self.setItemWidget(item, 1, myLayer)
        item.id = id
        item.type = 1

        return item


class Window(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.treeWidget = treeWidget(self)
        layout = QVBoxLayout()
        layout.addWidget(self.treeWidget)
        self.setLayout(layout)
        self.setGeometry(1000, 500, 500, 500)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

【问题讨论】:

嘿@Dariusz。我有另一个想法并深入研究了文档,结果发现 QTableWidgets / QTableViews 具有内置的动态行高,您可以使用函数 QTableWidget::setRowHeight( int index, int height ) 进行修改。你是锁定在使用 QTreeWidget 还是可以使用 QTableWidget 代替? 嘿@aatwo。再次开始处理这个问题。不确定 QTablewidgets 是否可以工作,我可以像使用 QTreeWidget 一样将行向上/向下/分组吗?我尝试了一些基本测试,但到目前为止没有运气 所以这取决于你的数据结构。如果您实际上正在使用 QTreeViews 功能的树部分,即一个或多个行是另一行的子行,那么不幸的是您几乎被锁定了。我只是想指出他们对行高的卓越控制!不过,您绝对可以向上/向下移动行。 【参考方案1】:

据我所知,虽然您可以通过将表实现为 QTreeView + QSortFilterProxyModel 子类对 (PyQt: How Can I set row heights of QTreeView) 来实现动态行高,但无法直接调整行的大小

或者,我想从表中删除小部件 (removeItemWidget),然后立即重新添加它会导致行大小重新计算,尽管我没有测试过。

至于我对这种表格内布局设置的看法,有两点值得注意:

Qt 布局的填充和调整大小都很慢。 具有可变行高的 Qt 表通常很慢。

话虽如此,500 并不是一个巨大的数字。我可能会拼凑一个快速原型,看看它在一系列机器上的性能如何,看看性能是否可以接受,然后如果速度太慢,我会担心探索其他路线。我预计这种情况下的性能将主要取决于布局的复杂程度。

【讨论】:

嘿 @aatwo 感谢您对 removeItemWidget 的建议,我正在考虑 atm。我添加了我当前尝试解决问题的示例代码......新的理由。

以上是关于QTreeWidget - 重新计算每行内容的行高?的主要内容,如果未能解决你的问题,请参考以下文章

wpf datagrid row height 行高自动计算使每行行高自适应文本

QtreeWidget的相关问题

QT如何设置QTreeWidget行高?

如何在 QTreeWidget/QTreeView 中获取行高

包含小部件和设置行高问题的 QTreeWidget

Python如何改变tkinter.ttk.Treeview表格组件的每行的行高?