Qt 中的按钮 Model/View Table
PushButton in Qt Model/View Table
我正在 PyQt5 中编写自定义 Table模型,继承自 QtCore.QAbstractTableModel
。我希望我的 Table 有一列只有 CheckBoxes,没有文本,一列每一行都有一个 PushButton。
我试图在 data
方法中为 Qt.Display
角色 return 一个 QPushButton
对象,但显然这是不可能的。
所以我的问题是:我可以在模型本身中实现它 return 某些单元格的某些小部件吗?在我看来,这是模型的工作,但我该如何实现呢?
我的第二个问题是我必须如何分配插槽,以便我知道操作是从哪个按钮(从哪一行)发生的?
解释:
我可以在模型本身中实现它 returns 某些单元格的某些小部件吗?在我看来,这是模型的工作,但我该如何实现呢?
可能是模型提供了小部件,但并不常见。一般而言,模型提供将要通过委托显示的信息,是可以提供小部件的委托。还可以使用 setIndexWidget 方法在模型的未链接视图上设置小部件。
考虑到第一种情况,解决方案是实现一个委托。
我必须如何分配插槽,以便我知道操作是从哪个按钮(从哪一行)发生的?
通常用作编辑器的小部件,因此您必须更新模型,然后模型可以通过 dataChanged 信号通知其他元素,例如,如果用户写入文本或更改复选框的状态,但在点击的情况下,不会通知永久更改而是临时更改。考虑到这一点,代表可以提出一个信号。
解决方案:
from PyQt5 import QtCore, QtGui, QtWidgets
class PushButtonDelegate(QtWidgets.QStyledItemDelegate):
clicked = QtCore.pyqtSignal(QtCore.QModelIndex)
def paint(self, painter, option, index):
if (
isinstance(self.parent(), QtWidgets.QAbstractItemView)
and self.parent().model() is index.model()
):
self.parent().openPersistentEditor(index)
def createEditor(self, parent, option, index):
button = QtWidgets.QPushButton(parent)
button.clicked.connect(lambda *args, ix=index: self.clicked.emit(ix))
return button
def setEditorData(self, editor, index):
editor.setText(index.data(QtCore.Qt.DisplayRole))
def setModelData(self, editor, model, index):
pass
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QTableView()
model = QtGui.QStandardItemModel(0, 2)
for i in range(10):
it1 = QtGui.QStandardItem()
it1.setData(QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
it1.setFlags(it1.flags() | QtCore.Qt.ItemIsUserCheckable)
it2 = QtGui.QStandardItem()
it2.setData("text-{}".format(i), QtCore.Qt.DisplayRole)
model.appendRow([it1, it2])
# pass the view as parent
delegate = PushButtonDelegate(w)
w.setItemDelegateForColumn(1, delegate)
def on_clicked(index):
print(index.data())
delegate.clicked.connect(on_clicked)
w.setModel(model)
w.show()
sys.exit(app.exec_())
我正在 PyQt5 中编写自定义 Table模型,继承自 QtCore.QAbstractTableModel
。我希望我的 Table 有一列只有 CheckBoxes,没有文本,一列每一行都有一个 PushButton。
我试图在 data
方法中为 Qt.Display
角色 return 一个 QPushButton
对象,但显然这是不可能的。
所以我的问题是:我可以在模型本身中实现它 return 某些单元格的某些小部件吗?在我看来,这是模型的工作,但我该如何实现呢?
我的第二个问题是我必须如何分配插槽,以便我知道操作是从哪个按钮(从哪一行)发生的?
解释:
我可以在模型本身中实现它 returns 某些单元格的某些小部件吗?在我看来,这是模型的工作,但我该如何实现呢?
可能是模型提供了小部件,但并不常见。一般而言,模型提供将要通过委托显示的信息,是可以提供小部件的委托。还可以使用 setIndexWidget 方法在模型的未链接视图上设置小部件。
考虑到第一种情况,解决方案是实现一个委托。
我必须如何分配插槽,以便我知道操作是从哪个按钮(从哪一行)发生的?
通常用作编辑器的小部件,因此您必须更新模型,然后模型可以通过 dataChanged 信号通知其他元素,例如,如果用户写入文本或更改复选框的状态,但在点击的情况下,不会通知永久更改而是临时更改。考虑到这一点,代表可以提出一个信号。
解决方案:
from PyQt5 import QtCore, QtGui, QtWidgets
class PushButtonDelegate(QtWidgets.QStyledItemDelegate):
clicked = QtCore.pyqtSignal(QtCore.QModelIndex)
def paint(self, painter, option, index):
if (
isinstance(self.parent(), QtWidgets.QAbstractItemView)
and self.parent().model() is index.model()
):
self.parent().openPersistentEditor(index)
def createEditor(self, parent, option, index):
button = QtWidgets.QPushButton(parent)
button.clicked.connect(lambda *args, ix=index: self.clicked.emit(ix))
return button
def setEditorData(self, editor, index):
editor.setText(index.data(QtCore.Qt.DisplayRole))
def setModelData(self, editor, model, index):
pass
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QTableView()
model = QtGui.QStandardItemModel(0, 2)
for i in range(10):
it1 = QtGui.QStandardItem()
it1.setData(QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
it1.setFlags(it1.flags() | QtCore.Qt.ItemIsUserCheckable)
it2 = QtGui.QStandardItem()
it2.setData("text-{}".format(i), QtCore.Qt.DisplayRole)
model.appendRow([it1, it2])
# pass the view as parent
delegate = PushButtonDelegate(w)
w.setItemDelegateForColumn(1, delegate)
def on_clicked(index):
print(index.data())
delegate.clicked.connect(on_clicked)
w.setModel(model)
w.show()
sys.exit(app.exec_())