qtreewidget 不需要的白色 space(额外的不可移动的行)

qtreewidget unwanted white space (additional unremovable rows)

我正在创建一个自定义 qtreewidget class,它会自动调整其 window 的大小以完全适合当前可见的元素(我不想滚动)。为此,我 运行 一个计数函数来查找打开的 qtreewidgetitems 及其子项的数量,并从那里设置一个固定的高度。然而,当我展开一个子窗口小部件(单击我的一个项目上的展开箭头)时,整个视图突然需要滚动,因为底部有额外的白色 space,尽管我的计数函数准确地计算了所需的高度。我该如何摆脱它?

下面是一个有效的 class,可以直接 运行。

import sys
from PyQt4 import QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class TreeWidget(QTreeWidget):
    def __init__(self, parent=None):
        super(TreeWidget, self).__init__()
        self.installEventFilter(self)
        self.setStyleSheet('''
            background: None;
            border: None;
            outline: None;
            outline-width: 0px;
            selection-background-color: blue;
            ''')
        header = QtGui.QTreeWidgetItem(["Tree", "First"])
        self.setAutoScroll(False)
        self.setHeaderItem(header)
        self.header().close()
        # self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

    def fill_item(self, item, value):
        item.setExpanded(False)
        if type(value) is dict:
            for key, val in sorted(value.iteritems()):
                child = QTreeWidgetItem()
                child.setText(0, unicode(key))
                # child.doubleClicked.connect(lambda: self.doubleClicked1(child))
                item.addChild(child)
                self.fill_item(child, val)
        elif type(value) is list:
            last = None
            for val in value:
                child = QTreeWidgetItem()
                if type(val) is dict:
                    item.addChild(child)
                    child.setText(0, '[dict]')
                    # child.doubleClicked.connect(lambda: self.doubleClicked1(child))
                    self.fill_item(child, val)
                    last = child
                elif type(val) is list:
                    self.fill_item(last, val)
                else:
                    item.addChild(child)
                    child.setText(0, unicode(val))
                    child.setText(1, 'test')
                    # child.doubleClicked.connect(lambda: self.doubleClicked1(child))
                    child.setExpanded(False)
                    last = child
        else:
            child = QTreeWidgetItem()
            child.setText(0, unicode(val))
            child.setText(1, 'test')
            # child.doubleClicked.connect(lambda: self.doubleClicked1(child))
            item.addChild(child)

    def fill_widget(self, value):
        self.clear()
        self.fill_item(self.invisibleRootItem(), value)

    def resizeEvent(self, event):
        self.resize()

    def resize(self):
        width = 50
        self.header().resizeSection(1, width)
        self.header().resizeSection(0, self.width()-width)
        height = self.visibleCount()
        print height/15
        self.setFixedHeight(height+0)

    def eventFilter(self, source, event):
        if source is self:
            if event.type() == 1:
                self.resize()
            elif event.type() == QEvent.Leave:
                self.clearSelection()
        return QtGui.QTreeWidget.eventFilter(self, source, event)

    def visibleCount(self, parent=0):
        height = 0
        if parent == 0:
            topHeight = 0
            for a in xrange(self.topLevelItemCount()):
                item = self.topLevelItem(a)
                topHeight += self.visualItemRect(item).height()
                if item.isExpanded():
                    height += self.visibleCount(item)
            height += topHeight
        else:
            childHeight = 0
            for a in xrange(parent.childCount()):
                item = parent.child(a)
                childHeight += self.visualItemRect(item).height()
                if item.isExpanded():
                    height += self.visibleCount(item)
            height += childHeight
        return height

    def editClicked(self, parent=0):
        # print 'edit 2'
        if parent == 0:
            for a in xrange(self.topLevelItemCount()):
                item = self.topLevelItem(a)
                print type(item)
                item.setExpanded(True)
                self.editClicked(item)
        else:
            for a in xrange(parent.childCount()):
                item = parent.child(a)
                print type(item)
                item.setText(1, '+')
                item.setExpanded(True)
                self.editClicked(item)

    def doubleClicked1(self, widget):
        print widget


def main():
    app = QtGui.QApplication(sys.argv)
    ex = TreeWidget()
    data = [
        'Make sure ZMQ remote button gets honored',
        'Fill in plot',
        'Remove cycle',
        'Remove current control or make it working',
        'Handle possible startup errors with dialogs',
        'Get improved current read-out (requires hardware changes)',
        ['1','2','3'],
        'Email quench notification'
        ]
    ex.fill_widget(data)
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main() 

您可以完全删除事件过滤器。当项目展开或折叠时,您需要调整小部件的大小。这两个动作都会触发信号,因此您只需将这些信号连接到 resize:

class TreeWidget(QTreeWidget):
    def __init__(self, parent=None):
        super(TreeWidget, self).__init__(parent)
        self.expanded.connect(self.resize)
        self.collapsed.connect(self.resize)