如何将额外的参数传递给 PyQt 插槽? [英] How to pass an extra arguments to PyQt slot?

查看:54
本文介绍了如何将额外的参数传递给 PyQt 插槽?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


大家好.我正在 Windows 7 中使用 python3.4 和 PyQt5 制作简单的模型/视图应用程序.

Hello everyone. I am making simple model/view application using python3.4 and PyQt5 in Windows 7.

首先,这是我的代码.

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

This works fine. But I want to add extra arguments with 'itemChanged' signal. So, I've used lambda and functools

  1. 拉姆达

  • 从'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

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 相同的结果.


问题是...

  1. 我不知道为什么 lambda 和 functools 显示错误的文本.

  1. I don't know why lambda and functools shows wrong text.

有什么有效的方法可以通过信号传递额外的参数吗?

Is any effective way to pass an extra args with signal?

感谢您阅读我的问题.

推荐答案

回答你的第一个问题,functools.partiallambda 函数使用的问题在于事实上,当您将信号连接到插槽时,变量 item 已设置,并且它引用了您在 QStandardItemModel 中添加的最后一个 QStandardItem.所以基本上你处于这种情况:

To answer your first question, the problem with functools.partial and lambda function usage lies in the fact the when you connect the signal to the slot, the variable item is set and it references the last QStandardItem you added in the QStandardItemModel. So basically you are in this situation:

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 变量引用了这个对象.

The reason why it prints "Toyota" is simply the fact that it's the last element in the carMaker list, so it's the last QStandardItem created, hence the item variable references this very object.

要回答第二个问题,您可以使用QStandardItemsetData()方法在项目中存储一些您需要的数据,然后检索它们使用 data().

To answer the second question instead, you can make use of the setData() method of QStandardItem to store some data you need in the item, and then retrieve them using 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_())

或者,您可以使用信号映射器,如这里.

Alternatively you can make use of a signal mapper as described here.

这篇关于如何将额外的参数传递给 PyQt 插槽?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆