QSortFilterProxyModel создает пустые элементы - PullRequest
0 голосов
/ 02 марта 2019

Что я пытаюсь сделать: взять элементы из модели и отсортировать их с помощью прокси-сервера сортировки по другой роли: ожидаемый результат:

What I want to happen:

Реальный вывод содержит пустые строки, которых там быть не должно:

You can see the empty lines expand the ListView and can even be selected by cursor

Вы можете видеть, что пустые строки расширяют ListView и могут быть даже выбраны с помощьюкурсор.

Вот код, который вызывает это неправильное поведение:

from PySide2.QtCore import *
from PySide2.QtWidgets import *
import sys
import string
import random

class MyItem:
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def __str__(self):
        return self.name +" "+ str(self.value)

class MyCustomModel(QAbstractListModel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.list = []

    def rowCount(self, parent=None):
        return len(self.list)

    def data(self, index, role):
        row = index.row()
        if row < 0 or row >= len(self.list):
            return None

        item = self.list[row]
        if role == Qt.DisplayRole:
            return str(item)
        if role == Qt.UserRole:
            return item.value
        else:
            return None

    def add(self, item):
        rc = self.rowCount()
        self.beginInsertRows(QModelIndex(), rc, rc+1)
        self.list.append(item)
        self.endInsertRows()

class MyWidget(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.model = MyCustomModel()
        self.listView = QListView(self)

        self.sortingProxy = QSortFilterProxyModel()
        self.sortingProxy.setSourceModel(self.model)
        self.sortingProxy.setSortRole(Qt.UserRole)
        self.sortingProxy.sort(0, Qt.AscendingOrder)

        self.listView.setModel(self.sortingProxy)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.listView)

        self.setLayout(self.layout)
        self.show()

        # create some random data for the model
        for i in range(10):
            randomName = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(8)])
            self.model.add(MyItem(randomName, random.randint(0, 30)))

app = QApplication(sys.argv)
widget = MyWidget()
app.exec_()

Я отследил проблему до QSortFilterProxyModel, потому что, когда она удалена, проблема исчезает, но программа больше не сортируетданные:

from PySide2.QtCore import *
from PySide2.QtWidgets import *
import sys
import string
import random

class MyItem:
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def __str__(self):
        return self.name +" "+ str(self.value)

class MyCustomModel(QAbstractListModel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.list = []

    def rowCount(self, parent=None):
        return len(self.list)

    def data(self, index, role):
        row = index.row()
        if row < 0 or row >= len(self.list):
            return None

        item = self.list[row]
        if role == Qt.DisplayRole:
            return str(item)
        if role == Qt.UserRole:
            return item.value
        else:
            return None

    def add(self, item):
        rc = self.rowCount()
        self.beginInsertRows(QModelIndex(), rc, rc+1)
        self.list.append(item)
        self.endInsertRows()

class MyWidget(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.model = MyCustomModel()
        self.listView = QListView(self)

        self.listView.setModel(self.model)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.listView)

        self.setLayout(self.layout)
        self.show()

        # create some random data for the model
        for i in range(10):
            randomName = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(8)])
            self.model.add(MyItem(randomName, random.randint(0, 30)))

app = QApplication(sys.argv)
widget = MyWidget()
app.exec_()

Поскольку проблема, по-видимому, вызвана кодом Pyside2 / Qt5, похоже, я не знаю, как с этим бороться.

1 Ответ

0 голосов
/ 02 марта 2019

Проблема не в прокси, проблема вызвана методом, который вы используете для добавления элементов. Если вы просматриваете документы , вы должны передать номер строки от и до того места, где он добавлен, в этомВ случае, когда добавляется только 1, то оба совпадают, в общем случае, если добавляются n-элементы, решение:

rc = self.rowCount()
self.beginInsertRows(QModelIndex(), rc, rc + n - 1)

Так что в вашем случае решение:

def add(self, item):
    rc = self.rowCount()
    self.beginInsertRows(QModelIndex(), rc, rc)
    self.list.append(item)
    self.endInsertRows()
...