You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现SimPy与PyQt交互,实时更新显示仿真运行时间

解决方案

核心思路是用Qt的事件循环驱动SimPy仿真步进,避免SimPy的阻塞run()方法占满主线程导致Qt界面无响应,具体实现如下:

核心修改点

  • 不直接调用env.run(until=xxx)阻塞主线程,改为逐次步进SimPy环境
  • 用QTimer将仿真步进逻辑挂载到Qt的事件队列中,定时触发仿真推进
  • 每次步进时先执行完当前时间点的所有SimPy事件,再更新界面,直到达到仿真结束条件
import sys
import simpy
from PyQt5 import QtWidgets, QtCore

class Window(QtWidgets.QWidget):
    """ 可与SimPy交互的Qt窗口
    """
    def __init__(self, env, parent=None):
        super(Window, self).__init__()
        self.env = env
        self.init()

    def init(self) -> None:
        layout = QtWidgets.QVBoxLayout()
        self.label = QtWidgets.QLabel('SimPy Time: {}'.format(self.env.now))
        layout.addWidget(self.label)
        self.setLayout(layout)
        self.show()

    def update_label(self) -> None:
        """ 更新标签显示的仿真时间 """
        self.label.setText(f"SimPy Time: {self.env.now}")

def simpy_generator(env, window):
    """ SimPy仿真生成器 """
    while True:
        window.update_label()
        yield env.timeout(1)

if __name__ == "__main__":
    # 仿真结束时间
    SIM_END = 25
    env = simpy.Environment()

    app = QtWidgets.QApplication(sys.argv)
    window = Window(env=env)
    # 提前注册仿真进程
    env.process(simpy_generator(env, window))

    # 定义仿真步进槽函数
    def step_simpy():
        # 未到结束时间就步进1个时间单位
        if env.now < SIM_END:
            env.run(until=env.now + 1)
        else:
            # 仿真结束后停止定时器
            sim_timer.stop()

    # 初始化定时器,间隔0.5秒触发一次步进(可根据需求调整间隔)
    sim_timer = QtCore.QTimer()
    sim_timer.timeout.connect(step_simpy)
    sim_timer.start(500)

    app.exec_()

补充说明

  • 如果需要仿真按真实时间比例运行,调整QTimer的start()参数即可,比如想要仿真1秒对应真实1秒,就设置为start(1000)
  • 如果仿真逻辑比较复杂,单次步进耗时较高,可以把SimPy仿真放到单独的子线程中运行,通过Qt的信号槽机制把仿真数据传递到主线程更新界面,避免界面卡顿
  • 也可以通过env.peek()获取SimPy下一个事件的触发时间,自动计算步进的时间长度,不需要固定每次走1个单位,适配更复杂的仿真场景

内容的提问来源于stack exchange,提问作者Sav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:18:03