在模拟期间通过 GUI 读取用户的输入 [关闭]
Posted
技术标签:
【中文标题】在模拟期间通过 GUI 读取用户的输入 [关闭]【英文标题】:Reading user's input during simulation via GUI [closed] 【发布时间】:2014-07-23 21:13:10 【问题描述】:我正在使用 simpy 将基于模拟的应用程序转换为 GUI。
程序当前在控制台中运行,并且正在执行模拟的 simpy 默认以类似循环的语法运行。这就是我的问题所在。
目前,在代码的控制台版本中,我通过 raw_input() 函数获取用户输入,该函数能够中断代码并允许用户输入模拟所需的值。然而,尽管对其进行了研究,但似乎没有一种类似且干净的方式可以通过我正在构建的 GUI 中的 pyqt inisde 执行此操作。
唯一的方法是在不同的线程中运行进程吗?如果我采用这种方法,它的外观和真正的功能会如何?
【问题讨论】:
【参考方案1】:PyQt 是基于事件的。它不断地运行一个循环等待事件,并在收到您关心的事件时调用您的回调(或向您的插槽发出信号)。所以,没有办法直接说“在我得到输入之前阻止”。
但是,在你到达那一点之前,如果你的模拟在主线程中连续运行一个循环,PyQt 也不能在主线程中连续运行一个循环。因此它无法响应来自操作系统的事件,例如“更新您的窗口”或“退出”。就您的用户而言,该应用程序只是冻结了;她只会看到广受欢迎的沙滩球(或其他平台等效)。
无论您选择如何解决第一个问题,几乎都可以免费解决第二个问题。
Why your GUI app freezes 试图解释整个问题,以及所有可能的解决方案,一般来说,使用 Tkinter 作为 GUI 库的示例。如果你想要更多特定于 Qt 的东西,我很确定 Qt 教程中有一个完整的部分,尽管我不确定在哪里,你可能需要在脑海中将一些 C++ 翻译成 Python。
但有两个主要选项:回调或线程。
首先,您可以将循环分成小块,每个小块只需要几毫秒。不是运行整个循环,而是运行第一段,作为最后一行,它要求 PyQt 尽快安排下一段(例如,使用超时为 0 的QTimer
)。现在,Qt 将每隔几毫秒检查一次事件,如果它没有任何事情要做,它会立即开始你的下一步工作。
如果您的流控制已经围绕生成适当大小的块的迭代器(或推送协程)构建,那么这非常容易。如果不是,则可能意味着将外部循环中的流量控制由内向外翻转,这可能很难理解。
那么,完成这些之后,您如何获得用户输入?简单:
您应该调用raw_input
,而不是安排下一段代码,而是执行一些适当的 GUI 操作 — 创建弹出消息框、取消隐藏文本输入控件和按钮等。
连接下一段代码作为处理按钮单击或消息框接受或任何信号的处理程序。
或者,您可以在后台线程中运行您的工作。这不需要你重新组织任何东西,但它确实需要你小心不要在线程之间共享任何东西。不幸的是,这包括从后台线程调用 GUI 小部件上的方法,您认为这会导致无法执行任何有用的操作。幸运的是,PyQt 的机制可以很容易地处理这个问题:信号会根据需要在线程之间自动路由。
那么,在这种情况下,您如何要求用户输入?
将raw_input
之后的所有内容拆分为一个单独的函数,您可以将其作为got_input
信号的处理程序进行连接。
在原来调用 raw_input
的函数中,改为发出 gimme_input
信号。
为gimme_input
信号编写一个处理程序以在主线程中运行,这将建立 GUI 小部件(与上面的单线程示例一样)。
为“确定”按钮编写一个处理程序,将got_input
信号发送回工作线程。
【讨论】:
这是一个很棒且非常透彻的答案。非常感谢!以上是关于在模拟期间通过 GUI 读取用户的输入 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
我如何从我的 GUI 向我的 matlab 模拟工作区 struct() 提供输入