Как выбрать элемент в QTreeView, который находится внутри QComboBox - PullRequest
2 голосов
/ 12 марта 2012

У меня QtreeView как представление в QComboBox.В моем приложении корневые элементы являются метками категорий и не должны быть выбраны.Когда я создаю представление, я хотел бы предварительно выбрать один из дочерних элементов (первый корневой элемент выбран по умолчанию), но я не могу понять, как это сделать.Примеры этого (особенно для python) тонкие на земле.

Вот мой упрощенный пример:

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

data = [ (("Cat A",False), [(("Thing 1",True), []),(("Thing 2",True), [])]),
    (("Cat B",False), [(("Thing 3",True), []), (("Thing 4",True), [])])]

class MyComboBox(QComboBox):
    def __init__(self):
        super(QComboBox,self).__init__()
        self.setView(QTreeView())

        self.view().setHeaderHidden(True)
        self.view().setItemsExpandable(False)
        self.view().setRootIsDecorated(False)

    def showPopup(self):
        self.view().expandAll()
        QComboBox.showPopup(self)

class Window(QWidget):
    def __init__(self):

        QWidget.__init__(self)

        self.model = QStandardItemModel()
        self.addItems(self.model, data)

        self.combo = MyComboBox()
        self.combo.setModel(self.model)

        layout = QVBoxLayout()
        layout.addWidget(self.combo)
        self.setLayout(layout)

        # I can choose which combobox item to select here, but I am unable to
        #choose child items
        #self.combo.setCurrentIndex(1)

    def addItems(self, parent, elements):
        for text, children in elements:
            item = QStandardItem(text[0])
            # root items are not selectable, users pick from child items
            item.setSelectable(text[1])
            parent.appendRow(item)
            if children:
                self.addItems(item, children)

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

Я работал на примерах здесь и здесь

вопрос был в значительной степени задан до , но не для python, и опубликованное решение не работает для меня.

Ответы [ 2 ]

2 голосов
/ 12 марта 2012

Это альтернативный и более общий способ для вашего текущего кода. Он будет работать для дополнительного уровня вложенных элементов и любой конфигурации выбираемых элементов.

class MyComboBox(QComboBox):
    def __init__(self):
        super(MyComboBox,self).__init__()  # your super was wrong.
                                           # you need to pass the _current_ class name
        self.setView(QTreeView())

        self.view().setHeaderHidden(True)
        self.view().setItemsExpandable(False)
        self.view().setRootIsDecorated(False)

    def showPopup(self):
        self.setRootModelIndex(QModelIndex()) # you need to add this
        self.view().expandAll()
        QComboBox.showPopup(self)

    def setModel(self, model):
        super(MyComboBox, self).setModel(model)
        parent, row = self._firstSelectableItem()
        if row is not None:
            self.setRootModelIndex(parent)
            self.setCurrentIndex(row)

    def _firstSelectableItem(self, parent=QModelIndex()):
        """
        Internal recursive function for finding the first selectable item.
        """
        for i in range(self.model().rowCount(parent)):
            itemIndex = self.model().index(i,0,parent)
            if self.model().itemFromIndex(itemIndex).isSelectable():
                return parent, i
            else:
                itemIndex, row = self._firstSelectableItem(itemIndex)
                if row is not None:
                    return itemIndex, row
        return parent, None
2 голосов
/ 12 марта 2012

Это будет работать, если вы используете QTreeWidget как вид и модель в вашем комбинированном списке, т.е.

self.tree = QTreeWidget()
self.combo.setModel(self.tree.model())
self.combo.setView(self.tree)

Кроме того, вам нужно изменить функцию addItems (), чтобы создать QTreeWidget с QTreeWidgetItem в качестве дочерних. Как только вы это сделаете, следующий элемент выберет элемент в вашем древовидном виджете:

# make item current in tree to get hold of its index
self.tree.setCurrentItem(ITEMTOSELECT)
# make item's parent reference point and provide index in relation to parent
self.combo.setRootModelIndex(self.tree.currentIndex().parent())
self.combo.setCurrentIndex(self.tree.currentIndex().row())
# reset combobox to display full tree again
self.tree.setCurrentItem(self.tree.invisibleRootItem())
self.combo.setRootModelIndex(self.tree.currentIndex()) 

Это основано на найденном примере здесь .

Надеюсь, это поможет.

...