繁体   English   中英

pyQt5 使用 QSortFilterProxyModel 时的段错误

[英]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.

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