在 QTableWidget 中使用 setCellWidget 对列进行排序
sort a column with setCellWidget in QTableWidget
我正在尝试对其中包含进度条的列进行排序。我希望列按进度条值排序。任何帮助都感激不尽
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()
您可以继承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 是不同的,因为默认情况下,后者将 return 普通 Python 类型而不是 QVariant
和 QString
。可以直接测试两个 QVariant
对象是否相等,但不能测试一个是否小于另一个(即使它们包含相同类型的值)。
在 Python 2 中,您可以通过在应用程序中第一个 PyQt 导入之前放置以下代码来消除 QVariant
和 QString
:
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
这将使行为与 Python 3 相同,并且意味着您永远不必使用像 variant.toPyObject()
或 str(qtstring)
.
这样丑陋的代码
我正在尝试对其中包含进度条的列进行排序。我希望列按进度条值排序。任何帮助都感激不尽
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()
您可以继承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 是不同的,因为默认情况下,后者将 return 普通 Python 类型而不是 QVariant
和 QString
。可以直接测试两个 QVariant
对象是否相等,但不能测试一个是否小于另一个(即使它们包含相同类型的值)。
在 Python 2 中,您可以通过在应用程序中第一个 PyQt 导入之前放置以下代码来消除 QVariant
和 QString
:
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
这将使行为与 Python 3 相同,并且意味着您永远不必使用像 variant.toPyObject()
或 str(qtstring)
.