Как отсортировать значения с плавающей запятой, используя QSortFilterProxyModel? - PullRequest
1 голос
/ 10 октября 2019

У меня есть класс, который создает виджет таблицы, используя QSortFilterProxyModel. Класс будет принимать список словарей в качестве данных, а затем заполнять столбцы и строки таблицы ключевыми значениями словарей. При настройке таблицы для сортировки по значениям с плавающей запятой некоторые поля таблицы становятся невидимыми. Однако, когда я сортирую таблицу по строковым значениям, проблем не возникает. Нужно ли указывать типы?

Сортировка по значению: self.proxyView.sortByColumn(0, Qt.AscendingOrder)

enter image description here

Сортировка по стр .: self.proxyView.sortByColumn(2, Qt.AscendingOrder)

enter image description here

from PyQt5.QtWidgets import *
from PyQt5.QtCore import (QDate, QDateTime, QRegExp, QSortFilterProxyModel, Qt,
        QTime, QModelIndex, QSize)
from PyQt5.QtGui import QStandardItemModel, QIcon

class Table(QWidget):
    def __init__(self, name, data, columns=None, index=0, parent=None):
        super(Table, self).__init__(parent)

        self.name = name

        #specify which keys of dictionary should be included in the table
        if columns:
            self.columns = columns      
        else:
            self.columns = data[0].keys()

        self.setData(data)

        self.initUI()

    def initUI(self):
        '''
        Layout UI elements of table
        '''
        mainLayout = QVBoxLayout()

        self.model = QSortFilterProxyModel()
        self.model.setDynamicSortFilter(True)

        model = QStandardItemModel(0, len(self.columns), self)
        for i, column in enumerate(self.columns):
            model.setHeaderData(i, Qt.Horizontal, column)

        self.model.setSourceModel(model)

        self.proxyGroupBox = QGroupBox(self.name)

        self.proxyView = QTreeView()
        self.proxyView.setRootIsDecorated(False)
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setModel(self.model)
        self.proxyView.setSortingEnabled(True)

        self.proxyView.setEditTriggers(QAbstractItemView.NoEditTriggers)

        proxyLayout = QGridLayout()
        proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3)
        self.proxyGroupBox.setLayout(proxyLayout)

        mainLayout.addWidget(self.proxyGroupBox)
        self.setLayout(mainLayout)
        self.proxyView.sortByColumn(0, Qt.AscendingOrder)
        self.update(self.data)

        self.show()

    def setSourceModel(self, model):
        self.proxyModel.setSourceModel(model)

    def setData(self, data):
        self.data = [{k: x[k] for k in self.columns} for x in data]

    def setColumns(self, cols):
        self.columns = cols
        self.data = setData()

    def addRow(self, row_i, rowData):
        self.model.insertRow(row_i)

        for col_i, data in enumerate(rowData.values()):
           self.model.setData(self.model.index(row_i, col_i), data)

    def update(self, data):
        self.setData(data)
        self.model.removeRows(0, self.model.rowCount())

        for i, data in enumerate(self.data):
            self.addRow(i, data)

    def getRowIndex(self):
        try:
            return self.proxyView.selectedIndexes()[0].row()
        except:
            return False

if __name__=='__main__':
    import sys
    data = [
        {'Lat': 1.123, 'Lon': 12.234, 'Desc': 'Point 1'},
        {'Lat': -2.123, 'Lon': 1.234, 'Desc': 'Point 2'},
        {'Lat': 3.123, 'Lon': -122.234, 'Desc': 'Point 3'},
        {'Lat': -22.123, 'Lon': -31.234, 'Desc': 'Point 4'},
        {'Lat': 33.123, 'Lon': -12.234, 'Desc': 'Point 5'}
    ]
    app = QApplication(sys.argv)
    window = Table('Table', data)
    sys.exit(app.exec_())

1 Ответ

1 голос
/ 10 октября 2019

Объяснение:

Проблема в том, что вы добавляете информацию в прокси-модель вместо исходной модели.

Чтобы лучше понять, давайте использовать следующий пример: скажем, порядки проксиэто в порядке возрастания относительно первого столбца, есть только 2 столбца и добавляются следующие данные: [(2, 1), (1, 2), (-1, 0)]:

  • шаг 1:
2 x
  • шаг 2:
2 1
  • шаг 3:
2 1
1 x
  • шаг 4:
1 x
2 2
  • шаг 5:
 1 x
 2 2
-1 x
  • шаг 6:
-1 x
 1 x
 2 0

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

Решение:

Чтобы избежать этого, необходимо добавить эту информацию в исходную модельтак как это никогда не переставляется.

class Table(QWidget):
    # ...
    def initUI(self):
        """
        Layout UI elements of table
        """
        mainLayout = QVBoxLayout()

        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setDynamicSortFilter(True)

        self.source_model = QStandardItemModel(0, len(self.columns), self)
        for i, column in enumerate(self.columns):
            self.source_model.setHeaderData(i, Qt.Horizontal, column)

        self.proxy_model.setSourceModel(self.source_model)

        self.proxyGroupBox = QGroupBox(self.name)

        self.proxyView = QTreeView()
        self.proxyView.setRootIsDecorated(False)
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setModel(self.proxy_model)
        self.proxyView.setSortingEnabled(True)

        self.proxyView.setEditTriggers(QAbstractItemView.NoEditTriggers)

        proxyLayout = QGridLayout()
        proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3)
        self.proxyGroupBox.setLayout(proxyLayout)

        mainLayout.addWidget(self.proxyGroupBox)
        self.setLayout(mainLayout)
        self.proxyView.sortByColumn(0, Qt.AscendingOrder)
        self.update(self.data)

        self.show()

    def setData(self, data):
        self.data = [{k: x[k] for k in self.columns} for x in data]


    def addRow(self, row_i, rowData):
        self.source_model.insertRow(row_i)

        for col_i, data in enumerate(rowData.values()):
            self.source_model.setData(self.source_model.index(row_i, col_i), data)

    def update(self, data):
        self.setData(data)
        self.source_model.removeRows(0, self.source_model.rowCount())

        for i, data in enumerate(self.data):
            self.addRow(i, data)

    # ...
...