如何使用 QAbstractTableModel 模型控制其他小部件?
How to control other widgets with an QAbstractTableModel model?
QTableView
由 QAbstractTableModel
控制。它是填充其内容的模型。由于用户双击 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_())
的评论已经是一个很好的起点,但在您的自定义模型中,您还必须在 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_()
注释行是重要的。
QTableView
由 QAbstractTableModel
控制。它是填充其内容的模型。由于用户双击 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_())
然后您还可以定义自己的自定义信号并发射它们并为它们连接。但是,这是您使用 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_()
注释行是重要的。