如何从模型的方法内部查询主应用程序的小部件

Posted

技术标签:

【中文标题】如何从模型的方法内部查询主应用程序的小部件【英文标题】:How to query the main app's widget from inside of model's method 【发布时间】:2014-12-20 18:13:36 【问题描述】:

下面的代码创建链接到QAbstractTableModelQTableView

当“显示全部”QCheckBox 被选中时,QTableView 应该显示所有七个项目:“一”、“二”、“三”、“四”、“五”、“六”和“七”。 但是当未选中 QTableView 时,应该只显示奇数索引项。 要首先完成它,需要从模型的data() 方法内部查询QCheckBox 的状态。但由于 self.checkBox 是在 Window 类中声明的,因此目前不可能。 问题:如何从模型的方法内部查询self.checkBox的状态?

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.UserRole:
            return item

        if role==QtCore.Qt.DisplayRole:
            return item

        if role==QtCore.Qt.TextColorRole:
            return QtCore.QVariant(QtGui.QColor(QtCore.Qt.white))

        if role == QtCore.Qt.BackgroundRole:
            if index.row()%2:
                return QtCore.QVariant(QtGui.QColor(QtCore.Qt.gray))
            else:
                return QtCore.QVariant(QtGui.QColor(QtCore.Qt.darkGray))

        if role == QtCore.Qt.TextAlignmentRole:
            return (QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)

    def headerData(self, column, orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.TextAlignmentRole:
            return (QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)

        if role == QtCore.Qt.BackgroundRole:
            return QtCore.QVariant(QtGui.QColor(QtCore.Qt.blue)) 

        if role == QtCore.Qt.ForegroundRole:
            if orientation == QtCore.Qt.Horizontal:
                return QtCore.QVariant(QtGui.QColor(QtCore.Qt.red))
            elif orientation == QtCore.Qt.Vertical:
                return QtCore.QVariant(QtGui.QColor(QtCore.Qt.green))

        if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
            return QtCore.QString('Horizont Column')

        if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Vertical:
            return QtCore.QString('Vertical Column')

        if role == QtCore.Qt.FontRole:
            return QtGui.QFont('Times', pointSize=12, weight=-1, italic=True)

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) 

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

        mainLayout.addWidget(self.viewA)
        self.checkBox=QtGui.QCheckBox("Show All")  
        self.checkBox.setChecked(True)
        mainLayout.addWidget(self.checkBox)  
        self.show()    

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

【问题讨论】:

【参考方案1】:

这不是 Qt 相关的问题。是代码设计问题。

您不希望您的模型了解您的视图。想象一下,将来您将复选框替换为其他类型的视图(组合框、单选组等),您将不得不更改模型...

您必须监听复选框中的变化,然后,根据复选框状态,您的控制器应该调用 yourmodel.loadAll() 或 yourmodel.loadOdd()。在您的模型上使用正确的方法,您的“TableView”将自动显示结果。

您应该阅读一些有关 MVC 的内容。

【讨论】:

是否应该将self.checkBox连接到模型函数之一:如:self.checkBox.stateChanged.connect(my_model.cbChanged) 请发布一些关于如何实现loadAll()loadOdd() 模型方法的示例(假设loadAll()loadOdd() 是模型方法而不是Window 的函数)? 我刚刚发布了同一主题的延续。那里的 MVC 代码设计是否正确实现?:***.com/questions/27592088/…

以上是关于如何从模型的方法内部查询主应用程序的小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何在保留在主屏幕上的小部件中打开另一个视图?

如何从 HomeScreen Widget 调用 Activity 中的函数

创建内部带有透明孔的小部件

为啥当主应用停止时我的小部件广播接收器服务停止

使用 qt 设计器创建的主应用程序中不会出现升级的小部件

WidgetKit - API 调用