我一直在寻找让PyQt和SimPy互相“对话”的机会。例如,在下面的代码中,我有一个带有单个标签的PyQt小部件,它显示SimPy环境时间。我希望这个标签随着模拟的进行而更新(我曾尝试用simpy_generator函数显示--小部件中的标签被更新,SimPy在一段时间内超时,并且此模式重复)。
import sys
import simpy
from PyQt5 import QtWidgets
class Window(QtWidgets.QWidget):
""" A generic Qt window that can interact with SimPy.
"""
def __init__(self, env, parent=None):
""" Class constructor.
Args:
env: SimPy environment.
parent: Optional parent of this widget.
"""
super(Window, self).__init__()
self.env = env
self.init()
def init(self) -> None:
""" Initialise the layout of the widget. Just a label that displays the
SimPy Environment time.
"""
layout = QtWidgets.QVBoxLayout()
self.label = QtWidgets.QLabel('SimPy Time: {}'.format(self.env.now))
layout.addWidget(self.label)
self.setLayout(layout)
self.show()
def update(self) -> None:
""" Update method for the window; retrieve the current SimPy environment time
and update the label.
"""
self.label.setText("SimPy Time: {}".format(self.env.now))
def simpy_generator(env, window):
""" Generator for SimPy simulation; just tick the environment's clock and update
the QtWidget's fields.
Args:
env: SimPy environment.
window: QtWidget to update with SimPy data.
"""
while True:
window.update()
yield env.timeout(1)
if __name__ == "__main__":
env = simpy.Environment()
app = QtWidgets.QApplication(sys.argv)
window = Window(env=env)
### These need to be incorporated into the Qt event queue somehow?
# simpy_process = env.process(simpy_generator(env, window))
# env.run(until=25)
app.exec_()然而,对于如何才能使其工作,我确实感到困惑不已。我知道Qt需要管理它的事件队列,而更新通常是通过一些QTimer来完成的,这些as发出一个信号来触发它所链接的某个插槽的运行(在本例中是Window的update方法)。但这似乎与SimPy自己的事件队列不兼容(或者更确切地说,我太不了解它们应该如何交互);生成器需要作为一个进程添加到环境中,然后环境设置为运行直到完成(参见代码的注释部分)。
有人能建议我如何才能做到这一点吗?
发布于 2021-09-15 21:40:53
根据Michael的回答,SimPy模拟是在独立线程上启动的。上面的代码被修改为包含以下内容:
def simpy_thread(env, window):
""" Function to be run on a dedicated thread where the SimPy simulation will live.
Args:
env: SimPy environment.
window: QtWidget to update with SimPy data.
"""
simpy_process = env.process(simpy_generator(env, window))
env.run(until=25)
if __name__ == "__main__":
env = simpy.rt.RealtimeEnvironment(factor=1)
# Create the Qt window
app = QtWidgets.QApplication(sys.argv)
window = Window(env=env)
# Launch a dedicated SimPy thread that has a reference to the window for updating
thread = threading.Thread(target=simpy_thread, args=(env,window,))
thread.start()
# Finally, start the Qt event queue; the code will block at this point until the window
# object is destroyed
app.exec_()仍然非常有兴趣知道人们是否有其他解决方案:)
https://stackoverflow.com/questions/69195416
复制相似问题