PyQt:如何对 QTableView 列(字符串和数字)进行排序

PyQt: How to sort QTableView columns(strings and numericals)

当单击 header 时,行 self.tableView.setSortingEnabled(True) 对 table 视图进行排序,但排序不正确。也就是说,它认为每一列都是一个字符串(例如,它对 1,11,12,2,22,3 等数字进行排序)。我该如何纠正?

我的代码:

self.model = QtGui.QStandardItemModel()

with open(file_name_temp, "rt") as fileInput:
    i = 1
    for row in csv.reader(fileInput):
        item = QtGui.QStandardItem()
        for field in row:
            items = [
                item.setData(field, QtCore.Qt.UserRole)
            ]
            print(items)
        self.model.appendRow(items)

    tab_table_view = QtGui.QWidget()
    self.Tab.insertTab(0, tab_table_view, self.File_Name)
    self.tableView = QtGui.QTableView(tab_table_view)
    self.tableView.setGeometry(QtCore.QRect(0, 0, 721, 571))
    self.model = QtGui.QStandardItemModel(self)
    self.tableView.setModel(self.model)
    colll = self.Datas.dtypes.index
    col_names = np.array(colll)
    col_names = np.insert(col_names, 0, self.Datas.index.name)
    self.model.setHorizontalHeaderLabels(col_names)
    self.tableView.hideRow(0)
    self.model.setSortRole(QtCore.Qt.UserRole)

更新 1:

if (".csv" or ".txt") in self.File_Name:
        with open(file_name_temp, "rt") as fileInput:
            i = 1
            reader = csv.reader(fileInput)
            next(reader, None)
            for row in reader:
                for x in range(0,Num_col+1):
                    try:
                        int(row[x])
                        row[x]=int(row[x])
                    except ValueError:
                        print('Not Int')
                items = []
                for field in row:
                    item = QtGui.QStandardItem(field)
                    if type(field)==int:
                        print('yyy')
                        data = int(field)
                    else:
                        data = field
                    item.setData(data, QtCore.Qt.UserRole)
                    items.append(item)
                print(items)
                self.model.appendRow(items)

输出为:

yyy
yyy
yyy
yyy
yyy
yyy
yyy
yyy
yyy
[<PyQt4.QtGui.QStandardItem object at 0x0000000006DF3948>, <PyQt4.QtGui.QStandardItem object at 0x0000000006DF38B8>, <PyQt4.QtGui.QStandardItem object at 0x0000000006DF3828>, <PyQt4.QtGui.QStandardItem object at 0x0000000006DF3798>, <PyQt4.QtGui.QStandardItem object at 0x0000000006DF3678>, <PyQt4.QtGui.QStandardItem object at 0x0000000006DF3EE8>, <PyQt4.QtGui.QStandardItem object at 0x0000000006DF3F78>, <PyQt4.QtGui.QStandardItem object at 0x00000000095D4048>, <PyQt4.QtGui.QStandardItem object at 0x00000000095D40D8>]

在控制台中一切似乎都很好,但在 GUI 上 window 它不显示 table?

你没有展示你是如何为模型创建项目的,但大概你正在做这样的事情:

item = QtGui.QStandardItem(str(value))

其中 value 是 python 数值类型。

要进行数字排序,请改为像这样设置值:

item = QtGui.QStandardItem()
item.setData(value, QtCore.Qt.DisplayRole)

但请注意,这也会使 table 自动使用旋转框来编辑单元格,这可能是您不想要的。因此,另一种解决方案是:

item = QtGui.QStandardItem(str(value))
item.setData(value, QtCore.Qt.UserRole)
...
model.setSortRole(QtCore.Qt.UserRole)

最后,对于完全自定义的排序,您还可以继承 QStandardItem:

class StandardItem(QtGui.QStandardItem):
    def __lt__(self, other):
        return int(self.text()) < int(other.text())

item = StandardItem(str(value))

更新:

这是一个演示脚本,可将 csv 文件读入 table,自动将字段转换为正确的数据类型以进行排序:

import sys, csv
from PyQt4 import QtCore, QtGui

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.model = QtGui.QStandardItemModel(self)
        self.model.setSortRole(QtCore.Qt.UserRole)
        self.tableView = QtGui.QTableView()
        self.tableView.setSortingEnabled(True)
        self.tableView.setModel(self.model)
        self.button = QtGui.QPushButton('Open CSV', self)
        self.button.clicked.connect(self.handleButton)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.tableView)
        layout.addWidget(self.button)

    def handleButton(self):
        path = QtGui.QFileDialog.getOpenFileName(
            self, 'Open CSV', '', 'CSV files (*.csv *.txt)')
        if path:
            self.model.setRowCount(0)
            with open(path) as stream:
                reader = csv.reader(stream)
                next(reader, None)
                for row in reader:
                    items = []
                    for field in row:
                        item = QtGui.QStandardItem(field)
                        for numtype in (int, float):
                            try:
                                data = numtype(field)
                                break
                            except (ValueError, OverflowError):
                                pass
                        else:
                            print('Not a number: %r' % field)
                            data = field
                        item.setData(data, QtCore.Qt.UserRole)
                        items.append(item)
                    self.model.appendRow(items)

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 150, 600, 400)
    window.show()
    sys.exit(app.exec_())