[英]PyQt5: phantom columns when using QTableView.setSortingEnabled and QSortFilterProxyModel
我有一个自定义的Qt表模型,允许用户在创建后添加列和行。 我正在尝试使用QSortFilterProxyModel / QTableView设置显示此表,但是当我尝试在表视图上启用排序时,我会遇到奇怪的行为。 我的视图启动并正确显示添加的数据:
但是,当我单击其中一个列标题(进行排序)时,幻像列将添加到视图中。
有没有人见过这个或知道发生了什么? 我当然是Qt的新手,所以也许我只是接近这个错误的方式。 谢谢。
# -*- mode:python; mode:auto-fill; fill-column:79; coding:utf-8 -*-
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
# =====================================================================
# =====================================================================
class SimpleProxyModel(QSortFilterProxyModel):
def filterAcceptsColumn(self, col, index):
return True
# =====================================================================
# =====================================================================
class SimpleModel(QAbstractTableModel):
def __init__(self):
super(SimpleModel, self).__init__()
self._data = {}
def rowCount(self, index=QModelIndex()):
if len(self._data.values()) > 0:
return len(self._data.values()[0])
else:
return 0
def columnCount(self, index=QModelIndex()):
return len(self._data.keys())
def data( self, index, role = Qt.DisplayRole ):
row, col = index.row(), index.column()
if ( not index.isValid() or
not ( 0 <= row < self.rowCount() ) or
not ( 0 <= col < self.columnCount() ) ):
return QVariant()
if role == Qt.DisplayRole:
return QVariant( self._data[col][row] )
return QVariant()
def addData( self, col, val):
new_col = False
# Turn on flag for new column
if col not in self._data.keys():
new_col = True
if new_col:
self.beginInsertColumns(QModelIndex(), self.columnCount(),self.columnCount())
# Catch this column up with the others by adding blank rows
self._data[col] = [""] * self.rowCount()
self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
# Add data to each column, either the value specified or a blank
for i in range(self.columnCount()):
if i == col:
self._data[i].append(val)
else:
self._data[i].append( "" )
self.endInsertRows()
if new_col:
self.endInsertColumns()
# =====================================================================
# =====================================================================
class SimpleView(QWidget):
def __init__(self, parent=None):
super(SimpleView, self).__init__(parent)
self._mainmodel = None
self._proxymodel = None
self._tableview = QTableView()
self._tableview.setSortingEnabled(True)
layout = QVBoxLayout()
layout.addWidget( self._tableview )
self.setLayout(layout)
def setModel(self, model):
self._mainmodel = model
proxy = SimpleProxyModel()
proxy.setSourceModel(model)
self._tableview.setModel(proxy)
# =====================================================================
# =====================================================================
app = QApplication([])
v = SimpleView()
m = SimpleModel()
v.setModel( m )
m.addData(0,1)
m.addData(0,2)
m.addData(1,3)
v.show()
app.exec_()
Qt文档对此非常清楚。 你必须调用endInsertRows后beginInsertRows和endInsertColumns后beginInsertColumns 。
上面最后一个链接中最相关的一点是:
注意:此函数发出columnsAboutToBeInserted()信号,连接的视图(或代理)必须在插入数据之前处理。 否则,视图可能最终处于无效状态。
因此, 在开始任何其他插入/删除之前,必须调用endInsertColum()
。
看起来问题出在我的SimpleModel.addData
方法中,并且与嵌套列和行插入的方式有关。 如果将此方法更改为首先插入新列,然后插入新行,则不会显示幻像列。
def addData( self, col, val):
if col not in self._data.keys():
self.beginInsertColumns(QModelIndex(), self.columnCount(),self.columnCount())
# Catch this column up with the others by adding blank rows
self._data[col] = [""] * self.rowCount()
self.endInsertColumns()
self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
# Add data to each column, either the value specified or a blank
for i in range(self.columnCount()):
if i == col:
self._data[i].append(val)
else:
self._data[i].append( "" )
self.endInsertRows()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.