如何根据用户的选择在 QColumnView 中添加另一列?

How to add another column in a QColumnView based on the user's selection?

使用 PySide2,我有一个包含 QColumnView 小部件的界面,我正在尝试为其创建类似于联系人查找的功能:select 一个人的名字,然后显示下一列更多 options/details 关于 selection.

目前,我在 UI 加载时填充视图,它显示用户可用的第一级选项。

所需功能:当用户创建 selection 时,QColumnView 会添加另一列,显示基于用户 selection 的可用选项。

当前问题:当用户创建 selection 时,由于我不确定如何向 QColumnView 添加另一个 column/level,相反,QColumnView 的模型被更新并且仅显示下一级选项 - 可以这么说,意味着以前的值在视图中被覆盖。虽然这很实用,但并不理想,因为前一列仍在视图中,使用户能够看到他们当前正在搜索的类别。

如此处所示,用户已 selected 'Address',然后在右侧的列中显示与 'Address' 关联的选项。

只是为了创建一个包含 QColumnView 的基本界面,它看起来像这样:

import sys
from PySide2 import QtWidgets, QtCore
import PySide2

class UserInput(object):
    def setupUi(self, get_user_input=None):
        # Basic shape
        self.width = 425
        get_user_input.setObjectName("get_user_input")
        get_user_input.resize(425, self.width)
        self.frame = QtWidgets.QFrame(get_user_input)
        self.frame.setGeometry(QtCore.QRect(11, 10, 401, 381))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.frame.setObjectName("frame")
        # Creating the grid layout for most of the display elements
        self.gridLayoutWidget = QtWidgets.QWidget(self.frame)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 10, 381, 361))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.get_user_input_layout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.get_user_input_layout.setContentsMargins(5, 5, 5, 5)
        self.get_user_input_layout.setObjectName("get_user_input_layout")
        # Grid layout for the buttons
        self.buttonLayoutGrid = QtWidgets.QWidget(get_user_input)
        self.buttonLayoutGrid.setGeometry(QtCore.QRect(10, 390, 401, 41))
        self.buttonLayoutGrid.setObjectName("buttonLayoutGrid")
        self.buttonLayout = QtWidgets.QGridLayout(self.buttonLayoutGrid)
        self.buttonLayout.setContentsMargins(0, 0, 0, 0)
        self.buttonLayout.setObjectName("buttonLayout")
        # Buttons
        self.buttonOK = QtWidgets.QPushButton(self.buttonLayoutGrid)
        self.buttonOK.setObjectName("buttonOK")
        self.buttonOK.setText("OK")
        self.buttonLayout.addWidget(self.buttonOK, 0, 1, 1, 1)
        self.buttonCancel = QtWidgets.QPushButton(self.buttonLayoutGrid)
        self.buttonCancel.setObjectName("buttonCancel")
        self.buttonCancel.setText("CANCEL")
        self.buttonLayout.addWidget(self.buttonCancel, 0, 2, 1, 1)

        #Column View Data
        self.t = PySide2.QtWidgets.QColumnView()
        self.t.setColumnWidths([10,10])

        model = PySide2.QtGui.QStandardItemModel()
        model.setColumnCount(1)
        model.setHorizontalHeaderLabels(['Data Collections'])

        self._dict = {'Test 1': [1, 2, 3], 'Test 2': [4, 5, 6], 'Test 3': [7, 8, 9]}
        _data = []

        for each in self._dict:
            resultItem = PySide2.QtGui.QStandardItem()
            insertText = each
            resultItem.setText(str(insertText))
            model.appendRow(resultItem)

        self.t.setModel(model)
        self.t.clicked.connect(self.column_view_clicked)
        self.get_user_input_layout.addWidget(self.t, 2,0,1,1)

    def column_view_clicked(self, row):
        model = PySide2.QtGui.QStandardItemModel()
        model.setColumnCount(1)
        model.setHorizontalHeaderLabels(['Analysis Variables'])
        _data = []

        for i in self._dict[row.data()]:
            resultItem = PySide2.QtGui.QStandardItem()
            resultItem.setText(str(i))
            model.appendRow(resultItem)

        self.t.createColumn(row)        

class UserInputPrompt(PySide2.QtWidgets.QDialog, UserInput):

    def __init__(self, path_to_image=None):
        app = PySide2.QtWidgets.QApplication(sys.argv)
        super(UserInputPrompt, self).__init__()
        self.setupUi(self)
        super(UserInputPrompt, self).exec_()        

    def get_user_input(self):
        print("Get user selection")

def main(): 
    UserInputPrompt()

if __name__ == '__main__':
    main()

当你运行以上代码时,点击界面左侧的任意一项('Test 1, 'Test 2' or 'Test 3'),结果会添加一个现有列右侧的列,但当前没有数据填充在那里 - 因为我现在不知道该怎么做。

OP 指出的要求只是 ColumnView 的功能,问题是您没有传递数据结构正确的模型。如您所见,该结构是一棵树,其中有父节点和子节点,因此您必须创建一个具有该结构的模型。在这种情况下,我使用 QStandardItemModel 来处理数据,如下所示:

import sys
from PySide2 import QtCore, QtGui, QtWidgets


def populateTree(children, parent):
    for child in children:
        child_item = QtGui.QStandardItem(child)
        parent.appendRow(child_item)
        if isinstance(children, dict):
            populateTree(children[child], child_item)


class Dialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.frame = QtWidgets.QFrame(
            frameShape=QtWidgets.QFrame.StyledPanel, frameShadow=QtWidgets.QFrame.Sunken
        )
        self.buttonOK = QtWidgets.QPushButton(self.tr("OK"))
        self.buttonCancel = QtWidgets.QPushButton(self.tr("CANCEL"))

        self.columnview = QtWidgets.QColumnView()

        grid_layout = QtWidgets.QGridLayout(self)
        grid_layout.addWidget(self.frame, 0, 0, 1, 2)
        grid_layout.addWidget(self.buttonOK, 1, 0)
        grid_layout.addWidget(self.buttonCancel, 1, 1)

        lay = QtWidgets.QVBoxLayout(self.frame)
        lay.addWidget(self.columnview)

        data = {
            "root1": {
                "child11": ["subchild111", "subchild112"],
                "child12": ["subchild121"],
            },
            "root2": {
                "child21": ["subchild211"],
                "child22": ["subchild221", "subchild222"],
            },
        }

        self.model = QtGui.QStandardItemModel(self)
        self.columnview.setModel(self.model)
        populateTree(data, self.model.invisibleRootItem())

        self.resize(1280, 480)


def main():
    app = QtWidgets.QApplication(sys.argv)
    w = Dialog()
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()