【问题标题】:How to control other widgets with an QAbstractTableModel model?如何使用 QAbstractTableModel 模型控制其他小部件?
【发布时间】:2015-03-21 11:37:57
【问题描述】:

QTableViewQAbstractTableModel 控制。它是填充其内容的模型。由于用户双击QTableView 的其中一项,然后输入新值,该模型会修改self.items 变量。

我的对话框底部的按钮最初是禁用的。我希望在用户输入新值后立即启用此按钮(通过双击 QTableView 的任何一项并键入字符串或数字)。

基本上我希望模型控制按钮的状态。我怎样才能实现它?

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, os

class Model(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items =[ 
                    ['Row0_Column0','Row0_Column1','Row0_Column2'],
                    ['Row1_Column0','Row1_Column1','Row1_Column2'],
                    ['Row2_Column0','Row2_Column1','Row2_Column2']
                    ]

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 3

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        row=index.row()
        column=index.column()

        if row>len(self.items): return QVariant()        
        if column>len(self.items[row]): return QVariant()

        if role == Qt.EditRole:
            return QVariant(self.items[row][column])

        if role == Qt.DisplayRole:            
            return QVariant(self.items[row][column])

        return QVariant()

    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid():            
            if role == Qt.EditRole:
                row = index.row()
                column=index.column()
                if row>len(self.items) or column>len(self.items[row]):
                    return False
                else:
                    self.items[row][column]=value  
                    return True
        return False

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)
        tablemodel=Model(self)               
        tableview=QTableView(self) 
        tableview.setModel(tablemodel)    
        layout=QVBoxLayout(self)
        layout.addWidget(tableview)
        self.button=QPushButton('Push Me')
        self.button.setDisabled(True)
        layout.addWidget(self.button)
        self.setLayout(layout)      

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

【问题讨论】:

  • 我不喜欢 Python 但我可以给你一个提示。您可以使用void QAbstractItemModel::​dataChanged(...) 信号来了解用户何时通过双击单元格输入新值。将此信号连接到一个插槽,在该插槽中以字符串格式获取新单元格内容,并使用此新字符串实现按钮。
  • 谢谢!我会试试看的!

标签: python qt model pyqt qtableview


【解决方案1】:

Martin 的评论已经是一个很好的起点,但在您的自定义模型中,您还必须在 setData 方法中发出 dataChanged 信号才能使其工作。

然后您还可以定义自己的自定义信号并发出它们并为它们连接。但是,这是您使用 QAbstractItemModel 的 dataChanged 信号的示例:

from PySide import QtGui, QtCore

class Model(QtCore.QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QtCore.QAbstractTableModel.__init__(self, parent, *args)
        self.items =[ 
                    ['Row0_Column0','Row0_Column1','Row0_Column2'],
                    ['Row1_Column0','Row1_Column1','Row1_Column2'],
                    ['Row2_Column0','Row2_Column1','Row2_Column2']
                    ]

    def flags(self, index):
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable

    def rowCount(self, parent):
        return len(self.items)

    def columnCount(self, parent):
        return 3

    def data(self, index, role):
        if not index.isValid():
            return None

        row=index.row()
        column=index.column()

        if row > len(self.items):
            return None
        if column > len(self.items[row]):
            return None

        if role == QtCore.Qt.EditRole:
            return self.items[row][column]

        if role == QtCore.Qt.DisplayRole:
            return self.items[row][column]

        return None

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if index.isValid():            
            if role == QtCore.Qt.EditRole:

                row = index.row()
                column = index.column()

                if row > len(self.items) or column > len(self.items[row]):
                    return False
                else:
                    self.items[row][column] = value
                    self.dataChanged.emit(index, index) # emit the signal
                    return True
        return False

class MyWindow(QtGui.QWidget):
    def __init__(self, *args):
        QtGui.QWidget.__init__(self, *args)

        tablemodel = Model(self)
        tablemodel.dataChanged.connect(self.data_changed) # connect dataChanged signal
        tableview = QtGui.QTableView(self)
        tableview.setModel(tablemodel)

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(tableview)

        self.button = QtGui.QPushButton('Push Me')
        self.button.setDisabled(True) # initially disabled

        layout.addWidget(self.button)
        self.setLayout(layout)

    def data_changed(self, topleft_index, bottom_right_index):
        # just enable the button
        self.button.setEnabled(True)

app = QtGui.QApplication([])
w = MyWindow()
w.show()
app.exec_()

注释的行是重要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多