Petri网模拟工具按钮函数异常:多按钮失效与绘图弹窗问题
解决方案
问题1:多按钮仅最后一个可点击的修复
原代码通过buttons.index(event.inaxes)获取按钮索引的方式不可靠——matplotlib的Axes引用会在后续创建操作中被干扰,导致无法正确匹配早期创建的按钮。正确做法是在创建按钮时直接绑定对应的变迁索引,通过闭包保存每个按钮的专属索引值,彻底避免动态查找的误差。
问题2:触发变迁后弹出新窗口的修复
点击事件中重复调用plt.show()是问题根源:该函数在非交互模式下会启动新的绘图窗口。应使用画布的draw_idle()方法更新原窗口内容,同时确保整个程序仅在主流程末尾调用一次plt.show(),避免重复触发窗口创建。
修改后的完整代码
def create_transition_buttons(num_transitions, markings_vector, incidence_matrix, ax, fig, G=None, num_places=None): buttons = [] button_width = 0.1 button_gap = 0.02 def on_button_click(transition_idx): nonlocal markings_vector # 校验变迁是否可触发:有输入库所则所有输入库所标识必须>0,无输入则直接可触发 input_places = incidence_matrix[:, transition_idx] == -1 if not np.any(input_places) or np.all(markings_vector[input_places] > 0): # 更新库所标识 modified = [False] * num_places for i in range(num_places): if incidence_matrix[i, transition_idx] == 1 and not modified[i]: markings_vector[i] += 1 modified[i] = True for i in range(num_places): if incidence_matrix[i, transition_idx] == -1 and not modified[i]: markings_vector[i] -= 1 modified[i] = True # 重绘Petri网并更新原窗口 ax.clear() draw_petri_net_graph(G, num_places, num_transitions, markings_vector, incidence_matrix) fig.canvas.draw_idle() for i in range(num_transitions): button_x = 0.05 + i * (button_width + button_gap) button_y = 0.05 button_label = f"Fire T{i+1}" button_ax = plt.axes([button_x, button_y, button_width, 0.05]) button = plt.Button(button_ax, button_label) # 通过lambda默认参数绑定当前按钮对应的变迁索引,避免闭包变量延迟绑定问题 button.on_clicked(lambda event, idx=i: on_button_click(idx)) buttons.append(button) # 移除函数内的plt.show(),统一移到主程序中调用 return buttons
主程序调用示例
确保整个流程仅调用一次plt.show():
# 初始化绘图组件 fig, ax = plt.subplots() # 初始化Petri网核心参数 num_places = 3 num_transitions = 2 markings_vector = np.array([1, 0, 0]) incidence_matrix = np.array([[-1, 0], [1, -1], [0, 1]]) G = None # 替换为你的图结构对象 # 创建变迁触发按钮 create_transition_buttons(num_transitions, markings_vector, incidence_matrix, ax, fig, G, num_places) # 仅在此处启动绘图窗口 plt.show()
额外修正说明
原代码中的变迁触发条件逻辑存在误差,修改后的条件严格遵循Petri网规则:只有当所有输入库所的标识数量满足要求时,变迁才能触发;无输入库所的变迁可直接触发。
内容的提问来源于stack exchange,提问作者samm bodie
相关产品推荐
相关产品推荐

