QTreeView不跨越父级宽度或高度

时间:2015-05-18 21:25:29

标签: python-3.x layout pyside qtreeview

所以我是QtGui的新手并且正在查找如何做事,我发现这很整洁example on QTreeView。当我自己开始工作时,我注意到它并没有像我预期的那样填满空间:

enter image description here

所以我一直在寻找答案,而不是在Python或C ++资源中找到太多。我已经checking the documentation了很多,但仍然没有找到我正在寻找的东西。

所以很明显,某些东西没有正确的尺寸政策,但我很难弄明白什么。到目前为止,我已经淘汰了几位潜在候选人:

  • 持有QTreeView实例的QWidget实例正确地跨越它所在的布局(QWidget跨越QGroupBox的宽度减去一点边距)。
  • 由于QTreeView的父窗口小部件是正确的维度,我认为它是QTreeView更本地的东西,但是当我使用setSizePolicy时,我使用的策略似乎都没有解决问题。可能是我不知道的多个步骤?
  • QTreeView继承的viewport(来自QAbstractScrollArea比我预期的要小得多。使用新的空QWidget调用QTreeView的setViewport()方法只会重绘非标题内容背景为灰色而不是白色,我怀疑这是接近但不是我需要看的地方。
  • QTreeView还有其他孩子(除了viewport),我还在调查。
  • 我尝试过的大部分内容都在下面的代码中留下了评论。

这是我要重现的源代码:

import sys
from PySide.QtGui import *


class TreeTime(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.main_widget = QWidget()
        self.main_layout = QVBoxLayout()
        self.main_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.main_widget)
        self.statusBar()

        self.make_tree()

        self.show()

    def make_tree(self):
        # init widgets
        self.tgb = QGroupBox("[Tree Group Box Title]")
        self.main_layout.addWidget(self.tgb)

        tgb_layout = QVBoxLayout()
        self.tgb.setLayout(tgb_layout)

        tgb_widget = QWidget()
        tgb_layout.addWidget(tgb_widget)

        debug_btn = QPushButton("DEBUG")
        tgb_layout.addWidget(debug_btn)

        view = QTreeView(parent=tgb_widget)
        # view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        view.setSelectionBehavior(QAbstractItemView.SelectRows)
        model = QStandardItemModel()
        model.setHorizontalHeaderLabels(['col1', 'col2', 'col3'])
        view.setModel(model)
        view.setUniformRowHeights(True)

        # populate data
        for i in range(10):
            parent1 = QStandardItem('Family {}. Some long status text for sp'.format(i))
            for j in range(3):
                child1 = QStandardItem('Child {}'.format(i*3+j))
                child2 = QStandardItem('row: {}, col: {}'.format(i, j+1))
                child3 = QStandardItem('row: {}, col: {}'.format(i, j+2))
                parent1.appendRow([child1, child2, child3])
            model.appendRow(parent1)
            # span container columns
            view.setFirstColumnSpanned(i, view.rootIndex(), True)

        # expand third container
        index = model.indexFromItem(parent1)
        view.expand(index)

        # select last row
        selmod = view.selectionModel()
        index2 = model.indexFromItem(child3)
        selmod.select(index2, QItemSelectionModel.Select|QItemSelectionModel.Rows)

        def print_debug_info():
            print('')
            for child in view.children():
                print("child "+repr(child)) #not sure what all these are yet
            print('')
            print('self.main_widget.frameSize: '+repr(self.main_widget.frameSize()))
            print('view.parent().parent().frameSize(): '+repr(view.parent().parent().frameSize())) #group box
            # print('self.frameSize: '+repr(self.frameSize()))
            print('self.tgb.frameSize: '+repr(self.tgb.frameSize()))
            print('view.parent(): '+repr(view.parent()))
            print('view.parent().frameSize(): '+repr(view.parent().frameSize()))
            # print('view.parent().frameSize(): '+repr(view.parent().frameSize())+" (before)")
            # print('view.parent().adjustSize(): '+repr(view.parent().adjustSize()))
            # print('view.parent().frameSize(): '+repr(view.parent().frameSize())+" (after)")
            print('view.viewport(): '+repr(view.viewport()))
            print('view.viewport().frameSize(): '+repr(view.viewport().frameSize()))
            # print('view.parent().parent().parent().frameSize(): '+repr(view.parent().parent().parent().frameSize()))
            # print('calling setViewport: '+repr(view.setViewport(QWidget())))
            # view.adjustSize()

        debug_btn.clicked.connect(print_debug_info)

    def sayHello(self):
        self.statusBar().showMessage("Hello World!")
        import time; time.sleep(2)
        self.statusBar().showMessage("")

    def sayWords(self, words):
        self.statusBar().showMessage(words)


if __name__ == '__main__':
    app = QApplication([])
    tt = TreeTime()
    sys.exit(app.exec_())

我使用的是Windows 8.1机器和Python 3.4.3,PySide版本1.2.2 - 任何帮助都将非常感谢! (另外,如果我遗漏任何重要细节,请告诉我)

更新(2015年5月19日):我尝试将我的DEBUG按钮移到QGroupBox之外,结果是QTreeView被折叠成一个完全不可读的大小,所以你甚至不能告诉对象是什么,所以它似乎是最小化使用的空间,即使我取消注释该行:

view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

有一位朋友建议这可能仅仅是Windows的问题,而不是我的代码,但我没有任何东西支持它。

2015年5月19日更新:我已经实施了@titusjan提供的建议,但我遇到了同样的问题/行为。

2 个答案:

答案 0 :(得分:1)

您必须使用setLayout方法将布局链接到窗口小部件。所以改变......

self.main_layout = QVBoxLayout(self.main_widget)

self.main_layout = QVBoxLayout()
self.main_widget.setLayout(self.main_layout)

类似于tgb_view布局(为了清楚起见,我将其重命名为tgb_layout)。

最后,您忘记将树视图添加到此布局中,因此请添加:

tgb_view.addWidget(view)

为方便起见,我在下面列出了所有相关的修改代码。

def initUI(self):
    self.main_widget = QWidget()
    self.main_layout = QVBoxLayout()
    self.main_widget.setLayout(self.main_layout)
    self.setCentralWidget(self.main_widget)
    self.statusBar()
    self.make_tree()

    self.show()

def make_tree(self):
    # init widgets
    self.tgb = QGroupBox("[Tree Group Box Title]")
    self.main_layout.addWidget(self.tgb)

    tgb_view = QVBoxLayout()
    self.tgb.setLayout(tgb_view)
    tgb_widget = QWidget()
    tgb_view.addWidget(tgb_widget)

    debug_btn = QPushButton("DEBUG")
    tgb_view.addWidget(debug_btn)

    view = QTreeView(parent=tgb_widget)
    tgb_view.addWidget(view)
    ...

大小政策是没有必要的,默认是好的。

答案 1 :(得分:1)

您需要删除多余的tp_widget并将view添加到tgb_layout

def make_tree(self):
    # init widgets
    self.tgb = QGroupBox("[Tree Group Box Title]")
    self.main_layout.addWidget(self.tgb)

    tgb_layout = QVBoxLayout()
    self.tgb.setLayout(tgb_layout)

    view = QTreeView()
    tgb_layout.addWidget(view)

    ...

    debug_btn = QPushButton("DEBUG")
    tgb_layout.addWidget(debug_btn)

请注意,当您向布局添加小部件时,它们将自动重新布局到布局的父级(无论何时获得布局),因此在构造函数中不必设置小部件。

另请注意:

    tgb_layout = QVBoxLayout(self.tgb)

完全等同于:

    tgb_layout = QVBoxLayout()
    self.tgb.setLayout(tgb_layout)

因为布局总是会重新设置为它所设置的小部件。