【问题标题】:PyQt5 passing argument between two classes: lambda vs partialPyQt5 在两个类之间传递参数:lambda vs partial
【发布时间】:2019-03-20 08:00:09
【问题描述】:

我试图在两个 PyQt5 类之间传递一个参数。我用了三种方法:

  1. 使用 lambda 函数。
  2. 包装函数(类似于 lambda 函数)。
  3. partial 来自 functools 模块。

在下面的示例中,我有两个窗口:

  • MainWindow 具有 QLineEdit mw_line_edit 和 QPushButton mw_open_new_dialog_button
  • 对话框:有一个 QLineEdit line_edit 和一个QPushButton push_button

当我点击按钮push_button时,我希望它把line_edit的内容插入mw_line_edit

这是一个最小的例子:

import sys
from functools import partial

from PyQt5 import QtWidgets, QtGui, QtCore


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.central_widget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.central_widget)
        self.mw_open_new_dialog_button = QtWidgets.QPushButton('Open New dialog', self)
        self.mw_line_edit = QtWidgets.QLineEdit(self)
        self.hlayout = QtWidgets.QHBoxLayout(self)
        self.hlayout.addWidget(self.mw_open_new_dialog_button)
        self.hlayout.addWidget(self.mw_line_edit)
        self.central_widget.setLayout(self.hlayout)

        self.mw_open_new_dialog_button.clicked.connect(self.open_new_dialog)


    def open_new_dialog(self):
        self.dlg = Dialog()
        #self.dlg.clicked.connect(partial(self.write_something, self.dlg.line_edit.text())) # <<<<<<< This does not work
        self.dlg.clicked.connect(lambda: self.write_something(self.dlg.line_edit.text())) # this works
        #self.dlg.clicked.connect(self.wrapper(self.dlg.line_edit.text()))# <<<<<<<<<<This does not work 
        self.dlg.exec()

    @QtCore.pyqtSlot()
    def write_something(self, text):
        self.mw_line_edit.setText(text)

    def wrapper(self, text):
        return lambda: self.write_something(text)



class Dialog(QtWidgets.QDialog):

    clicked = QtCore.pyqtSignal()
    def __init__(self, parent=None):
        super(QtWidgets.QDialog, self).__init__(parent)
        self.hlayout = QtWidgets.QHBoxLayout(self)
        self.line_edit = QtWidgets.QLineEdit(self)
        self.push_button = QtWidgets.QPushButton('Click me', self)
        self.hlayout.addWidget(self.line_edit)
        self.hlayout.addWidget(self.push_button)
        self.label = QtWidgets.QLabel('I am a Qlabel', self)
        self.hlayout.addWidget(self.label)
        self.setLayout(self.hlayout)
        self.push_button.clicked.connect(self.clicked)

    def write_something(self, text):
        print(text)



app = QtWidgets.QApplication(sys.argv)

main_window = MainWindow()
main_window.show()
sys.exit(app.exec())

正如您在注释行中看到的,只有以下方法有效:

self.dlg.clicked.connect(lambda: self.write_something(self.dlg.line_edit.text()))

为什么其他两个不起作用,即:

self.dlg.clicked.connect(partial(self.write_something, self.dlg.line_edit.text())) # &lt;&lt;&lt;&lt;&lt;&lt;&lt; This does not work

self.dlg.clicked.connect(self.wrapper(self.dlg.line_edit.text()))# &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;This does not work

谢谢

【问题讨论】:

  • 你的问题是什么?
  • @eyllanesc:我问了一个问题:为什么 partial 和 wrapper 不起作用
  • @eyllanesc:如果我试图将额外的参数传递给同一个类中的插槽,partialwrapper 都可以工作,但在我的情况下,有两个类为什么它们不起作用?

标签: python python-3.x pyqt5


【解决方案1】:

1) functools.partial()

您向 partial 传递了哪些参数? 在建立连接时,您正在传递 write_something 方法和 self.dlg.line_edit 的文本。

该文本的值是什么?它是一个空字符串,这说明了失败。

这种情况有什么解决办法吗?是的,不是传递文本,而是传递QLineEdit,在write_something方法中获取文本并设置在另一个QLineEdit中:

def open_new_dialog(self):
    self.dlg = Dialog()
    self.dlg.clicked.connect(partial(self.write_something, self.dlg.line_edit))
    self.dlg.exec()

def write_something(self, le):
    self.mw_line_edit.setText(le.text())

2) 包装器

同样的问题,你传递的是连接时的空文本

有什么解决办法吗?是的,和上一个解决办法一样。

def open_new_dialog(self):
    self.dlg = Dialog()
    self.dlg.clicked.connect(self.wrapper(self.dlg.line_edit))
    self.dlg.exec()

def write_something(self, text):
    self.mw_line_edit.setText(text)

def wrapper(self, line):
    return lambda: self.write_something(line.text())

会有干净的解决方案吗?是的,创建一个在您点击时传输文本的信号。

from PyQt5 import QtWidgets, QtGui, QtCore

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        self.mw_open_new_dialog_button = QtWidgets.QPushButton('Open New dialog')
        self.mw_line_edit = QtWidgets.QLineEdit()
        hlayout = QtWidgets.QHBoxLayout(central_widget)
        hlayout.addWidget(self.mw_open_new_dialog_button)
        hlayout.addWidget(self.mw_line_edit)
        self.mw_open_new_dialog_button.clicked.connect(self.open_new_dialog)

    @QtCore.pyqtSlot()
    def open_new_dialog(self):
        self.dlg = Dialog()
        self.dlg.textSignal.connect(self.mw_line_edit.setText)
        self.dlg.exec()

class Dialog(QtWidgets.QDialog):
    textSignal = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(QtWidgets.QDialog, self).__init__(parent)
        hlayout = QtWidgets.QHBoxLayout(self)
        self.line_edit = QtWidgets.QLineEdit()
        self.push_button = QtWidgets.QPushButton('Click me')
        hlayout.addWidget(self.line_edit)
        hlayout.addWidget(self.push_button)
        self.label = QtWidgets.QLabel('I am a Qlabel')
        hlayout.addWidget(self.label)
        self.push_button.clicked.connect(self.sendText)

    @QtCore.pyqtSlot()
    def sendText(self):
        self.textSignal.emit(self.line_edit.text())

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec())

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多