[英]PyQt5 - exit code 3 when using QSortFilterProxyModel --> filterAcceptsRow
[英]pyQt5 segfault when using QSortFilterProxyModel
在我的 Mac 上將 QSortFilterProxy 與 PyQT5 和 python3 一起使用時,我一直遇到段錯誤 (11)。
該表按預期出現,並且能夠很好地排序。 但是,當添加一個項目,然后嘗試進行后續排序時,gui 會因“segfault 11”而崩潰
我的研究沒有成果。 我希望這里有人可以提供幫助。 以下代碼是一個簡單的示例。
#! /Library/Frameworks/Python.framework/Versions/3.8/bin/python3
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QObject
from PyQt5.QtWidgets import (QApplication,
QTableView, QWidget,QPushButton,
QVBoxLayout,QMainWindow)
import sys
class MyModel(QtCore.QAbstractTableModel) :
def __init__(self,data=None,parent = None, *args) :
super(MyModel,self).__init__(parent,*args)
self.data = data or []
#Add item to the data.
def addItem(self,item) :
#add the item to to the model data.
self.data.append(item)
#Emit signal to the TableView to redraw
self.layoutChanged.emit()
#Overloaded function that must be defined.
def data(self,index,role) :
#The index (contains both x,y) and role are passed.
#The roles give instructions about how to display the model.
row = index.row()
col = index.column()
#Insert the appropriate information into the display, based
#on the column.
if role == Qt.DisplayRole :
item = self.data[row]
if (col == 0) :
return(item.name)
if (col == 1) :
return(item.num)
#rowCount must be overloaded
def rowCount(self,index) :
return(len(self.data))
#columnCount must be overloaded
def columnCount(self,index) :
return(2)
#Display headers for the columns
def headerData(self,section,orientation,role) :
if (role != Qt.DisplayRole) :
return
if (orientation != Qt.Horizontal) :
return
if (section == 0) :
return("Name")
if (section == 1) :
return("Number")
class MainWindow(QtWidgets.QMainWindow) :
def __init__(self,*args,**kwargs) :
super(MainWindow,self).__init__(*args,**kwargs)
self.data = []
proxymodel = QtCore.QSortFilterProxyModel()
proxymodel.setDynamicSortFilter(True)
proxymodel.setFilterKeyColumn(0)
self.proxymodel = proxymodel
#Create the TableView widget that will display the model
self.mytable = QtWidgets.QTableView()
self.mytable.setSortingEnabled(True)
#Create the model that will be displayed in the table
self.mymodel = MyModel(self.data)
#Assign the model to the table
self.mytable.setModel(proxymodel)
self.proxymodel.setSourceModel(self.mymodel)
#Put the table in the main widget's layout.
#Need to have a layout for its size hint.
layout = QtWidgets.QHBoxLayout()
layout.addWidget(self.mytable,0,Qt.AlignHCenter)
button = QPushButton("Add Item",self)
button.clicked.connect(self.addItem)
layout.addWidget(button)
self.layout = layout
#The actual widget.
widget = QtWidgets.QWidget()
widget.setLayout(layout)
#Show the results
self.setCentralWidget(widget)
self.show()
for i in range(10) :
item = Item(i)
self.mymodel.addItem(item)
def addItem(self) :
num = len(self.mymodel.data)
item = Item(num)
self.mymodel.addItem(item)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
app.exec()
提前致謝
問題不是 QSortFilterProxyModel,而是源 model 的錯誤實現。 另一方面,雖然使用 layoutAboutToBeChanged 解決問題不是合適的選項,如文檔中所述,如果您想將行添加到 model 那么您必須使用將在內部調用 layoutAboutToBeChanged 的beginInsertRows()
和endInsertRows()
方法信號,考慮到上述情況,最合適的實現是:
class MyModel(QtCore.QAbstractTableModel):
def __init__(self, data=None, parent=None, *args):
super(MyModel, self).__init__(parent, *args)
self.data = data or []
# Add item to the data.
def addItem(self, item):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
self.data.append(item)
self.endInsertRows()
def data(self, index, role):
if not index.isValid(): return row = index.row() col = index.column() if (row < 0 or row >= self.rowCount()) and ( col < 0 or col >= self.columnCount() ): return
if role == Qt.DisplayRole:
item = self.data[row]
if col == 0:
return item.name
if col == 1:
return item.num
def rowCount(self, index=QtCore.QModelIndex()):
return len(self.data)
def columnCount(self, index=QtCore.QModelIndex()):
return 2
def headerData(self, section, orientation, role):
if role != Qt.DisplayRole:
return
if orientation != Qt.Horizontal:
return
if section == 0:
return "Name"
if section == 1:
return "Number"
更改表格時發出“layoutAboutToBeChanged”信號。
class MyModel(QtCore.QAbstractTableModel) :
def __init__(self,data=None,parent = None, *args) :
super(MyModel,self).__init__(parent,*args)
self.data = data or []
#Add item to the data.
def addItem(self,item) :
#add the item to to the model data.
self.data.append(item)
**#Emit signal to the TableView to redraw**
self.layoutAboutToBeChanged.emit()
self.layoutChanged.emit()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.