Вопрос по python – QT QItemSelectionModel игнорировать столбцы?

1

Я пытаюсь ограничить выбор дерева для определенного столбца.

Я интенсивно использую делегатов для создания пользовательских поведений для каждого элемента в столбце, редакторов и т. Д. Я надеялся, что смогу как-то сделать это из делегата, заблокировав событие или что-то подобное. Проблема, я думаю, мне нужно было бы создать полностью индивидуальное решение, которое имитирует расширенный выбор.

Тем не менее, после долгих поисков и очень немногих примеров, звучит так, будто я хочу создать собственную QItemSelectionModel в своем древовидном представлении. Это предположение верно?

Как мне создать пользовательский QItemSelectionModel, который будет использовать расширенный режим выбора, но позволит мне игнорировать или отменить выбор, если не в конкретном столбце. Другими словами, нажатие на другой столбец не должно изменять выбор (не должен выделять или отменять выбор)

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

Я использую Python, но оценил бы любую помощь.

Спасибо,

[EDIT:] Я нашел эти похожие вопросы: http://lists.qt.nokia.com/pipermail/qt-interest/2010-September/027647.html

& Quot;Subclass QItemSelectionModel and reimplement both select methods to have the behaviour you want. Just ignore the parts of ranges with column > 0. ... Or maybe just reimplement flags() to make the item not selectable. I don't know if that will have any side effects."

Я попытался переопределить флаги на моем QTreeWidgetItem, но он никогда не вызывался:

def flags(self, index):
    print index.column()
    return super(DDOutlinerBaseItem, self).flags(index)
Используете ли вы пользовательскую модель для ваших данных? Независимо от того, элементы выбираются или нет, зависит от модели. УвидетьQAbstractItemModel::flags() (qt-project.org/doc/qt-4.8/qabstractitemmodel.html#flags) иQt::ItemFlags (qt-project.org/doc/qt-4.8/qt.html#ItemFlag-enum). leemes
Спасибо за комментарий. Я использую QTreeWidgetItems. я вижу этоflags может быть прочитан по индексу, но единственный способ установить флаги, который я нашел, это на уровне элемента в QTreeWidgetItem.setFlags (). Я пытался переопределить функцию, но она никогда не вызывалась:def flags(self, index): print index.column() return super(DDOutlinerBaseItem, self).flags(index) Rafe
Я думаю, что уровень предмета == уровень индекса. Индекс определяется его родительским элементом, строкой и столбцом. С «item», я думаю, вы именно это и имеете в виду. Этоshould Достаточно вернуть невыбираемый флаг для любых запросов, сделанных методу flag (), когда столбец данного индекса является одним из ваших столбцов, которые не должны принимать выбор. Но я думаю, что вы уже поняли - должна быть еще одна ошибка. leemes
Хорошо, это странно, но в любом случае модели Qt :) Я только что посмотрел на исходный код C ++ модели выбора. Всякий раз, когдаselect() называется, он не смотрит даже на связанную модель данных. Попробуйте поиграть с некоторыми значениями для QAbstractItemView.selectionBehaviour (qt-project.org/doc/qt-4.8/…). Может быть, это представление (не модель выбора), которое смотрит на модель, когда пользователь хочет что-то выбрать. Если это не помогает, вам нужно дождаться ответа кого-то другого, так как я недостаточно знаю, как обрабатывать выборки представлений Qt. :( leemes
Спасибо за попытку. Я думаю, что проблема, с которой я сталкиваюсь, заключается в том, что мне нужно установить эти флаги на уровне индекса, а не на уровне элемента, и это, по-видимому, недоступно. Вот почему я начал искать способы заблокировать или перехватить поведение. В идеале мой делегат согласился бы с событием мыши, поэтому модель выбора даже не увидит его, но я тоже не смог найти это, поэтому сейчас я смотрю на саму модель. Я добавил еще немного к своему вопросу, и я продолжаю взламывать свой путь вокруг. Мое королевство для нескольких примеров! Rafe

Ваш Ответ

2   ответа
4

Приведенное выше решение может использовать два отдельных метода и декораторы @pyqtSlot для устранения неоднозначности имен перегруженных методов:

@pyqtSlot(QModelIndex, QItemSelectionModel.SelectionFlags)
  def select(self, index, command):
    # ...

@pyqtSlot(QItemSelection, QItemSelectionModel.SelectionFlags)
  def select(self, selection, command):
    #...

Это избавляет от необходимости проверять экземпляры определенных классов в реализациях метода.

0

что, поскольку Python не может перегрузить метод, мой метод select, кажется, просто вызывается дважды, по одному разу для каждого типа в аргументе 0. Вот пример, иллюстрирующий это, а также базовые настройки. Моё дерево QTreeWidget называется "деревом" (self.tree)

    # in __init__ of my QTreeWidget:
    sel_model = ColumnSelectionModel(self.tree.model())
    self.tree.setSelectionModel(sel_model)

class ColumnSelectionModel(QtGui.QItemSelectionModel):
    def select(self, selection, selectionFlags):
    """
    Runs both QItemSelectionModel.select methods::

        1. select(QtCore.QModelIndex, QItemSelectionModel.SelectionFlags)
        2. select(QtGui.QItemSelection, QItemSelectionModel.SelectionFlags)

    The first seems to run on mouse down and mouse up.
    The second seems to run on mouse down, up and drag
    """
    print("select(%s,  %s)" % (type(selection), type(selectionFlags)))

    if isinstance(selection, QtGui.QItemSelection):
        infos = []
        for index in selection.indexes():
            infos.append(("index=%s row=%s column=%s" 
                                    % (index, index.row(), index.column())))

        print ", ".join(infos)
    elif isinstance(selection, QtCore.QModelIndex):
        index = selection
        print("index=%s row=%s column=%s" % (index, index.row(), index.column()))
    else:
        raise Exception("Unexpected type for arg 0: '%s'" % type(selection))

    super(ColumnSelectionModel, self).select(selection, selectionFlags)

Похоже, это решает мою проблему:

class ColumnSelectionModel(QtGui.QItemSelectionModel):
    def __init__(self, model):
        super(ColumnSelectionModel, self).__init__(model)

        self.selectable_columns = [0]
        """ Set the columns that are allowed to be selected """


    def select(self, selection, selectionFlags):
        """
        Ignores any selection changes if an item is not in one of the columns
        in the self.selectable_columns list.

        Is run by both QItemSelectionModel.select methods::

            1. select(QtCore.QModelIndex, QItemSelectionModel.SelectionFlags)
            2. select(QtGui.QItemSelection, QItemSelectionModel.SelectionFlags)

        The first seems to run on mouse down and mouse up.
        The second seems to run on mouse down, up and drag
        """
        if isinstance(selection, QtGui.QItemSelection):
            # This is the overload with the QItemSelection passed to arg 0
            # Loop over all the items and if any are not in selectable_columns
            #   ignore this event. This works because it is run for every change
            #   so the offending selection index will always be the newest
            indexes = selection.indexes()
            for i in xrange(len(indexes)):
                index = indexes[i]
                if not index.column() in self.selectable_columns:
                    return
        elif isinstance(selection, QtCore.QModelIndex):
            # This is the overload with the QModelIndex passed to arg 0
            # If this index isn't in selectable_columns, just ignore this event
            index = selection
            if not index.column() in self.selectable_columns:
                return
        else:  # Just in case
            raise Exception("Unexpected type for arg 0: '%s'" % type(selection))

        # Fall through. Select as normal
        super(ColumnSelectionModel, self).select(selection, selectionFlags)

В моей окончательной реализации я планирую делегировать решение моей системе делегатов, сделав это универсальным и, теоретически, способным динамически игнорировать любой индекс, который я хочу.

Похожие вопросы