【问题标题】:pyQt5 segfault when using QSortFilterProxyModel使用 QSortFilterProxyModel 时的 pyQt5 段错误
【发布时间】:2021-01-04 20:19:25
【问题描述】:

在我的 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()

谢谢,提前

【问题讨论】:

    标签: python python-3.x segmentation-fault pyqt5 qsortfilterproxymodel


    【解决方案1】:

    问题不是 QSortFilterProxyModel 而是源模型的错误实现。另一方面,虽然使用 layoutAboutToBeChanged 解决问题不是合适的选项,如the docs 中所述,如果您想向模型添加行,那么您必须使用将在内部调用的beginInsertRows()endInsertRows() 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):
            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"

    【讨论】:

      【解决方案2】:

      更改表格时发出“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()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-08
        • 2020-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多