如何将额外的参数传递给PyQt槽?

时间:2015-11-15 09:59:50

标签: python-3.x pyqt pyqt4 pyqt5


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

首先,这是我的代码。

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

  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()'只显示'丰田'。 (也许是最后的项目模型)
  2. 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()'只显示'丰田'。 (也许是最后一个项目模型)与lambda相同的结果。

  3. 问题是......

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

    2. 通过信号传递额外的args是否有效?

    3. 感谢您阅读我的问题。

1 个答案:

答案 0 :(得分:3)

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

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))

它打印“丰田”的原因只是它是carMaker列表中的最后一个元素,因此它是最后创建的QStandardItem,因此item变量引用了这个很反对。

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

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所述的信号映射器。