【问题标题】:PySide \ PyQt: How to return value to UI after button click?PySide \ PyQt:按钮单击后如何将值返回给UI?
【发布时间】:2016-02-11 01:26:30
【问题描述】:

我正在尝试从浏览文件夹对话框返回路径。

我已经尝试将实例对象甚至属性传递给调用并将其设置在那里:

self.browseBtn.clicked.connect(myExporter.browseFolder(self))

self.browseBtn.clicked.connect(myExporter.browseFolder(self.path))

但这不起作用。它会导致浏览器对话框在加载时立即弹出打开,然后一旦您选择了一个文件夹,它就会出错:无法连接信号 clicked()。

我尝试将点击调用设置为返回,但没有成功:

result = self.browseBtn.clicked.connect(myExporter.browseFolder)

当您处理处理 UI 和逻辑的单独类时,有人可以引导我朝着正确的方向返回值吗?另外......像这样分开它们是不好的做法吗?我知道如果我将所有内容都放入一个 python 文件中,我可能很容易解决这个问题,但我认为这是不正确的。

这是我的 ui 文件 (ui.py):

from PySide import QtCore, QtGui

class Ui_Dialog(object):
    def __init__(self):
        self.path =""

    def setupUi(self, Dialog, myExporter):
        Dialog.setObjectName("Dialog")
        Dialog.resize(382, 589)
        ...
        .......
        ............. 
        .................
        self.retranslateUi(Dialog)
        self.tabWidget.setCurrentIndex(1)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

        self.browseBtn.clicked.connect(myExporter.browseFolder)

这是我的导出器文件 (exporter.py):

class Exporter(object):
    def __init__(self):
        ...
        ......

    def browseFolder(self):
        ...
        .......
        do something
        ...........    
        return path

这是我的加载/测试文件 (loadExporter.py):

import ui as interface
import exporter as exporter
from PySide import QtCore, QtGui

app = QtGui.QApplication.instance()
if app is None:
    app = QtGui.QApplication(sys.argv)       
Dialog = QtGui.QDialog()
myExporter = exporter.Exporter()
myUI = interface.Ui_Dialog()
myUI.setupUi(Dialog, myExporter)
Dialog.show()
app.exec_()

【问题讨论】:

    标签: python button pyqt return-value pyside


    【解决方案1】:

    将它们放在单独的文件中不一定是坏事。为某些小部件拥有一个单独的文件是一件好事,尤其是如果这些小部件可以重复使用。

    我希望我的主文件有一个 QMainWindow 类。

    class MyWindow(QtGui.QMainWindow):
        pass
    
    if __name__ == "__main__":
        QtGui.QApplication([])
    
        mywindow = MyWindow()
        mywindow.show()
    
        sys.exit(QtGui.qApp.exec_())
    

    将应用程序功能包装在 if __name__ == "__main__" 中可防止在另一个文件尝试导入此文件时运行此代码。

    信号 (self.browserBtn.clicked) 调用回调方法。在python中一切都是对象。

    def my_func():
        pass
    
    new_func_name = my_func # my_func can be reassigned like any variable
    

    my_func 是一个对象。 self.browseBtn.clicked.connect(my_func) 将 my_func 作为稍后调用的变量传递。

    self.browserBtn.clicked.emit() 发生时(在用户点击时),它与调用连接的函数my_func() 相同。其他信号可能会将值传递给回调函数self.lineEdit.textChanged.connect(my_func)调用'my_func(new_text)'

    您希望您的函数为您调用所有内容。

    def open_file(filename=None):
        """Open a file."""
        # If a filename isn't given ask the user for a file
        if filename is None:
            filename, ext = QtGUi.QFileDialog.getOpenFileName(None, "Open File", ".../My Documents/")
            # You may have to use the ext to make a proper filename
    
        # Open the file
        with open(filename, "r") as file:
            file.read()
    
    self.browserBtn.clicked.connect(open_file)
    

    结构

    ...
    import mywidget
    
    class MyWindow(QtGui.QMainWindow):
        def __init__(self):
            super().__init__()
            ...
            self.show_file = QtGui.QLineEdit()
            self.setCentralWidget(self.show_file)
    
            self.exporter = mywidget.Exporter()
            self.browserBtn.clicked.connect(self.open_file)
    
        def open_file(self, filename=None):
            """Open a file."""
            path = self.exporter.browseFolder()
            # Do something with the path
            self.show_file.setText(path)
    
    if __name__ == "__main__":
        QtGui.QApplication([])
    
        mywindow = MyWindow()
        mywindow.show()
    
        sys.exit(QtGui.qApp.exec_())
    

    【讨论】:

    • 感谢您的输入,但这并不能真正回答我的问题。我知道信号可以调用方法。我试图弄清楚如何传递,更重要的是从信号中返回值。文件对话框只是简单地返回一个文件目录路径以在 GUI 中填写一个值。需要首先接收返回的路径,然后将其设置到 GUI 的某一行中。当然......我仍然想弄清楚如何返回所说的值。
    • 如果有人能解决这里的复杂性,我将 UI 和逻辑分开,以及加载两者的主文件,那就太好了。我可以通过将所有内容放入一个文件中轻松解决此问题,但我正在避免这种情况,因此我遇到了这个问题。
    • 您不能从信号中返回值。连接到信号的方法在 signal.emit() 上调用。发射函数立即返回,在单独的超时中调用连接的函数。没有办法从信号中返回值。让你的函数引用你需要的对象,并在你的函数中执行所有操作。这就是我试图用 open 方法展示的内容。 def open_file(self, filename=None): 然后使用 self 调用您需要的其他方法或使用 self.my_line_edit.setText(filename) 设置 QLineEdit
    • 我现在有点明白了......昨晚甚至在重新审视这个之前做了一些思考,并心想我可以在一个单独的方法调用中完成所有这些,该方法调用在信号中抛出,在那个相同的 UI 文件...而不是从其他模块尝试,如果这有意义的话。谢谢。
    • 我在底部添加了一个结构部分来澄清。
    【解决方案2】:

    我不认为我完全理解您想要实现的目标,但我可以建议以下解决方案。

    exporter.py

    # implementation
    

    dialog.py(主界面)

    import PyQt4.QtGui as qg
    from exporter import Exporter
    
    class Dialog(qg.QDialog):
    
        def __init__(self):
            super().__init__()
            self.path = None
            self.setup_widgets()
    
        def setup_widgets(self):
            self.browse.clicked.connect(self.on_browse_clicked)
    
        def on_browse_clicked(self):
            self.path = Exporter().browse_folder()
    

    ma​​in.py

    import sys
    import PyQt4.QtGui as qg
    from dialog import Dialog
    
    if __name__ == '__main__':
        app = qg.QApplication(sys.argv)
        dialog = Dialog()
        dialog.show()
        sys.exit(app.exec_())
    

    这样你仍然有三个文件,但是 dialog.py 导入 exporter.py 而不是 ma​​in.py 导入这两个文件。

    至于信号的返回值,我不知道;我认为信号是无效的(不返回值)。

    信号通过其形式参数将参数传递给槽。通常槽的参数与信号对应的参数相同或更少。返回值的是槽。

    【讨论】:

    • 谢谢,这也有帮助,而且比上面更清楚(仍然习惯于 PyQt/PySide)。
    猜你喜欢
    • 2016-03-06
    • 2012-08-24
    • 2021-09-13
    • 2016-01-11
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    相关资源
    最近更新 更多