QTableView由模型驱动时如何刷新 [英] How to refresh QTableView when it is driven by model

查看:47
本文介绍了QTableView由模型驱动时如何刷新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码创建了由 self.myModel (QAbstractTableModel) 驱动的 QTableView.'Show All' self.checkBox 链接到 self.myModel.cbChanged() 方法.

The code below creates QTableView driven by self.myModel (QAbstractTableModel). 'Show All' self.checkBox is linked to self.myModel.cbChanged() method.

问题:如何修改此代码,以便在选中复选框后立即刷新QTableView"?

Question: How to modify this code so 'QTableView' gets refreshed as soon as checkbox is checked?

目标:当复选框被选中时,我们希望显示奇数项.以及要隐藏的偶数项.当复选框关闭(未选中)时,我们希望显示偶数项.隐藏所有奇数项.

The goal: when the checkbox is checked we want the odd numbered items to be displayed. And the even numbered items to be hidden. When the checkbox is off (unchecked) we want the even numbered items to be displayed. All the odd numbered items are hidden.

import sys, os
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)      

        self.items=['One','Two','Three','Four','Five','Six','Seven']
        self.cb_status=True

    def rowCount(self, parent=QtCore.QModelIndex()):   
        return len(self.items)
    def columnCount(self, index=QtCore.QModelIndex()):
        return 1

    def data(self, index, role):
        if not index.isValid() or not (0<=index.row()<len(self.items)):
            return QtCore.QVariant()

        item=str(self.items[index.row()])

        if role==QtCore.Qt.DisplayRole and self.cb_status:
            return item
        else:
            return QtCore.QVariant()

    def cbChanged(self, arg=None):
        self.cb_status=arg  

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        mainLayout=QtGui.QHBoxLayout()
        self.setLayout(mainLayout)   

        self.viewA=QtGui.QTableView()
        self.viewA.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) 

        self.myModel=TableModel()
        self.viewA.setModel(self.myModel)

        self.checkBox=QtGui.QCheckBox("Show All")  
        self.checkBox.stateChanged.connect(self.myModel.cbChanged)
        self.checkBox.setChecked(self.myModel.cb_status)

        mainLayout.addWidget(self.viewA)
        mainLayout.addWidget(self.checkBox)  
        self.show()   

view=Window() 
sys.exit(app.exec_())

推荐答案

为此,您可以使用 QSortFilterProxyModel 类.这样,我们就不会篡改实际源模型的结构或其数据.我们只是将主源映射到这个代理模型,视图使用它来显示过滤/排序的数据.我们可以随意影响代理模型中的数据,而不会有篡改源模型的风险.

For this purpose, you can use the QSortFilterProxyModel class. This way, we don't tamper with the actual source model's structure or it's data. We just map the main source to this proxy model, which the view uses to display filtered/sorted data. We can affect the data in the proxy model as we please, without the risk of tampering the source model.

这是您修改后使用的源代码:

Here is your source code modified to use this:

import sys, os
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.items=['One','Two','Three','Four','Five','Six','Seven']

    def rowCount(self, parent=QtCore.QModelIndex()):   
        return len(self.items)
    def columnCount(self, index=QtCore.QModelIndex()):
        return 1

    def data(self, index, role):
        if not index.isValid() or not (0<=index.row()<len(self.items)):
            return QtCore.QVariant()

        item=str(self.items[index.row()])

        if role==QtCore.Qt.DisplayRole:
            return item
        else:
            return QtCore.QVariant()


class MySortFilterProxyModel(QtGui.QSortFilterProxyModel):
    def __init__(self):
        super(MySortFilterProxyModel, self).__init__()
        self.cb_status=True

    def cbChanged(self, arg=None):
        self.cb_status=arg
        print self.cb_status
        self.invalidateFilter()

    def filterAcceptsRow(self, sourceRow, sourceParent):
        print_when_odd_flag = self.cb_status
        is_odd = True
        index = self.sourceModel().index(sourceRow, 0, sourceParent)
        print "My Row Data: %s" % self.sourceModel().data(index, role=QtCore.Qt.DisplayRole)

        if (sourceRow + 1) % 2 == 0:
            is_odd = False

        if print_when_odd_flag:
            if is_odd:
                return True
            else:
                return False
        else:
            if not is_odd:
                return True
            else:
                return False


class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        mainLayout=QtGui.QHBoxLayout()
        self.setLayout(mainLayout)   

        self.viewA=QtGui.QTableView()
        self.viewA.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) 

        self.myModel=TableModel()

        self.sortModel = MySortFilterProxyModel()
        self.sortModel.setSourceModel(self.myModel)

        self.viewA.setModel(self.sortModel)

        self.checkBox=QtGui.QCheckBox("Show All")  
        self.checkBox.stateChanged.connect(self.sortModel.cbChanged)
        self.checkBox.setChecked(self.sortModel.cb_status)

        mainLayout.addWidget(self.viewA)
        mainLayout.addWidget(self.checkBox)  
        self.show()   

view=Window() 
sys.exit(app.exec_())

如您所见,我已从 UI 和主要源模型中删除了所有连接.主源模型不关心是否设置了复选框.这使它保持解耦.它更干净.代理模型现在被赋予了这个责任.filterAcceptsRow() 根据复选框状态显示的行的索引是奇数还是偶数来执行显示右行的主要繁重工作.

As you can see, I have removed all connection from UI and the main source model. The main source model does not care about whether the checkbox is set or not. This keeps it decoupled. It's cleaner. The proxy model has been given this responsibility now. The filterAcceptsRow() does the main heavy lifting of displaying the right row based on whether the index of the row shown is odd or even based on the checkbox status.

我在其中添加了一些打印语句,以防万一您想根据数据而不是索引更改逻辑.

I have added a few print statements to it, just in case you want to alter the logic based on the data and not the index.

查看关于 QSortFilterProxyModel 和一些示例在这里.

希望这有用.

这篇关于QTableView由模型驱动时如何刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆