PyQt5在两个类之间传递参数:lambda vs部分

时间:2019-03-20 08:00:10

标签: python python-3.x pyqt5

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

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

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

  • MainWindow具有QLineEdit mw_line_edit和QPushButton mw_open_new_dialog_button
  • 对话框:具有QLineEdit line_edit和aQPushButton 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())) # <<<<<<< This does not work

self.dlg.clicked.connect(self.wrapper(self.dlg.line_edit.text()))# <<<<<<<<<<This does not work

谢谢

1 个答案:

答案 0 :(得分:2)

1)functools.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())