在QTableWidget中使用setCellWidget对一列进行排序

3

我想对一个包含进度条的列进行排序。我希望按照进度条的值对该列进行排序。非常感谢您的帮助。

在这里输入图片描述
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys


class Example(QMainWindow):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        self.tablew = Table(self)
        self.setCentralWidget(self.tablew)

        self.setGeometry(300, 300, 300, 200)
        self.show()


class ProgressBar(QProgressBar):

    def __init__(self, value, parent=None):
        QProgressBar.__init__(self)
        self.setMinimum(1)
        self.setMaximum(5.0)
        self.setValue(value)
        self.setFormat('{0:.5f}'.format(value))
        style = ''' QProgressBar{max-height: 15px;text-align: center;}'''
        self.setStyleSheet(style)


class Table(QTableWidget):

    def __init__(self,   parent=None):
        QTableWidget.__init__(self)
        self.setColumnCount(2)
        self.setHorizontalHeaderLabels(['id', 'status'])
        header = self.horizontalHeader()
        header.setResizeMode(QHeaderView.Stretch)
        self.setSortingEnabled(True)
        self.loadData()
        #

    def loadData(self):
        #
        tableData = [[89, 4.8], [99, 3.9], [101, 2.6], [105, 4]]
        #
        self.setRowCount(len(tableData))
        #
        for index, value in enumerate(tableData):
            # column1
            item = QTableWidgetItem()
            item.setData(Qt.DisplayRole, value[0])
            self.setItem(index, 0, item)
            # column2
            self.setCellWidget(index, 1, ProgressBar(value[1]))
        #


def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

更新: 根据@ekhumoro的答案,以下是完整的代码,但是它无法正确排序。 在手动排序列后附上截图 排序问题

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys


class Example(QMainWindow):

    def __init__(self):
        super(Example, self).__init__()

        self.initUI()

    def initUI(self):

        self.tablew = Table(self)
        self.setCentralWidget(self.tablew)

        self.setGeometry(300, 300, 300, 200)
        self.show()


class ProgressBar(QProgressBar):

    def __init__(self, value, parent=None):
        QProgressBar.__init__(self)
        self.setMinimum(1)
        self.setMaximum(5.0)
        self.setValue(value)
        self.setFormat('{0:.5f}'.format(value))
        style = ''' QProgressBar{max-height: 15px;text-align: center;}'''
        self.setStyleSheet(style)


class Table(QTableWidget):

    def __init__(self,   parent=None):
        QTableWidget.__init__(self)
        self.setColumnCount(2)
        self.setHorizontalHeaderLabels(['id', 'status'])
        header = self.horizontalHeader()
        header.setResizeMode(QHeaderView.Stretch)
        self.setSortingEnabled(True)
        self.loadData()
        #

    def loadData(self):
        #
        tableData = [[89, 4.8], [99, 3.9], [101, 2.6], [105, 4]]
        #
        self.setRowCount(len(tableData))
        #
        for index, value in enumerate(tableData):
            # column1
            item = QTableWidgetItem()
            item.setData(Qt.DisplayRole, value[0])
            self.setItem(index, 0, item)
            # column2
            item = ProgressWidgetItem()
            self.setItem(index, 1, item)
            item.updateValue(value[1])
            progress = ProgressBar(value[1])
            self.setCellWidget(index, 1, progress)
            progress.valueChanged.connect(item.updateValue)
        self.sortItems(1, Qt.DescendingOrder)


class ProgressWidgetItem(QTableWidgetItem):

    def __lt__(self, other):
        return self.data(Qt.UserRole) < other.data(Qt.UserRole)

    def updateValue(self, value):
        self.setData(Qt.UserRole, value)


def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
1个回答

5
您可以继承QTableWidgetItem,重新实现__lt__方法,然后在进度条列中添加空白项:
            # column2
            item = ProgressWidgetItem()
            self.setItem(index, 1, item)
            item.updateValue(value[1])
            progress = ProgressBar(value[1])
            self.setCellWidget(index, 1, progress)
            progress.valueChanged.connect(item.updateValue)
        self.sortItems(1, Qt.DescendingOrder)


class ProgressWidgetItem(QTableWidgetItem):
    def __lt__(self, other):
        # python 3
        # return self.data(Qt.UserRole) < other.data(Qt.UserRole)
        # python 2
        return (self.data(Qt.UserRole).toPyObject() <
                other.data(Qt.UserRole).toPyObject())

    def updateValue(self, value):
        self.setData(Qt.UserRole, value)

PS:

__lt__的实现在Python 2和Python 3中是不同的,因为后者默认返回正常的Python类型而不是QVariantQString。虽然可以直接测试两个QVariant对象是否相等,但无法确定一个是否小于另一个(即使它们包含相同类型的值)。

在Python 2中,您可以通过在应用程序中第一次导入PyQt之前放置以下代码来消除QVariantQString

import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)

这将使行为与Python 3相同,这意味着您永远不必使用丑陋的代码,如variant.toPyObject()str(qtstring)


我使用了您的建议,但当我应用排序时,得到的顺序是2.6、3.9、4.8、4.0。4.0被固定在底部,无论我多少次对表格进行排序...有什么想法吗? - django
@django。我再次检查了一遍,对我来说它完美地运行了。你确定你做出了正确的更改吗?复制我的代码并替换loadData的最后三行。 - ekhumoro
请检查上面。我已经更新了我的帖子,包括新的代码和问题的截图。 - django
@django。请仔细阅读我的先前评论:复制我的代码并替换loadData最后三行 - ekhumoro
我已经用你的代码替换了 loadData 的最后三行,但是它对我没有起作用。正如你建议的那样,我已经更新了我的帖子,并在末尾附上了问题的截图。这可能是 Python 版本的问题吗?我正在使用 Python 2.7.6.1 和 QT 4.8.5。 - django
@django。出于某种原因,我确信你正在使用python3。无论如何,请查看我的更新代码和解释以获取一些解决方案。 - ekhumoro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接