PyQt中QTableWidget按IP地址升序排序的实现与报错解决
PyQt QTableWidget IP地址列升序排序实现及崩溃问题解决
崩溃问题根因修复
- 不要在插入数据的循环内部调用
setSortingEnabled(True),每插入一行触发一次全表排序,数据量大时会直接触发栈溢出导致进程退出,需将该方法调用移到所有数据插入完成后。 - 自定义
IpAddressItem类需正确重写<比较运算符(即Python中的__lt__方法),排序时的比较逻辑依赖该方法,实现错误会直接触发运行时异常。
正确的IP排序实现方案
首先实现支持IP数值比较的自定义表格项类:
from PyQt5 import QtWidgets, QtCore class IpAddressItem(QtWidgets.QTableWidgetItem): def __lt__(self, other): # 把IP字符串转成四段整数元组用于比较 def ip_to_tuple(ip_str): try: return tuple(map(int, ip_str.split('.'))) except (ValueError, AttributeError): # 非法IP默认排到列表末尾 return (255, 255, 255, 255) return ip_to_tuple(self.text()) < ip_to_tuple(other.text())
修改后的数据插入逻辑:
tablerow = 0 # 插入数据前先关闭排序,避免插入过程中触发不必要的性能损耗 self.tableWidget.setSortingEnabled(False) for row in results: self.tableWidget.setItem(tablerow, 0, QTableWidgetItem(str(row[0]))) self.tableWidget.setItem(tablerow, 1, QTableWidgetItem(row[1])) self.tableWidget.setItem(tablerow, 2, QTableWidgetItem(row[2])) self.tableWidget.setItem(tablerow, 3, QTableWidgetItem(row[3])) self.tableWidget.setItem(tablerow, 4, QTableWidgetItem(row[4])) # 第5列使用自定义的IP项类 self.tableWidget.setItem(tablerow, 5, IpAddressItem(str(row[5]))) self.tableWidget.setItem(tablerow, 6, QTableWidgetItem(row[6])) self.tableWidget.setItem(tablerow, 7, QTableWidgetItem(row[7])) self.tableWidget.setItem(tablerow, 8, QTableWidgetItem(decryption(to_enc=row[8]))) self.tableWidget.setItem(tablerow, 9, QTableWidgetItem(row[9])) self.tableWidget.setItem(tablerow, 10, QTableWidgetItem(row[10])) self.tableWidget.setItem(tablerow, 11, QTableWidgetItem(row[11])) tablerow += 1 # 所有数据插入完成后再开启排序并执行IP列升序排序 self.tableWidget.setSortingEnabled(True) self.tableWidget.sortItems(5, QtCore.Qt.AscendingOrder)
实现说明
- 自定义
IpAddressItem的__lt__方法会将IP字符串拆分为四个整数组成的元组,Python元组的逐位比较逻辑刚好匹配IP地址的数值排序规则,完全符合你给出的预期排序效果。 - 增加了非法IP的异常捕获逻辑,避免格式错误的IP导致排序时崩溃,非法IP会默认排在列表末尾。
- 插入数据前先关闭排序,所有数据插入完成后再开启排序,大幅提升大量数据下的插入和排序性能,避免栈溢出问题。
内容的提问来源于stack exchange,提问作者Milan Bültmann
相关产品推荐
相关产品推荐

