【问题标题】:Sorting in pyqt tablewidget在pyqt qtablewidget中排序
【发布时间】:2022-11-24 22:55:11
【问题描述】:

如何按最高数字对 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 = 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()

【问题讨论】:

    标签: python pyqt qtablewidget


    【解决方案1】:

    它按字母数字排序(因此,就字符串而言,'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_()
    

    【讨论】:

    • 你希望用什么方式?到目前为止你有什么 - 它是如何加载的?您真正需要知道的唯一部分是,您调用的不是 item.setText(str(text)),而是 item.setData(Qt.EditRole, QVariant(data))
    • 当我将问题中所示的 item 放入 Qvariant 时,它仍在按字母数字排序。
    • 我已经编辑了示例 - 老实说,我很惊讶它在我的测试用例中起作用。我以前总是不得不重载小于方法。试试这个,使用带有自定义 lt 方法的子类,看看是否可行。
    • 奇怪的是它仍然不起作用,如果我插入项目(或者在你的情况下 c)它保持不变,但是当我在 qvariant 你的案例行中插入 m 时,它只是在每个列中变为 1-169(行用完了),有什么想法吗?
    • 所以我的示例的重要部分是新的 QTableWidgetItem 子类,它实现了自己的 less than 方法。您仍在代码中使用标准 QTableWidgetItem。您需要使用自定义类。
    【解决方案2】:

    使用自定义 Item 的另一种方法是使用 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
    

    它使用 EditRole 获取数据进行排序,因此您可以在 DisplayRole 案例中为可用性做任何映射。它还只是尝试对可以转换为float 的值进行数字排序,或者以其他方式进行本机排序。不是最通用的方法,但似乎对我很有效。 YMMV。

    【讨论】:

    • 我们如何在 QTableWidget 中使用它?有什么例子吗?
    • 代理很简单,上面差不多就全了。创建它的实例,在其上使用 setSourceModel(&lt;original model&gt;) 并使用它代替原始模型。要进行编辑,您还需要将startEditing()stopEditing() 呼叫转接到您的原始模型。到目前为止,这似乎对我很有效。
    【解决方案3】:

    另一种对数字进行排序的可能解决方案是,添加一个特殊属性并根据该值进行比较。 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)
    

    【讨论】:

      【解决方案4】:

      一种更简单的方法是在数字文本前添加几个空格。 “ ”的 ascii 值小于“0”,因此它将按您希望的那样工作。这是我所做的:

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

      【讨论】:

      • zfill() 用'0'填充。我们在前面加上空白字符“”,而不是零。
      猜你喜欢
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      • 2018-08-02
      • 2012-08-09
      • 1970-01-01
      • 2019-05-14
      • 2015-05-29
      相关资源
      最近更新 更多