Простой иерархический листинг в PyQT - PullRequest
1 голос
/ 25 сентября 2011

Я пытаюсь создать пользовательский интерфейс с 3 столбцами - когда вы выбираете элемент в левом столбце, выбранный элемент передается функции, и он возвращает элементы для среднего столбца (и, конечно, то же самое для выбора элементы в средней колонке)

Должно быть просто, но я не могу найти простой способ сделать это ..

Сначала я попробовал QColumnView, так как он казался идеальным ... однако реализация QAbstractItemModel кажется чрезмерно сложной, и я не смог найти никаких полезных примеров этого.

Далее, поскольку существует фиксированное количество уровней, я создал три QListView и изменил в этом примере QAbstractListModel

.. однако, похоже, не было никакого полезного сигнала, который я мог бы использовать для запуска обновления других уровней иерархии. Согласно документации PyQT, QListView имеет только сигнал «indexesMoved». Также есть «нажатие» и «нажатие», однако они не срабатывают при смене элементов с помощью клавиатуры

Последняя опция - QListWidget, которая будет работать, поскольку у нее есть необходимые сигналы (itemChanged и т. Д.), Но способ создания элементов списка немного утомителен (создание QListWidgetItem с родительским элементом, установленным в экземпляр QListWidget)

Редактировать: QListWidget делает в значительной степени то, что мне нужно:

self.first_column = QListWidget()
self.first_column.itemSelectionChanged.connect(self.update_second_column)

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

Любой QAbastractItemView имеет QItemSelectionModel, доступный по методу selectionModel. QItemSelectionModel имеет сигналы, которые могут вам помочь:

currentChanged ( const QModelIndex & current, const QModelIndex & previous )
currentColumnChanged ( const QModelIndex & current, const QModelIndex & previous )
currentRowChanged ( const QModelIndex & current, const QModelIndex & previous )
selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )

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

1 голос
/ 25 сентября 2011

QListView наследуется от QAbstractItemView (думаю, вы знали это), поэтому он получает несколько сигналов , надеюсь, один (или несколько) из них вам подойдет.

Это работает для меня (подключите сигналы при инициализации вашего QMainWindow или основного QWidget, как в примере SaltyCrane):

connect(your_list_view, SIGNAL("clicked(const QModelIndex&)"), handler_slot)

...

def handler_slot(idx):
    #idx is a QModelIndex
    #QModelIndex.data() returns a QVariant, Qt4's generic data container
    celldata = idx.data()
    #Choose the proper datatype to ask the QVariant for (e.g. QVariant.toInt())
    actualvalue = celldata.toInt()
    #QVariant.toInt() happens to return a tuple
    print actualvalue[0]

В зависимости от типа данных в вашей модели вы можете выбрать правильный тип данных, чтобы запросить QVariant для .

Подлая часть здесь заставляет QListView сообщать вам, в какой ячейке щелкнули (то есть, используя clicked(const QModelIndex&) против clicked()). Я думаю, что потратил некоторое время на просмотр документации C ++ для Qt4, прежде чем понял, что вы можете получить больше от сигналов.

Отсюда у меня будет handler_slot() вызов метода setData() для модели для вашего второго QListView (с использованием данных, сгенерированных функцией, которую вы изначально планировали использовать).

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

Редактировать: Работа со стрелками

Хм, странно, что по умолчанию QListView нет сигнала для перемещения стрелы, но мы можем сделать его самостоятельно.

(Это выглядит почти не в стиле для сигналов и слотов Qt4 modus operandi)

QListView переопределяет метод keyPressEvent(self, QKeyEvent), который действует как функция обратного вызова при нажатии определенных клавиш. Вы можете прочитать больше . Мы можем использовать это, чтобы получить ключевые события, которые мы хотим, и подать наш собственный сигнал.

class ArrowableListView(QListView):
    def keyPressEvent(self, keyevent):
        #Maintain original functionality by calling QListView's version
        QListView.keyPressEvent(self, keyevent)

        #QListView.selectedIndexes returns a list of selected cells, I'm just taking the first one here
        idx = self.selectedIndexes()[0]

        #We'll emit a signal that you can connect to your custom handler
        self.emit(SIGNAL("my_signal"), idx)

Как только происходит нажатие клавиши, мы спрашиваем QListView, каковы выбранные индексы (!). Конечно, вы можете выбрать отфильтровать определенные ключи и выбрать, обрабатывать ли несколько выделенных ячеек (я думаю, вы можете установить режим выбора, когда это невозможно, см. Документацию QListView).

Теперь, когда у нас есть выбранные индексы (список QModelIndex), мы передаем первый (a QModelIndex) вместе с нашим сигналом. Поскольку мы определяем этот сигнал в python, нам не нужно устанавливать прототип функции; Я понятия не имею, если это плохой стиль.

Теперь все, что вам нужно сделать, это подключить сигнал к обработчику:

self.connect(your_list_view, SIGNAL("my_signal"), handler_slot)

и напишите свой обработчик.

Надеюсь, это не слишком неприятный обходной путь.

...