Python Kivy开发:如何跨类访问全局变量?飞行计算APP遇阻
解决Kivy跨Screen传递数据的问题
刚上手Kivy和面向对象编程时,遇到不同Screen之间无法共享变量的问题太常见了。你尝试的全局变量方案容易踩作用域的坑,而且不是最佳实践,我给你几个更可靠的方案:
方案1:通过ScreenManager获取其他Screen实例直接访问属性
这个方法最简单,适合你的场景:
步骤1:在输入Screen中把计算结果存为实例属性
修改Takeoff_3Window的TO_4Btn方法,把计算好的HWC1和XWC1存在当前Screen的实例里,而不是全局变量:
def TO_4Btn(self, math): # 先调用校验方法,注意这里要调用方法,不是判断函数对象 is_valid = self.advance_TO3() if is_valid: # 从控件获取输入值(确保先转成数值类型) rwy_val = float(self.rwy1.text) wd_val = float(self.wd1.text) wv_val = float(self.wv1.text) angle_diff = abs(rwy_val - wd_val) # 把结果存为当前Screen的实例属性 self.HWC1 = round((wv_val * math.cos(math.radians(angle_diff))), 1) self.XWC1 = round((wv_val * math.sin(math.radians(angle_diff))), 1) self.manager.current = "TakeoffResult" # 这里要对应你在ScreenManager里给结果Screen起的名字 else: pass
步骤2:在结果Screen中获取输入Screen的实例并读取属性
修改Takeoff_ResultWindow的TOR_Page1方法,通过self.manager.get_screen()拿到输入Screen的实例,直接读取里面的属性:
def TOR_Page1(self): # 获取输入Screen的实例(参数是你在ScreenManager中注册的该Screen的name) takeoff_input_screen = self.manager.get_screen("Takeoff_3Window") # 读取计算好的结果 hwc_val = takeoff_input_screen.HWC1 xwc_val = takeoff_input_screen.XWC1 # 赋值给Label self.tor_hwc.text = f"Wind (HWC): {hwc_val}" self.tor_xwc.text = f"Wind (XWC): {xwc_val}" # 其他变量同理,比如从对应的输入Screen中读取(比如TOM、Elevation1等) # 假设这些值也存在对应的Screen实例属性里 self.tor_tom.text = f"TOM: {takeoff_input_screen.TOM}" # ... 其他Label赋值
方案2:创建共享数据类(更规范的长期方案)
如果你的应用后续会有更多Screen需要共享数据,推荐用一个专门的类来存储所有共享数据:
步骤1:定义共享数据类
class FlightData: def __init__(self): # 初始化所有需要共享的变量 self.HWC1 = 0.0 self.XWC1 = 0.0 self.TOM = 0.0 self.Elevation1 = 0.0 self.QNH_1 = 0.0 # ... 其他需要共享的变量
步骤2:在App类中初始化数据实例并传递给所有Screen
from kivy.app import App from kivy.uix.screenmanager import ScreenManager class FlightPlanningApp(App): def build(self): # 创建共享数据实例 self.flight_data = FlightData() sm = ScreenManager() # 添加Screen时把数据实例传递过去 sm.add_widget(Takeoff_3Window(name="Takeoff_3Window", flight_data=self.flight_data)) sm.add_widget(Takeoff_ResultWindow(name="TakeoffResult", flight_data=self.flight_data)) # ... 添加其他Screen return sm
步骤3:在每个Screen中接收并使用共享数据
修改Takeoff_3Window的初始化和计算方法:
class Takeoff_3Window(Screen): rwy1 = ObjectProperty(None) wd1 = ObjectProperty(None) wv1 = ObjectProperty(None) def __init__(self, flight_data, **kwargs): super().__init__(**kwargs) self.flight_data = flight_data # 保存共享数据实例 def TO_4Btn(self, math): is_valid = self.advance_TO3() if is_valid: rwy_val = float(self.rwy1.text) wd_val = float(self.wd1.text) wv_val = float(self.wv1.text) angle_diff = abs(rwy_val - wd_val) # 把结果存到共享数据类里 self.flight_data.HWC1 = round((wv_val * math.cos(math.radians(angle_diff))), 1) self.flight_data.XWC1 = round((wv_val * math.sin(math.radians(angle_diff))), 1) # 其他输入数据也存到共享类里 self.flight_data.TOM = ... # 从对应控件获取值 self.manager.current = "TakeoffResult"
修改Takeoff_ResultWindow的初始化和展示方法:
class Takeoff_ResultWindow(Screen): tor_tom = ObjectProperty(None) tor_cog = ObjectProperty(None) tor_hwc = ObjectProperty(None) tor_xwc = ObjectProperty(None) # ... 其他控件 def __init__(self, flight_data, **kwargs): super().__init__(**kwargs) self.flight_data = flight_data def TOR_Page1(self): # 直接从共享数据类读取值 self.tor_hwc.text = f"Wind (HWC): {self.flight_data.HWC1}" self.tor_xwc.text = f"Wind (XWC): {self.flight_data.XWC1}" self.tor_tom.text = f"TOM: {self.flight_data.TOM}" # ... 其他Label赋值
对你原有代码的小提示
你之前的代码里有个小错误:if advance_TO3 is True:这里,advance_TO3是函数对象,应该改成调用方法if self.advance_TO3()(假设advance_TO3方法返回布尔值表示校验是否通过)。
全局变量方案失效大概率是因为作用域问题——比如在Takeoff_ResultWindow里没有正确导入这些全局变量,或者赋值时没有正确声明global(比如在TO_4Btn里虽然写了global HWC1, XWC1,但如果HWC1之前没定义过,可能会有问题)。不过还是推荐上面的两种方案,代码更清晰也更易维护。
内容的提问来源于stack exchange,提问作者Matt S
相关产品推荐
相关产品推荐

