【问题标题】:Calling python script from python script, giving input and getting output, PyQt5, GUI从 python 脚本调用 python 脚本,提供输入和获取输出,PyQt5,GUI
【发布时间】:2017-12-27 15:04:25
【问题描述】:

我是编程新手,2个月前开始学习python,所以请简单解释一下。对于我的学士论文,我编写了 2 个独立的 Python 脚本,它们从用户那里获取输入、进行计算并给出输出。我没有使用任何 OOP,但两个脚本中都有很多功能。 现在我必须让脚本通过 GUI 运行(在 GUI 中获取用户输入和打印输出)。我使用 PyQt5 和 Qt 设计器。 我在其他线程上读到这里有人建议在每个脚本中创建一个类,以便从主脚本中调用并将整个内容放在类中。我这样做了,并且以某种方式设法从 GUI 获取输入,并将该输入提供给其中一个计算脚本。我的问题是我不知道如何将计算脚本的输出返回到主脚本。如果我设法这样做,使用 setText 在 GUI 中打印结果应该很容易。 我的主脚本如下所示:

    import sys
from PyQt5 import QtWidgets, QtCore, uic
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from iad import IAD  # here import the file iad.py with class IAD
class MeinDialog (QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = uic.loadUi("kobi.ui", self)
        fck = 25
        self.input_fck.currentIndexChanged.connect(self.fck_change)

        self.show()


    def fck_change(self):
        fck_i = (self.input_fck.currentIndex())
        if fck_i == 0:
            fck = 12
        elif fck_i == 1:
            fck = 16
        elif fck_i == 2:
            fck = 20
        elif fck_i == 3:
            fck = 25
        elif fck_i == 4:
            fck = 30
        elif fck_i == 5:
            fck = 35
        elif fck_i == 6:
            fck = 40
        elif fck_i == 7:
            fck = 45
        elif fck_i == 8:
            fck = 50
        IAD(fck)

        as1 = str(IAD.as1_output())      # ???  this does not work
        self.output_as1.setText(as1)     # ???  

app = QtWidgets.QApplication(sys.argv)
dialog = MeinDialog()
dialog.show()
sys.exit(app.exec_())

iad.py 文件如下所示:

class IAD():
    def __init__(self, fck):
        #get inputs from user
        #make some calculations
        #output:
        as1 = f_as1(epsc2_Found, epss1_Found)  #f_as1 is a function

函数 as1 如下所示:

def f_as1(epsc2_var, epss1_var):
    if ned < 0 and med == 0:
        return (ned + b*h*fcd/10) / (sigma_sd(epss1_var) / 10 + sigma_sd(epss1_var / varas) / (10)) #+ fcd/10*(1+1/varas))
    elif ned > 0 and med == 0:
        return (alphar_var(epsc2_var) * b * (abs(epsc2_var) * d / (epss1_var + abs(epsc2_var))) * fcd / 10 + ned) / (
                sigma_sd(epss1_var) / 10 + sigma_sd(epss1_var) / (10 * varas) )
    elif bereich5 == True:
        return (alphar_var_5(epsc2_var) * b * h * fcd / 10 + ned) / (
                sigma_sd(epss1_bereich_5(epsc2_var)) / 10 + sigma_sd(epss2_bereich_5(epsc2_var)) / (10 * varas))
    else:
        return (alphar_var(epsc2_var)*b*(-epsc2_var*d/(epss1_var-epsc2_var))*fcd/10*(h_m/2-ka_var(epsc2_var)*(-epsc2_var*d_m/(epss1_var-epsc2_var)))-med)/(-sigma_sd(epss1_var) * zs1 / 1000 + sigma_sd((epss1_var - epsc2_var) * d2 / d + epsc2_var) * zs2 / (varas * 1000))

如有任何提示、建议和意见,我将不胜感激。

【问题讨论】:

    标签: python user-interface pyqt5


    【解决方案1】:

    我相信您发布的内容应该起作用:

        as1 = str(IAD.as1_output())      # ???  this does not work
        self.output_as1.setText(as1)     # ???  
    

    我不确定您所说的“这不起作用”究竟是什么意思,但是为了解决问题,您可以尝试按如下方式更改代码:

         import QTimer
         from functools import partial as bind
         ...
         self.output_as1.setText("Calling as1_output()...")
         QTimer.singleShot(
             10000,
             bind(self.output_as1.setText, str(IAD.as1_output()
         )
    

    我猜你会看到:

    1. 输出文本为Calling as1_output()...,然后:
    2. 十秒后,它要么:
      1. 更改为空字符串,或:
      2. 保持完全相同(即Calling as1_output()...

    如果情况确实如此,下一步就是找出str(IAD.as1_output()) 没有按预期工作的原因。不幸的是,我们还没有足够的细节来帮助解决这个问题,但是...这是一个完整的小程序,您可以运行它来确信您的基本方法是正确的:

    #!/usr/bin/env python
    
    from PyQt5 import QtCore, QtWidgets
    
    class IAD():
        def as1_output():
            return 42
    
    if __name__ == '__main__':
        import sys
        from functools import partial as bind
        app = QtWidgets.QApplication(sys.argv)
        mw = QtWidgets.QMainWindow()
        label = QtWidgets.QLabel(mw)
        mw.show()
        label.setText("The answer is...")
        QtCore.QTimer.singleShot(
            5000,
            bind(label.setText, str(IAD.as1_output()))
        )
        sys.exit(app.exec_())
    

    【讨论】:

      【解决方案2】:

      好的,我找到了解决问题的方法。我没有从我的脚本中创建类,而是简单地创建了一个函数,然后将所有相关输出作为列表返回。这种方式更简单,而且效果很好!

      【讨论】:

        【解决方案3】:

        要使用 tkinter,你可以这样做, 创建空白窗口作为变量:

        window = Tk()
        

        创建具有 tkinter 类型值的变量,例如。按钮、条目、标签:

        label1 = Label(window, text="random label text")
        

        然后像这样添加到窗口中:

        label1.grid(row=0, column=0)
        

        将行和列更改为位置 使窗口运行: window.mainloop() 并且您可以更改类型等来自定义窗口,例如这是一个运行龟(python 内置图形)来制作形状的 GUI:

        ` 来自 tkinter 导入 * 进口乌龟

        def graphics():
            roots.destroy()
            pen = turtle.Turtle()
            for i in range(5): 
               pen.forward(100)
               pen.left(72)
            pen.clear()
            window()
        
        def window():
            global roots
        
            roots = Tk()
            roots.title('Graphics Demostration')
            l1 = Label(roots, text='Graphics Demostration:\nclick the button to 
            begin')
            b1 = Button(roots, text="Begin", command=graphics)
            b1.grid()
            l1.grid()
        
            roots.mainloop()
        window()`
        

        【讨论】:

        • 我不明白你,解释一下,如果你检查你使用的标签和你清楚地看到你想要用 PyQt 回复并且你正在使用 tkinter 的问题的内容,它们是 2 个不同的库具有不同的行为。
        • 我知道它们是两个不同的模块,这就是我试图对他说的一点,他可以比 Pyqt 更轻松地使用 tkinter 来做他正在做的事情,因为 tkinter 实际上更适合脚本中的计算
        • 您的观点不正确,我曾与这两个库一起工作,并且都为相同的库服务,虽然 PyQt 更专业(这是我的观点),但它们在设计和方式上有很多差异处理 OOP。