我正在使用simpy将基于仿真的应用程序转换为GUI。
程序当前在控制台中运行,并且正在进行模拟的simpy默认以循环方式运行。那就是我的问题所在。
目前,在代码的控制台版本中,我通过raw_input()函数获取用户输入,并且能够中断代码并允许用户输入模拟所需的值。然而,尽管进行了研究,但似乎并没有采用类似且干净的方式来实现这一目标。通过pyqt inisde构建GUI。
唯一的方法是在不同的线程中运行进程吗?如果我采用这种方法,那看起来究竟如何并真正起作用?
答案 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小部件(与上面的单线程示例一样)。got_input
信号发送回工作线程。