通过 connect 传递额外的参数

问题描述 投票:0回答:2

是否可以通过槽传递变量,以便我可以打印出某些文本? 尝试将另一个函数中定义的变量“DiffP”传递给插槽。

“DiffP”根据选择的文件而变化。

def addLineEdit(self):
    try:
        self.clearLayout()
        self.FileButton ={}
        self.Input = {}
        self.TotalInput = []
        for i in range(int(self.numberLine.text())):
            self.FileButton[i] = QtWidgets.QPushButton(self.centralwidget)
            self.FileButton[i].setText('Case {}'.format(i+1))
            self.FileButton[i].setFlat(True)
            self.FileButton[i].setMaximumSize(QtCore.QSize(50, 50))
            self.hboxlayout[0].addWidget(self.FileButton[i])
            self.FileButton[i].clicked.connect(lambda i=i: self.openfile(i))
            self.buttonGroup.addButton(self.FileButton[i],i)
            self.buttonGroup.buttonClicked['int'].connect(self.input)

def searchfile(self,dir):
        with open(dir) as f:
            content = f.readlines()
            MainList = content[44].split()
            RPM = round(float(MainList[0]), 2)
            Ps = round(float(MainList[1]), 2)
            Ts = round(float(MainList[2]), 2)
            Pd = round(float(MainList[3]), 2)
            Ratio = round(Pd / Ps, 2)
            DiffP = round(Pd - Ps, 2)
@pyqtSlot(int)
def input(self,button_or_id,DiffP):
    if isinstance(button_or_id, int):
        if button_or_id == 0:
            self.TotalInput[0].setText(str(DiffP))
        elif button_or_id == 1:
            self.TotalInput[54].setText('1')

def openfile(self,i):
    filename = QtWidgets.QFileDialog.getOpenFileName(self, 'Choose file')
    dir = filename[0]
    directory = os.path.split(dir)[0]
    return self.searchfile(dir)
python python-3.x pyqt pyqt5 qt-signals
2个回答
23
投票

问题可以通过两种方式解决:

使用 lambda 函数:

总体来说:

    obj.signal.connect(lambda param1, param2, ..., arg1=val1, arg2= value2, ... : fun(param1, param2,... , arg1, arg2, ....))

def fun(param1, param2,... , arg1, arg2, ....):
    [...]

地点:

  • param1, param2, ...:是信号发送的参数
  • arg1, arg2, ...:是您想要使用的额外参数

您的情况:

    self.buttonGroup.buttonClicked['int'].connect(lambda i: self.input(i, "text"))

@pyqtSlot(int)
def input(self, button_or_id, DiffP):
    if isinstance(button_or_id, int):
        if button_or_id == 0:
            self.TotalInput[0].setText(DiffP)
        elif button_or_id == 1:
            self.TotalInput[54].setText('1')

使用
functools.partial

总体来说:

    obj.signal.connect(partial(fun, args1, arg2, ... ))

def fun(arg1, arg2, ..., param1, param2, ...):
    [...]

地点:

  • param1, param2, ...:是信号发送的参数
  • arg1, arg2, ...:是您要发送的额外参数

您的情况:

from functools import partial

    [...]
    self.buttonGroup.buttonClicked['int'].connect(partial(self.input, "text"))


@pyqtSlot(int)
def input(self, DiffP, button_or_id):
    if isinstance(button_or_id, int):
        if button_or_id == 0:
            self.TotalInput[0].setText(DiffP)
        elif button_or_id == 1:
            self.TotalInput[54].setText('1')

0
投票

其他答案中建议的方法有问题,

self.whatever.connect(lambda x: self.method(..., x))        # approach 1 (suboptimal)
self.whatever.connect(functools.partial(self.method, ...))  # approach 2 (suboptimal)

它们创建了一个引用循环:

self
对象持有对(或者是)带有信号的对象的引用,该对象持有对函数或
partial
对象的引用,该对象持有对
self的引用
对象。结果是(在 CPython 中)当所有其他对这些对象的引用消失时,这些对象都不会被垃圾回收;它们只会在下次循环收集器运行时被收集。反过来,他们将保留他们引用的所有其他 Python 数据结构以及他们共同拥有的任何 Qt 对象。这并不完全是内存泄漏,因为所有内容最终都会被释放,但这可能是一个问题。

这样写就没有引用循环

self.whatever.connect(self.method)

因为在 PyQt 和 PySide 中,

connect
对于 Python 绑定方法对象有一个特殊情况:它仅保存对“self”对象的弱引用。
functools.partial
不返回
connect
识别的特定类型的对象。但是您可以定义
functools.partial
的替代品来返回该类型,这样您就可以获得避免循环的行为:

def partial_bound_method(bound_method, *args, **kwargs):
    f = functools.partialmethod(bound_method.__func__, *args, **kwargs)
    # NB: the seemingly redundant lambda is needed to ensure the correct result type
    return (lambda *args: f(*args)).__get__(bound_method.__self__)

...

self.whatever.connect(partial_bound_method(self.method, ...))  # approach 2' (better)

请参阅这个较长的答案了解更多详细信息。

© www.soinside.com 2019 - 2024. All rights reserved.