简体   繁体   English

从 QTableView 中清除多余的行/列

[英]clear excess rows/colums from QTableView

I have a created a proxy model that filters a QStringListModel and formats the remaining indexes for a QTableView.我创建了一个代理 model,它过滤 QStringListModel 并为 QTableView 格式化剩余的索引。 When the filter is applied the table view continues to display the rows and columns of the original unfiltered data, leaving a large empty scrollable section.当应用过滤器时,表视图继续显示原始未过滤数据的行和列,留下一个大的空白可滚动部分。 I've updated the rows and columns in the model so, I don't think that's the cause.我已经更新了 model 中的行和列,所以我认为这不是原因。 I would have thought it would update that when the dataChanged signal was emitted.我原以为它会在发出 dataChanged 信号时更新它。

I'm sure the solution is pretty easy but this is my first time making a proxymodel.我确定解决方案非常简单,但这是我第一次制作代理模型。

在此处输入图像描述

在此处输入图像描述

# Standard modules
import os
import re
import sys

# QT modules
from Qt import QtGui
from Qt import QtCore
from Qt import QtWidgets

COL_HEIGHT = 10
class TableModel(QtCore.QAbstractProxyModel):
    def __init__(self, parent):
        super(TableModel, self).__init__(parent)
        self.rows = 0
        self.cols = 0
        self.count = 0
        self.i_map = {}
        self.p_map = {}
        self.regex = re.compile("")

    def sourceDataChanged(self, topLeft, bottomRight):
        self.dataChanged.emit(self.mapFromSource(topLeft), self.mapFromSource(bottomRight))

    def setFilter(self, exp):
        self.regex = re.compile(exp)      
        rows = self.rows-1
        cols = self.cols-1

        self.build_map(self.sourceModel())
        self.dataChanged.emit(self.index(0,0), self.index(rows, cols))

    def build_map(self, model):
        model_rows = model.rowCount(QtCore.QModelIndex())
        
        self.p_map = {}
        self.i_map = {}
        count = 0
        
        for i in range(model_rows):
            index = model.index(i, 0, QtCore.QModelIndex())
            if(self.regex.search(index.data())):
                self.p_map[i] = count
                self.i_map[count] = index
                count += 1
        
        if count:
            self.rows = min(count + 1, COL_HEIGHT)
            self.cols = count / COL_HEIGHT + 1
        else:
            self.rows = 0
            self.cols = 0
        self.count = count

    def setSourceModel(self, model):
        super(TableModel, self).setSourceModel(model)
        self.build_map(model)
        model.dataChanged.connect(self.sourceDataChanged)
    
    def mapFromSource(self, index):
        i_row = index.row()
        if i_row < 0:
            return QtCore.QModelIndex()
        row = self.p_map[i_row] % COL_HEIGHT
        col = self.p_map[i_row] / COL_HEIGHT
        return self.createIndex(row, col)
    
    def mapToSource(self, index):
        if index.row() < 0:
            return QtCore.QModelIndex()
        pos = index.row() + index.column() * COL_HEIGHT
        if pos in self.i_map:
            return self.i_map[pos]
        return QtCore.QModelIndex()
    
    def index(self, row, column, parent = QtCore.QModelIndex()):
        return self.createIndex(row, column)

    def rowCount(self, parent = QtCore.QModelIndex()):
        return self.rows
    def columnCount(self,parent = QtCore.QModelIndex()):
        return self.cols

    def parent(self, index):
        return QtCore.QModelIndex()

Change to script to emit layoutAboutToBeChanged before the change and layoutChanged after looks to have solved my issue.更改为脚本以在更改之前发出layoutAboutToBeChanged并在看起来解决了我的问题之后发出layoutChanged Thanks to musicamante for pointing me at them.感谢 musicamante 指点我。

Updated code:更新代码:

def setFilter(self, exp):
    self.regex = re.compile(exp)      
    rows = self.rows-1
    cols = self.cols-1

    self.layoutAboutToBeChanged.emit()
    self.build_map(self.sourceModel())
    self.dataChanged.emit(self.index(0,0), self.index(rows, cols))
    self.layoutChanged.emit()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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