简体   繁体   English

在pyqt tablewidget中排序

[英]Sorting in pyqt tablewidget

How can I sort a coloumn in pyqt by the highest number? 如何用最高数字对pyqt中的coloumn进行排序? Currently I have setSortingEnabled(True) and that only sorts it by the most numbers (ex. 1,1,1,1,2,2,2,3,3) i want to do it by the highest number for example (ex. 58,25,15,10). 目前我有setSortingEnabled(True)并且只按最大数量排序(例如1,1,1,1,2,2,2,3,3)我想以最高数字为例进行排序(例如.58,25,15,10)。 Thanks! 谢谢!

Data Update: 数据更新:

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)

Whole code: 整码:

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()

Its sorting alpha-numerically (so, in terms of strings, '1', '10', '11', '12', '2', '20', '21', '22', '3', '4' etc. is the proper sort order. It appears that for a QTableWidgetItem, if you use the setData(Qt.EditRole, value) method, the sort order will work. Depending on your version of Qt (I assume) you may have to overload the less than method of your table widget item. 它按字母顺序排序(因此,就字符串而言,'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_()

An alternative to using a custom Item is to use a SortFilterProxy (which you probably should be doing anyway). 使用自定义Item的另一种方法是使用SortFilterProxy (无论如何你可能应该这样做)。 In that case you can define a lessThan method that will be used for sorting. 在这种情况下,您可以定义一个将用于排序的lessThan方法。 Here's mine: 这是我的:

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

It uses the EditRole to get the data for sorting, so you can do whatever mapping for usability you want to do in the DisplayRole cases. 它使用EditRole来获取用于排序的数据,因此您可以在DisplayRole案例中执行您想要执行的任何映射。 It also just tries to do numerical sorting for values than can be converted to float , or native sorting otherwise. 它也只是尝试对值进行数值排序,而不是转换为float ,否则进行本机排序。 Not the most general approach, but seems to work well for me. 不是最通用的方法,但似乎对我有用。 YMMV. 因人而异。

Another possible solution to sort numeric could be, to add a special attribute and compare it based on that value. 另一种可能的数字排序解决方案是,添加一个特殊属性并根据该值进行比较。 Mybe that is a more java like way. 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)

A simpler way is to prepend a few blank spaces to your numeric text. 一种更简单的方法是在数字文本前加上一些空格。 The ascii value of ' ' is less than '0', so it will work as you want it to. ''的ascii值小于'0',因此它可以按您的意愿工作。 Here is what I do: 这是我做的:

element = str(num)                # convert to str
padded = ('     '+element)[-5:]   # make all elements the same length
item.setText(padded)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM