如何在Flet组件类间实现数据的实时传递?
Flet组件状态同步问题解决:YouTube下载器ID验证与下载模块数据同步
问题场景
使用Python和Flet开发简易YouTube视频下载应用,将界面拆分为两个组件:
- ID_Section:负责接收并验证YouTube视频/播放列表/短视频的ID,维护
valid_id(验证状态)和txt_video_id(输入值)两个状态 - Download_Section:负责触发下载操作,需要实时获取ID_Section的最新验证状态和输入值
当前问题:Download_Section只能获取ID_Section的初始值,当ID_Section中的valid_id或输入值更新后,Download_Section无法同步获取最新数据。
问题原因
- 实例不共享:在Download_Section的
__init__方法中,新建了ID_Section()实例来读取状态,这和页面上实际使用的ID_Section是两个完全独立的对象,自然无法获取实时更新的状态。 - 无状态监听机制:ID_Section状态变化时,没有通知Download_Section进行更新,也没有让Download_Section直接引用页面上的同一个ID_Section实例。
解决方案
修改思路
- 在
main函数中创建唯一的ID_Section和Download_Section实例,将ID_Section实例传递给Download_Section,让两者共享同一个状态源 - 让Download_Section直接引用ID_Section的属性,在需要时读取最新值
- 添加状态监听,让Download_Section根据ID_Section的验证状态自动启用/禁用下载按钮
修改后的完整代码
from yt_dlp import YoutubeDL import flet as ft import func class ID_Section(ft.Column): def __init__(self, on_status_change=None): super().__init__() self.horizontal_alignment = ft.CrossAxisAlignment.CENTER self.on_status_change = on_status_change # 状态变化回调 self.valid_id = False self.txt_video_id = ft.TextField( label='Cole o ID do vídeo/short/playlist aqui...', on_change=self.make_invalid ) self.bt_validate_id = ft.ElevatedButton(text="Validar", on_click=self.validate) self.txt_id_status = ft.Text('Insira uma ID para começar!', size=14, color='yellow') self.controls = [ ft.Row([ self.txt_video_id, self.bt_validate_id, ], ft.MainAxisAlignment.CENTER ), self.txt_id_status, ] def check_id(self, e): if self.valid_id: self.txt_id_status.value='ID válida!' self.txt_id_status.color='green' elif self.txt_video_id.value== '': self.txt_id_status.value='Insira uma ID para começar!' self.txt_id_status.color='yellow' else: self.txt_id_status.value='Insira uma ID válida!' self.txt_id_status.color='red' # 状态变化时通知回调 if self.on_status_change: self.on_status_change(self.valid_id, self.txt_video_id.value) self.update() def make_invalid(self, e): self.valid_id = False self.check_id(e) def validate(self, e): if self.txt_video_id.value != '': self.valid_id = func.link_validation(self.txt_video_id.value) self.check_id(e) class Download_Section(ft.Column): def __init__(self, id_section): super().__init__() self.horizontal_alignment = ft.CrossAxisAlignment.CENTER self.id_section = id_section # 引用同一个ID_Section实例 self.btn_download = ft.CupertinoFilledButton( content=ft.Text("Baixar"), disabled_color='yellow', disabled=True, # 默认禁用 on_click=self.download_vid ) self.controls = [ ft.Row(), self.btn_download, ] def update_button_state(self, valid_id, vid_id): # 根据验证状态启用/禁用下载按钮 self.btn_download.disabled = not valid_id or not vid_id.strip() self.update() def download_vid(self, e): # 直接读取ID_Section的最新值 current_valid = self.id_section.valid_id current_vid_id = self.id_section.txt_video_id.value print(current_valid) print(current_vid_id) # 这里添加下载逻辑 # if current_valid and current_vid_id: # with YoutubeDL() as ydl: # ydl.download([current_vid_id]) def main(page: ft.Page): page.title = 'YouTube Downloader' page.vertical_alignment = ft.MainAxisAlignment.CENTER page.horizontal_alignment = ft.CrossAxisAlignment.CENTER # 创建唯一的组件实例 id_section = ID_Section() download_section = Download_Section(id_section) # 给ID_Section绑定状态变化回调,更新下载按钮状态 id_section.on_status_change = download_section.update_button_state page.add( ft.Text('YouTube Downloader', size=28), ft.Row(height=20), id_section, download_section ) ft.app(main)
关键修改点
- ID_Section添加回调:新增
on_status_change参数,在状态变化时触发回调,通知Download_Section更新 - Download_Section接收实例引用:在
__init__中接收ID_Section实例,直接引用其属性获取最新值 - 按钮状态自动更新:通过回调函数
update_button_state,根据ID_Section的验证状态自动启用/禁用下载按钮 - main函数管理实例:创建唯一的组件实例,确保两者共享同一个状态源
内容的提问来源于stack exchange,提问作者Jizon Carlos
相关产品推荐
相关产品推荐

