如何将额外的参数传递给 PyQt 插槽?
How to pass an extra arguments to PyQt slot?
大家好。我正在使用 python3.4 和 Windows 7.
中的 PyQt5 制作简单的 model/view 应用程序
首先,这是我的代码。
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QListView
from PyQt5.Qt import QStandardItemModel, QStandardItem
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.list = QListView(self)
model = QStandardItemModel(self.list)
carMaker = ['Ford', 'GM', 'Renault', 'VW', 'Toyota']
for maker in carMaker:
item = QStandardItem(maker)
item.setCheckable(True)
model.appendRow(item)
self.list.setModel(model)
model.itemChanged.connect(self.on_item_changed)
#model.itemChanged.connect(functools.partial(self.on_item_changed, item, 1))
#model.itemChanged.connect(lambda: self.on_item_changed(item, 2))
self.list.setMinimumSize(300, 300)
self.setWindowTitle("Simple modelView")
self.show()
def on_item_changed(self, item):
print(item.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
这很好用。但我想用 'itemChanged' 信号添加额外的参数。所以,我使用了 lambda 和 functools
λ
- 从 'def on_item_changed(self, item)' 更改为 'def on_item_changed(self, item, num)'
- 从 'model.itemChanged.connect(self.on_item_changed)' 更改为 'model.itemChanged.connect(lambda: self.on_item_changed(item, 1))'
- 没有错误。但是 'item.text()' 只显示 'Toyota'。 (也许是最后一个项目模型)
functools.partial
- 从 'def on_item_changed(self, item)' 更改为 'def on_item_changed(self, item, num)'
- 从 'model.itemChanged.connect(self.on_item_changed)' 更改为 'model.itemChanged.connect(functools.partial(self.on_item_changed, item, 1))'
- 没有错误。但是 'item.text()' 只显示 'Toyota'。 (可能是最后一项模型)与 lambda 相同的结果。
问题是...
我不知道为什么 lambda 和 functools 显示错误的文本。
有什么有效的方法可以通过信号传递额外的参数吗?
感谢您阅读我的问题。
回答你的第一个问题,functools.partial
和 lambda
函数使用的问题在于当你将信号连接到插槽时,变量 item
被设置它引用了您在 QStandardItemModel
中添加的最后一个 QStandardItem
。所以基本上你处于这种情况:
def initUI(self):
self.list = QListView(self)
model = QStandardItemModel(self.list)
carMaker = ['Ford', 'GM', 'Renault', 'VW', 'Toyota']
for maker in carMaker:
item = QStandardItem(maker) # here you create a item variable that is overwritten
item.setCheckable(True) # on every iteration of the for loop
model.appendRow(item)
self.list.setModel(model)
# here you use again the item variable (the same applies for lambda)
model.itemChanged.connect(functools.partial(self.on_item_changed, item, 1))
它打印 "Toyota" 的原因仅仅是因为它是 carMaker
列表中的最后一个元素,所以它是最后创建的 QStandardItem
,因此 item
变量引用了这个对象。
要回答第二个问题,您可以使用 QStandardItem
的 setData()
方法在项目中存储您需要的一些数据,然后使用 data()
检索它们.
import sys
from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtWidgets import QApplication, QWidget, QListView
from PyQt5.QtGui import QStandardItemModel, QStandardItem
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.list = QListView(self)
model = QStandardItemModel(self.list)
carMaker = ['Ford', 'GM', 'Renault', 'VW', 'Toyota']
index = 0 # just to store something different for each QStandardItem
for maker in carMaker:
item = QStandardItem(maker)
item.setCheckable(True)
item.setData(index, Qt.UserRole + 1)
model.appendRow(item)
index += 1
self.list.setModel(model)
model.itemChanged.connect(self.on_item_changed)
self.list.setMinimumSize(300, 300)
self.setWindowTitle("Simple modelView")
self.show()
@pyqtSlot('QStandardItem')
def on_item_changed(self, item):
print("%s - %s" % (item.text(), item.data(Qt.UserRole + 1)))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
或者,您可以使用信号映射器,如 here 所述。
大家好。我正在使用 python3.4 和 Windows 7.
中的 PyQt5 制作简单的 model/view 应用程序首先,这是我的代码。
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QListView
from PyQt5.Qt import QStandardItemModel, QStandardItem
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.list = QListView(self)
model = QStandardItemModel(self.list)
carMaker = ['Ford', 'GM', 'Renault', 'VW', 'Toyota']
for maker in carMaker:
item = QStandardItem(maker)
item.setCheckable(True)
model.appendRow(item)
self.list.setModel(model)
model.itemChanged.connect(self.on_item_changed)
#model.itemChanged.connect(functools.partial(self.on_item_changed, item, 1))
#model.itemChanged.connect(lambda: self.on_item_changed(item, 2))
self.list.setMinimumSize(300, 300)
self.setWindowTitle("Simple modelView")
self.show()
def on_item_changed(self, item):
print(item.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
这很好用。但我想用 'itemChanged' 信号添加额外的参数。所以,我使用了 lambda 和 functools
λ
- 从 'def on_item_changed(self, item)' 更改为 'def on_item_changed(self, item, num)'
- 从 'model.itemChanged.connect(self.on_item_changed)' 更改为 'model.itemChanged.connect(lambda: self.on_item_changed(item, 1))'
- 没有错误。但是 'item.text()' 只显示 'Toyota'。 (也许是最后一个项目模型)
functools.partial
- 从 'def on_item_changed(self, item)' 更改为 'def on_item_changed(self, item, num)'
- 从 'model.itemChanged.connect(self.on_item_changed)' 更改为 'model.itemChanged.connect(functools.partial(self.on_item_changed, item, 1))'
- 没有错误。但是 'item.text()' 只显示 'Toyota'。 (可能是最后一项模型)与 lambda 相同的结果。
问题是...
我不知道为什么 lambda 和 functools 显示错误的文本。
有什么有效的方法可以通过信号传递额外的参数吗?
感谢您阅读我的问题。
回答你的第一个问题,functools.partial
和 lambda
函数使用的问题在于当你将信号连接到插槽时,变量 item
被设置它引用了您在 QStandardItemModel
中添加的最后一个 QStandardItem
。所以基本上你处于这种情况:
def initUI(self):
self.list = QListView(self)
model = QStandardItemModel(self.list)
carMaker = ['Ford', 'GM', 'Renault', 'VW', 'Toyota']
for maker in carMaker:
item = QStandardItem(maker) # here you create a item variable that is overwritten
item.setCheckable(True) # on every iteration of the for loop
model.appendRow(item)
self.list.setModel(model)
# here you use again the item variable (the same applies for lambda)
model.itemChanged.connect(functools.partial(self.on_item_changed, item, 1))
它打印 "Toyota" 的原因仅仅是因为它是 carMaker
列表中的最后一个元素,所以它是最后创建的 QStandardItem
,因此 item
变量引用了这个对象。
要回答第二个问题,您可以使用 QStandardItem
的 setData()
方法在项目中存储您需要的一些数据,然后使用 data()
检索它们.
import sys
from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtWidgets import QApplication, QWidget, QListView
from PyQt5.QtGui import QStandardItemModel, QStandardItem
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.list = QListView(self)
model = QStandardItemModel(self.list)
carMaker = ['Ford', 'GM', 'Renault', 'VW', 'Toyota']
index = 0 # just to store something different for each QStandardItem
for maker in carMaker:
item = QStandardItem(maker)
item.setCheckable(True)
item.setData(index, Qt.UserRole + 1)
model.appendRow(item)
index += 1
self.list.setModel(model)
model.itemChanged.connect(self.on_item_changed)
self.list.setMinimumSize(300, 300)
self.setWindowTitle("Simple modelView")
self.show()
@pyqtSlot('QStandardItem')
def on_item_changed(self, item):
print("%s - %s" % (item.text(), item.data(Qt.UserRole + 1)))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
或者,您可以使用信号映射器,如 here 所述。