Python pyqt tablewidget中的排序
如何在pyqt中按最大数对列进行排序?目前我有Python pyqt tablewidget中的排序,python,pyqt,qtablewidget,Python,Pyqt,Qtablewidget,如何在pyqt中按最大数对列进行排序?目前我有setSortingEnabled(True),它只按最多的数字排序(例如1,1,1,1,2,2,2,3,3)。例如,我想按最高的数字排序(例如58,25,15,10)。谢谢 数据更新: def setmydata(self): for n, key in enumerate(self.data): for m, item in enumerate(self.data[key]): newitem =
setSortingEnabled(True)
,它只按最多的数字排序(例如1,1,1,1,2,2,2,3,3)。例如,我想按最高的数字排序(例如58,25,15,10)。谢谢
数据更新:
def setmydata(self):
for n, key in enumerate(self.data):
for m, item in enumerate(self.data[key]):
newitem = QtGui.QTableWidgetItem(item)
self.setItem(m, n, newitem)
全部代码:
import sys
from PyQt4.QtGui import QTableWidget
from PyQt4 import QtGui,QtCore,Qt
import MySQLdb as mdb
from functools import partial
import time
class Window(QtGui.QDialog):
process_column_signal = QtCore.pyqtSignal()
def __init__(self,parent=None):
super(Window, self).__init__()
self.layout = QtGui.QVBoxLayout(self)
self.db = mdb.connect('serv','user','pass','db')
self.model = self.db.cursor()
self.initialData = self.get_data_status()
self.table1 = MyTableStatus(self.initialData, 145, 4)
callback = partial(self.process_column,self.table1)
self.process_column_signal.connect(callback)
self.layout.addWidget(self.table1)
self.timer_status = QtCore.QTimer()
self.timer_status.timeout.connect(self.updateAllViews)
self.timer_status.timeout.connect(self.some_method)
# check every half-second
self.timer_status.start(1000*5)
def some_method(self):
self.process_column_signal.emit()
def get_data_status(self):
self.model.execute("""SELECT cpu_juliet,cpu,cpu_julietleft FROM status
WHERE date = (SELECT MAX(date) FROM status)""")
rows_status_cpu = self.model.fetchone()
self.listb1 = ['%s' % rows_status_cpu[0],'%s' % rows_status_cpu[2],'%s' % rows_status_cpu[1],'%s' % rows_status_cpu[1]]#['%s %s' % self.rows_status]
self.model.execute("""SELECT disk_queue_juliet FROM status
WHERE date = (SELECT MAX(date) FROM status)""")
rows_status_disk_queue = self.model.fetchone()
self.lista1 = 'Juliet','Julietleft','Pong','Hulk'
self.listc1 = ['%s' % rows_status_disk_queue,'%s' % rows_status_disk_queue,'%s' % rows_status_disk_queue,'%s' % rows_status_disk_queue ]
if self.listb1[0] >= '80' or self.listc1[0] >= '9':
server_status_Juliet = 'WARNING'
else:
server_status_Juliet = 'Normal'
if self.listb1[1] >= '80' or self.listc1[1] >= '9':
server_status_Julietleft = 'WARNING'
else:
server_status_Julietleft = 'Normal'
if self.listb1[2] >= '80' or self.listc1[2] >= '9':
server_status_Pong = 'WARNING'
else:
server_status_Pong = 'Normal'
if self.listb1[3] >= '80' or self.listc1[3] >= '9':
server_status_Hulk = 'WARNING'
else:
server_status_Hulk = 'Normal'
self.listd1 = ['%s' % server_status_Juliet,'%s' % server_status_Julietleft,'%s' % server_status_Pong,'%s' % server_status_Hulk]
# if server_status_Hulk == "WARNING": #or server_status_Pong == "WARNING" or server_status_Julietleft == "WARNING" or server_status_Juliet == "WARNING":
# self.serverstatus.setStyleSheet("QTabWidget {color: red}")
#status label conditions
self.mystruct1 = {'A':self.lista1, 'B':self.listb1, 'C':self.listc1, 'D':self.listd1}
return self.mystruct1
def updateAllViews(self):
_ = self.get_data_status()
self.updateTable()
def updateTable(self):
self.table1.updateFromDict(self.mystruct1)
def process_column(table1, processCol=1):
colCount = table1.table1.rowCount()
for row in xrange(table1.table1.rowCount()):
for col in xrange(4):
try:
item = table1.table1.item(row, 3)
text = item.text()
if (float(text) >= 20.0 ):
for col in xrange(colCount):
print row
item = table1.table1.item(row,col)
item.setBackground(QtGui.QBrush(QtCore.Qt.yellow))
except:
pass
class MyTableStatus(QTableWidget):
def __init__(self, thestruct, *args):
QTableWidget.__init__(self, *args)
self.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Preferred)
self.setHorizontalHeaderLabels(['Server', 'Avg. Disk Queue','CPU Load',"Status"])
self.setSortingEnabled(False)
self.data = {}
self.setmydata()
def updateFromDict(self, aDict):
self.data.clear()
self.data.update(aDict)
self.setmydata()
def setmydata(self):
for n, key in enumerate(self.data):
for m, item in enumerate(self.data[key]):
newitem = QtGui.QTableWidgetItem(item)
self.setItem(m, n, newitem)
def main():
app = QtGui.QApplication(sys.argv)
app.setStyle(QtGui.QStyleFactory.create("plastique"))
main_window = Window()
main_window.repaint()
main_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
它的字母数字排序(因此,就字符串而言,'1','10','11','12','2','20','21','22','3','4'等是正确的排序顺序。对于QTableWidgetItem,如果使用setData(Qt.EditRole,value)方法,排序顺序将起作用。这取决于您的Qt版本(我假设)您可能必须重载表小部件项的小于方法
from PyQt4.QtCore import Qt, QVariant
from PyQt4.QtGui import QApplication, QTableWidget, QTableWidgetItem
class MyTableWidgetItem(QTableWidgetItem):
def __lt__(self, other):
if ( isinstance(other, QTableWidgetItem) ):
my_value, my_ok = self.data(Qt.EditRole).toInt()
other_value, other_ok = other.data(Qt.EditRole).toInt()
if ( my_ok and other_ok ):
return my_value < other_value
return super(MyTableWidgetItem, self).__lt__(other)
if ( __name__ == '__main__' ):
app = None
if ( QApplication.instance() is None ):
app = QApplication([])
widget = QTableWidget()
widget.setWindowFlags(Qt.Dialog)
widget.setSortingEnabled(True)
widget.setRowCount(50)
widget.setColumnCount(3)
for row in range(50):
# create a normal QTableWidgetItem
a = QTableWidgetItem()
a.setText(str(row))
widget.setItem(row, 0, a)
# create a proper sorted item
b = QTableWidgetItem()
b.setData(Qt.EditRole, QVariant(row))
widget.setItem(row, 1, b)
# create a custom sorted item
c = MyTableWidgetItem()
c.setData(Qt.EditRole, QVariant(row))
widget.setItem(row, 2, c)
widget.show()
if ( app ):
app.exec_()
从PyQt4.QtCore导入Qt,QVariant
从PyQt4.QtGui导入QApplication、QTableWidget、QTableWidgetItem
类MyTableWidgetItem(QTableWidgetItem):
定义(自身、其他):
如果(isinstance(其他,QTableWidgetItem)):
my_值,my_ok=self.data(Qt.EditRole).toInt()
other_值,other_ok=other.data(Qt.EditRole).toInt()
如果(我的ok和其他ok):
返回我的值<其他值
返回超级(MyTableWidgetItem,self)。\u\lt\u(其他)
如果(uuuu name_uuuuuu=='uuuuuu main_uuuuu'):
app=无
如果(QApplication.instance()为无):
app=QApplication([])
widget=QTableWidget()
widget.setWindowFlags(Qt.Dialog)
widget.setSortingEnabled(真)
widget.setRowCount(50)
widget.setColumnCount(3)
对于范围(50)中的行:
#创建普通QTableWidgetItem
a=QTableWidgetItem()
a、 setText(str(世界其他地区))
widget.setItem(行,0,a)
#创建一个正确排序的项目
b=QTableWidgetItem()
b、 setData(Qt.EditRole,QVariant(行))
widget.setItem(第1行,b)
#创建自定义排序项
c=MyTableWidgetItem()
c、 setData(Qt.EditRole,QVariant(行))
widget.setItem(第2行,c)
widget.show()
如果(应用程序):
app.exec()
使用自定义项的替代方法是使用SortFilterProxy
(您可能无论如何都应该这样做)。在这种情况下,您可以定义一个lessThan
方法,用于排序。这是我的:
class SortFilterProxyModel(QSortFilterProxyModel):
def lessThan(self, left_index, right_index):
left_var = left_index.data(Qt.EditRole)
right_var = right_index.data(Qt.EditRole)
try:
return float(left_var) < float(right_var)
except (ValueError, TypeError):
pass
return left_var < right_var
类SortFilterProxyModel(QSortFilterProxyModel):
def lessThan(自身、左索引、右索引):
left_var=left_index.data(Qt.EditRole)
right\u var=right\u index.data(Qt.EditRole)
尝试:
返回浮点(左变量)<浮点(右变量)
除了(ValueError、TypeError):
通过
返回左变量<右变量
它使用EditRole
获取数据进行排序,因此您可以在DisplayRole
案例中进行任何可用性映射。它还尝试对可以转换为float
或本机排序的值进行数字排序。这不是最通用的方法,但在r me.YMMV.一种更简单的方法是在数字文本前加上一些空格。ascii值“”小于“0”,因此它将按照您的要求工作。我的操作如下:
element = str(num) # convert to str
padded = (' '+element)[-5:] # make all elements the same length
item.setText(padded)
对数值排序的另一个可能的解决方案是,添加一个特殊的属性,并基于该值对其进行比较。Mybe这是一种更类似java的方法
class MyTableWidgetItem(QTableWidgetItem):
def __init__(self, value):
QTableWidgetItem.__init__(self)
self.value = value
def __lt__(self, other):
if isinstance(other, MyTableWidgetItem):
return self.value < other.value
return super(QTableWidgetItem, self).__lt__(other)
类MyTableWidgetItem(QTableWidgetItem):
定义初始值(自身,值):
QTableWidgetItem.\uuuuuu初始化\uuuuuuuuu(自)
自我价值=价值
定义(自身、其他):
如果isinstance(其他,MyTableWidgetItem):
返回self.value
您希望采用什么方法?到目前为止您有什么方法?它是如何加载的?您需要真正了解的唯一一点是,不是调用:item.setText(str(text)),而是调用item.setData(Qt.EditRole,QVariant(data))当我将问题中所示的item
放入Qvariant中时,它仍然是字母数字排序。我编辑了这个示例-老实说,我很惊讶它在我的测试用例中起作用。我以前总是不得不重载“小于”方法。试试这个,使用一个带有自定义lt方法的子类,看看它是否起作用。奇怪的是,它确实起作用了仍然不起作用,如果我插入项(或在您的案例c中),它将保持不变,但是当我在您的案例行中插入m时,它在每个列中只会变为1-169(已使用的行数),知道为什么吗?所以我的示例的重要部分是新的QTableWidgetItem子类,它实现了自己的小于方法。您仍然在代码中使用标准的QTableWidgetItem。您需要使用自定义类。我们如何在QTableWidget中使用它?任何示例?代理都很简单,上面的内容几乎完成了。创建一个它的实例,在其上使用setSourceModel()
,并使用它而不是原始模型。要进行编辑,还需要将startEditing()
和stopEditing()
调用转发到原始模型。到目前为止,这似乎对我很有效。zfill()用“0”填充。我们正在预写空白字符“”,而不是零。