通过GUI在模拟过程中读取用户的输入

时间:2014-07-23 21:13:11

标签: python user-interface pyqt pyqt5 simpy

我正在使用simpy将基于仿真的应用程序转换为GUI。

程序当前在控制台中运行,并且正在进行模拟的simpy默认以循环方式运行。那就是我的问题所在。

目前,在代码的控制台版本中,我通过raw_input()函数获取用户输入,并且能够中断代码并允许用户输入模拟所需的值。然而,尽管进行了研究,但似乎并没有采用类似且干净的方式来实现这一目标。通过pyqt inisde构建GUI。

唯一的方法是在不同的线程中运行进程吗?如果我采用这种方法,那看起来究竟如何并真正起作用?

1 个答案:

答案 0 :(得分:2)

PyQt是基于事件的。它正在运行一个循环,不断等待事件,当它收到您关心的事件时,它会调用您的回调(或指示您的插槽)​​。所以,没有办法直接说“阻止直到我得到输入”。

但是,在你达到这一点之前,如果你的模拟在主线程中连续运行循环,PyQt也不能在主线程中连续运行循环。因此它无法响应来自操作系统的事件,如“更新窗口”或“退出”。就您的用户而言,该应用程序刚被冻结;除了流行的沙滩球(或其他平台等)外,她什么也看不见。

然而你选择解决第一个问题几乎可以免费解决第二个问题。


Why your GUI app freezes试图用一般的术语解释整个问题以及所有可能的解决方案,使用Tkinter作为GUI库的一个例子。如果你想要更具Qt特定的东西,我很确定Qt教程中有关于它的整个部分,虽然我不确定在哪里,你可能需要在脑中翻译一些C ++到Python。 / p>

但是有两个主要选项:回调或线程。


首先,您可以将循环分成小块,每个小块只需要几毫秒。运行第一个部分,而不是运行整个循环,作为最后一行,它要求PyQt尽快安排下一个部分(例如,使用超时为0的QTimer)。现在,Qt将每隔几毫秒检查一次事件,如果没有任何关系,它将立即启动你工作的下一步。

如果您的流控件已经围绕迭代器(或push-coroutine)构建,这会产生适当大小的块,这非常容易。如果没有,这可能意味着将外部循环中的流量控制从内到外,这很难理解。

因此,完成此操作后,您如何获得用户输入?简单:

  • 您可以调用raw_input,而不是安排下一段代码,而是执行一些适当的GUI工作 - 创建一个弹出消息框,取消隐藏文本输入控件和按钮,无论如何。
  • 将下一段代码连接为按钮点击或接收消息框或任何信号的处理程序。

或者,您可以在后台线程中运行您的工作。这不需要你重新组织任何东西,但它确实要求你注意不要在线程之间共享任何东西。不幸的是,这包括从后台线程调用GUI小部件上的方法,您认为这样做无法做任何有用的事情。幸运的是,PyQt具有很容易处理的机制:根据需要在线程之间自动路由信号。

那么,在这种情况下你如何要求用户输入?

  • raw_input之后的所有内容拆分为一个单独的函数,您将其作为got_input信号的处理程序进行连接。
  • 在您之前调用raw_input的原始功能中,您会发出gimme_input信号。
  • 编写一个gimme_input信号的处理程序,在主线程中运行,该线程将放置GUI小部件(与上面的单线程示例一样)。
  • 为OK按钮编写处理程序,将got_input信号发送回工作线程。