各位大神好,我建立一个简单的由电池、开关和负载的电路,目的是通过开关实时操控来量测电路中电压、电流的变化。现在的代码如下:
import tkinter as tkimport numpy as npimport matplotlib.pyplot as pltfrom matplotlib.backends.backend_tkagg import FigureCanvasTkAggfrom matplotlib.animation import FuncAnimationt_max = 10.0 # 最大时间(秒)fps = 20 # 帧率t = np.linspace(0, t_max, int(fps * t_max)) # 时间序列# 电路参数V_battery = 15 # 电池电压(V)R_load = 10 # 负载电阻(欧姆)class CircuitSimulator: def __init__(self, t_values, initial_switch_state=True): self.t_values = t_values self.VoltageOverTime = np.full_like(t_values, V_battery) # 初始时所有时间点电压均为电池电压 self.CurrentOverTime = np.full_like(t_values, V_battery / R_load) # 初始化电流数组 self.switch_states = np.ones_like(t_values, dtype=bool) * initial_switch_state # 记录每个时间点开关的状态 self.previous_switch_state = initial_switch_state # 记录上一个开关状态 self.previous_switch_time_index = -1 # 初始化为-1,表示尚未进行过切换 def calculate_circuit_response(self, current_time_index): # 检查当前时间点是否有开关切换发生 if current_time_index > self.previous_switch_time_index: # 检查当前时间点的开关状态是否与前一时刻不同 if self.switch_states[current_time_index] != self.switch_states[current_time_index - 1]: self.previous_switch_state = self.switch_states[current_time_index] next_switch_index = current_time_index + np.argmax(self.switch_states[current_time_index:] != self.switch_states[current_time_index]) if not self.previous_switch_state: # 开关断开 self.VoltageOverTime[current_time_index:next_switch_index] = 0 self.CurrentOverTime[current_time_index:next_switch_index] = 0 else: # 开关闭合 self.VoltageOverTime[current_time_index:next_switch_index] = V_battery * np.ones_like(self.VoltageOverTime[current_time_index:next_switch_index]) self.CurrentOverTime[current_time_index:next_switch_index] = V_battery / R_load * np.ones_like(self.CurrentOverTime[current_time_index:next_switch_index]) # 更新上一次开关切换的时间索引 self.previous_switch_time_index = next_switch_index def toggle_switch_at_time(self, switch_time_index): if 0 <= switch_time_index < len(self.switch_states): # 只改变指定时间点及其之后已定义的时间段内的开关状态 end_of_simulation = min(switch_time_index + 1, len(self.switch_states)) # 防止越界 self.switch_states[switch_time_index:end_of_simulation] = not self.switch_states[switch_time_index] else: raise IndexError(f"Invalid time index: {switch_time_index}. Maximum allowed index is {len(self.switch_states) - 1}")# 创建一个新的窗口类,用于集成matplotlib图表与Tkinter GUIclass CircuitSimulationGUI(tk.Tk): def __init__(self): super().__init__() # 设置窗口标题 self.title("电路运行状态监控") # 创建主容器 container = tk.Frame(self) container.pack(side="top", fill="both", expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) # 初始化图表 self.fig, self.axs = plt.subplots(2, 1, figsize=(10, 6)) self.V_line, = self.axs[0].plot([], [], label='Circuit Voltage (V)') self.I_line, = self.axs[1].plot([], [], label='Circuit Current (A)', color='r') for ax in self.axs: ax.set_xlabel('Time (s)') ax.set_ylabel('Value') ax.legend() # 将matplotlib图表嵌入到Tkinter窗口中 self.canvas = FigureCanvasTkAgg(self.fig, master=container) self.canvas.draw() self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) # 创建开关按钮 self.manual_switch_button = tk.Button(master=self, text="Close Circuit", command=self.toggle_manual_switch) self.manual_switch_button.pack(pady=10) # 初始化动画 self.simulator = CircuitSimulator(t) self.ani = None # 将动画实例化变量初始化为None # 初始化状态变量 self.current_time_index = 0 # 启动模拟 self.start_simulation() def toggle_manual_switch(self): """ 处理手动开关按钮点击事件,切换当前时刻的开关状态并持续影响后续状态 """ # 获取当前时刻的索引 current_index = int(self.current_time_index) # 切换开关状态 self.simulator.toggle_switch_at_time(current_index) self.simulator.calculate_circuit_response(current_index) # 更新按钮文本和命令 if self.manual_switch_button["text"] == "Close Circuit": self.manual_switch_button["text"] = "Open Circuit" else: self.manual_switch_button["text"] = "Close Circuit" # 更新整个图表,传递当前时间点的索引 self.update_plot(current_index) self.canvas.draw_idle() def start_simulation(self): # 使用更现代且兼容的方式检测和控制动画状态 if self.ani is None: self.ani = FuncAnimation( fig=self.fig, func=self.update_plot, #传递函数而非方法 frames=len(t), interval=200, blit=True ) self.canvas.draw_idle() elif getattr(self.ani, '_is_running', False): # 更改此处 self.ani.event_source.stop() self.ani.event_source.start() else: self.ani.event_source.start() def update_plot(self, frame): self.simulator.calculate_circuit_response(frame) time = t[frame] V_circuit = self.simulator.VoltageOverTime[:frame+1] I_circuit = self.simulator.CurrentOverTime[:frame+1] self.V_line.set_data(t[:len(V_circuit)], V_circuit) self.I_line.set_data(t[:len(I_circuit)], I_circuit) self.axs[0].set_xlim(0, t_max) self.axs[1].set_xlim(0, t_max) self.axs[0].set_ylim(0, 20) self.axs[1].set_ylim(0, 2) print("Plot updated") # 添加这行代码来确认图表是否被更新 print("Plot Voltage:", V_circuit[-1], "V") return self.V_line, self.I_line# 创建并启动GUI应用if __name__ == "__main__": app = CircuitSimulationGUI() app.mainloop()
现在基本运行时没有问题,但是在逻辑上有些不对。
1、在点击模拟开关的按钮时,整体的电压电流从0时刻,而不是点击按钮时刻开始。
2、按钮无法实现电路的断开和闭合。
我曾经改动了在CircuitSimulator类中的calculate_circuit_response,CircuitSimulationGUI(tk.Tk)中的toggle_manual_switch以及update_plot,但都达不到理想的效果。也曾经到某四字字母网站求助,但是回答的都是GPT未经验证的答案。
希望获得效果如下图所示:
这种问题很赞
def toggle_manual_switch(self): """ 处理手动开关按钮点击事件,切换当前时刻的开关状态并持续影响后续状态 """ # 获取当前时刻的索引 current_index = int(self.current_time_index) # FIXME: Q1.这个值没有更新过def update_plot(self, frame): self.simulator.calculate_circuit_response(frame) time = t[frame] # FIXME: A1.这里更新一下 self.current_time_index = frame
修改值不持久问题。能满足逻辑,但思想好像和你的不太一致,又不太想花太多时间了解你的意图。
def calculate_circuit_response(self, current_time_index): # 检查当前时间点是否有开关切换发生 if current_time_index > self.previous_switch_time_index: # 检查当前时间点的开关状态是否与前一时刻不同 if self.switch_states[current_time_index] != self.switch_states[current_time_index - 1]: # self.previous_switch_state = self.switch_states[current_time_index] self.previous_switch_state = not self.previous_switch_state # TODO: 这块的值反正需要修改一下的 next_switch_index = current_time_index + np.argmax( self.switch_states[current_time_index:] != self.switch_states[current_time_index]) if not self.previous_switch_state: # 开关断开 self.VoltageOverTime[current_time_index:] = 0 # FIXME: VoltageOverTime 和 CurrentOverTime 的赋值有些问题,之前是只赋值一个点? self.CurrentOverTime[current_time_index:] = 0 else: # 开关闭合 self.VoltageOverTime[current_time_index:] = V_battery * np.ones_like( self.VoltageOverTime[current_time_index:]) self.CurrentOverTime[current_time_index:] = V_battery / R_load * np.ones_like( self.CurrentOverTime[current_time_index:]) # 更新上一次开关切换的时间索引 self.previous_switch_time_index = next_switch_index
问题内容: 我想生成大量的Tkinter ,它们可以做不同的事情。我有以下代码: 如果为5,尽管我得到标记为的按钮,但单击它们时都可以。 我需要第一个按钮执行,第二个按钮执行,依此类推。 问题答案: 我认为问题在于,循环结束后,会获取的最终值。这应该解决(未测试): 更新资料 顺便说一句,这是通过在函数中添加一个自变量的默认值来实现的,该默认值是根据在循环中创建每个变量时的值计算得出的,而不是在稍
Button 控件是 Tkinter 中常用的窗口部件之一,同时也是实现程序与用户交互的主要控件。通过用户点击按钮的行为来执行回调函数,是 Button 控件的主要功用。首先自定义一个函数或者方法,然后将函数与按钮关联起来,最后,当用户按下这个按钮时,Tkinter 就会自动调用相关函数。 按钮控件使用起来非常简单,它同样可以包含文本、图像、位图,并通过 参数回调函数。当然按钮也并非一定要执行回调
我有一个简单的PDF与一个按钮字段,我想用图像填充。 按钮字段在文档中出现多次。我想在字段级别设置一次图像,以便在字段的每次出现时都显示图像。 我用于测试的PDF。 失败的代码: 引发的异常: 我使用的是iText7.1.4(上一个7.x版本)。
本文向大家介绍Python 窗体(tkinter)按钮 位置实例,包括了Python 窗体(tkinter)按钮 位置实例的使用技巧和注意事项,需要的朋友参考一下 如下所示: 以上这篇Python 窗体(tkinter)按钮 位置实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。
本文向大家介绍js实现的倒计时按钮实例,包括了js实现的倒计时按钮实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了js实现的倒计时按钮。分享给大家供大家参考。具体分析如下: 效果图如下: 具体代码如下: 这里只是一个小例子,在实际运用中,可能需要记录各种时间,考虑到页面刷新的变化,需要用cookie来进行数据存储等等! 希望本文所述对大家的javascript程序设计有所帮助。
本文向大家介绍php输出控制函数和输出函数生成静态页面,包括了php输出控制函数和输出函数生成静态页面的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了php输出控制函数和输出函数生成静态页面的具体代码,供大家参考,具体内容如下 Output Control 函数详解: flush - 刷新输出缓冲 ob_clean - 清空输出缓冲区 ob_end_clean - 清空缓冲区并关闭输