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

Flet框架中类实现表单时page.update无法更新GUI问题求助

问题描述

我尝试用Tesseract识别图片数据后更新Flet表单的TextField值,但遇到了问题:代码里已经更新了TextField的value属性,GUI界面却没同步更新。直接在main函数里写代码时功能正常,但把表单封装成UserControl类后就出现了这个GUI不更新的问题。

下面是相关代码示例:

封装为类的问题代码

from flet import *
from vvisiteur import Visiteur
import pytesseract
from PIL import Image as img

class AppForm(UserControl):
    def __init__(self, page : Page):
        super().__init__()
        self.page = page
        self.name = self.app_form_input_field('Name', True)
        self.id_number = self.app_form_input_field('id Number', 3)
        self.phone = self.app_form_input_field('phone', 1)
        self.autre = self.app_form_input_field('Field Tree *', 1)

    def app_form_input_field(self, name:str, expand:int):
        return Container(
            expand=expand,
            height=45,
            bgcolor='#ebebeb',
            border_radius=6,
            padding=8,
            content = TextField(
                        label=name,
                        border_color="transparent",
                        height=20,
                        text_size=13,
                        content_padding=0,
                        cursor_color="black",
                        cursor_width=1,
                        cursor_height=18,
                        color="black",
                    ),
        )
    
    def pickFile(self, e:FilePickerResultEvent):
        image_loc = e.files[0].path
        img_pro=img.open(image_loc)
        text = pytesseract.image_to_string(img_pro, lang='fra')
        sections= {}
        lines = text.split("\n")
        sections['name'] = lines[18] + ' ' + lines[4]
        sections['id number'] = lines[24].split(" ")[0]
        temp =  lines[13].split()
        sections['phone'] = ' '.join(temp[1:])
        print(sections)
        self.id_number.content.value = sections["id number"]
        self.name.content.value = sections["name"]
        self.phone.content.value = sections["phone"]
        self.page.snack_bar = SnackBar(
            Text("sucess get from image", size=30),
            bgcolor="green"
        )
        self.page.snack_bar.open=True
        self.page.update()
    

    def return_vit(self):
        visiteur = Visiteur(self.name.content.value ,self.phone.content.value, self.id_number.content.value)
        return visiteur.to_dict()
        
    def build(self):
        file_picker = FilePicker(on_result=self.pickFile)
        self.page.overlay.append(file_picker)
        return Container(
            expand=True,
            height=220,
            bgcolor="white10",
            border=border.all(1, "#ebebeb"),
            border_radius=8,
            padding= 15,
            content=Column(
                expand=True,
                controls = [
                    Row(controls= [self.name]),
                    Row(controls= [
                        self.id_number,
                        self.phone,
                        self.autre,
                        ]
                    ),
                    ElevatedButton("Process",
                           bgcolor="blue",
                           color='white',
                           on_click=lambda _ :file_picker.pick_files()),
                ]
            )
        )

直接在main中编写的正常代码

import pytesseract
from PIL import Image as img
from flet import *
import flet
import os

def main(page: Page):
    image_loc= TextField(label="yout image name")
    id_number= TextField(label="id number")
    name_txt= TextField(label="your name")
    phone= TextField(label="phone number")
    healthy_service = TextField(label="healthy service")
    image_preview = Image(src=False, width= 150, height=120)

    def pickFile(e:FilePickerResultEvent):
        image_loc.value = e.files[0].path
        print(image_loc.value)
        img_pro=img.open(image_loc.value)
        text = pytesseract.image_to_string(img_pro, lang='fra')
        sections= {}
        lines = text.split("\n")
        sections['name'] = lines[18] + ' ' + lines[4]
        sections['id number'] = lines[24].split(" ")[0]
        temp =  lines[13].split()
        sections['phone'] = ' '.join(temp[1:])
        print(sections)
        id_number.value = sections["id number"]
        name_txt.value = sections["name"]
        phone.value = sections["phone"]
        page.snack_bar = SnackBar(
            Text("sucess get from image", size=30),
            bgcolor="green"
        )
        page.snack_bar.open=True
        page.update()

    file_picker = FilePicker(on_result=pickFile)

    page.overlay.append(file_picker)
    page.add(
        Column([
            image_loc,
            ElevatedButton("Process",
                           bgcolor="blue",
                           color='white',
                           on_click=lambda _ :file_picker.pick_files()),
            Text('you result in image', weight="bold"),
            image_preview,
            id_number,
            name_txt,
            phone,
            healthy_service,
        ])
    )

flet.app(target=main)

最简类实现的问题代码

import pytesseract
from PIL import Image as img
from flet import *
import flet
import os


class form(UserControl):
    def __init__(self, page : Page):
        super().__init__()
        self.page = page
        self.image_loc= TextField(label="yout image name")
        self.id_number= TextField(label="id number")
        self.name_txt= TextField(label="your name")
        self.phone= TextField(label="phone number")
        self.healthy_service = TextField(label="healthy service")
        self.image_preview = Image(src=False, width= 150, height=120)

    def pickFile(self, e:FilePickerResultEvent):
        image_loc = e.files[0].path
        img_pro=img.open(image_loc)
        text = pytesseract.image_to_string(img_pro, lang='fra')
        sections= {}
        lines = text.split("\n")
        sections['name'] = lines[18] + ' ' + lines[4]
        sections['id number'] = lines[24].split(" ")[0]
        temp =  lines[13].split()
        sections['phone'] = ' '.join(temp[1:])
        print(sections)
        self.id_number.value = sections["id number"]
        self.name_txt.value = sections["name"]
        self.phone.value = sections["phone"]
        self.page.snack_bar = SnackBar(
            Text("sucess get from image", size=30),
            bgcolor="green"
        )
        self.page.snack_bar.open=True
        self.page.update()

    def build(self):
        file_picker = FilePicker(on_result=self.pickFile)
        self.page.overlay.append(file_picker)
        return(
            Container(
                content = Column([
                ElevatedButton("Process",
                           bgcolor="blue",
                           color='white',
                           on_click=lambda _ :file_picker.pick_files()),
                Text('you result in image', weight="bold"),
                self.image_preview,
                self.id_number,
                self.name_txt,
                self.phone,
                self.healthy_service,
            ])
        )
    )

def main(page: Page):
    myform = form(page)
    page.add(myform)
    page.update()

flet.app(target=main)
解决方案

问题出在Flet的UserControl更新机制上:当你在UserControl内部修改控件属性后,仅调用self.page.update()不足以触发UserControl内部控件的UI同步,必须额外调用self.update()来通知Flet更新当前UserControl的视图。

下面是修改后的代码:

修改后的封装类代码

from flet import *
from vvisiteur import Visiteur
import pytesseract
from PIL import Image as img

class AppForm(UserControl):
    def __init__(self, page : Page):
        super().__init__()
        self.page = page
        self.name = self.app_form_input_field('Name', True)
        self.id_number = self.app_form_input_field('id Number', 3)
        self.phone = self.app_form_input_field('phone', 1)
        self.autre = self.app_form_input_field('Field Tree *', 1)

    def app_form_input_field(self, name:str, expand:int):
        return Container(
            expand=expand,
            height=45,
            bgcolor='#ebebeb',
            border_radius=6,
            padding=8,
            content = TextField(
                        label=name,
                        border_color="transparent",
                        height=20,
                        text_size=13,
                        content_padding=0,
                        cursor_color="black",
                        cursor_width=1,
                        cursor_height=18,
                        color="black",
                    ),
        )
    
    def pickFile(self, e:FilePickerResultEvent):
        image_loc = e.files[0].path
        img_pro=img.open(image_loc)
        text = pytesseract.image_to_string(img_pro, lang='fra')
        sections= {}
        lines = text.split("\n")
        sections['name'] = lines[18] + ' ' + lines[4]
        sections['id number'] = lines[24].split(" ")[0]
        temp =  lines[13].split()
        sections['phone'] = ' '.join(temp[1:])
        print(sections)
        self.id_number.content.value = sections["id number"]
        self.name.content.value = sections["name"]
        self.phone.content.value = sections["phone"]
        self.page.snack_bar = SnackBar(
            Text("sucess get from image", size=30),
            bgcolor="green"
        )
        self.page.snack_bar.open=True
        self.page.update()
        # 新增:更新当前UserControl
        self.update()
    

    def return_vit(self):
        visiteur = Visiteur(self.name.content.value ,self.phone.content.value, self.id_number.content.value)
        return visiteur.to_dict()
        
    def build(self):
        file_picker = FilePicker(on_result=self.pickFile)
        self.page.overlay.append(file_picker)
        return Container(
            expand=True,
            height=220,
            bgcolor="white10",
            border=border.all(1, "#ebebeb"),
            border_radius=8,
            padding= 15,
            content=Column(
                expand=True,
                controls = [
                    Row(controls= [self.name]),
                    Row(controls= [
                        self.id_number,
                        self.phone,
                        self.autre,
                        ]
                    ),
                    ElevatedButton("Process",
                           bgcolor="blue",
                           color='white',
                           on_click=lambda _ :file_picker.pick_files()),
                ]
            )
        )

修改后的最简类实现代码

import pytesseract
from PIL import Image as img
from flet import *
import flet
import os


class form(UserControl):
    def __init__(self, page : Page):
        super().__init__()
        self.page = page
        self.image_loc= TextField(label="yout image name")
        self.id_number= TextField(label="id number")
        self.name_txt= TextField(label="your name")
        self.phone= TextField(label="phone number")
        self.healthy_service = TextField(label="healthy service")
        self.image_preview = Image(src=False, width= 150, height=120)

    def pickFile(self, e:FilePickerResultEvent):
        image_loc = e.files[0].path
        img_pro=img.open(image_loc)
        text = pytesseract.image_to_string(img_pro, lang='fra')
        sections= {}
        lines = text.split("\n")
        sections['name'] = lines[18] + ' ' + lines[4]
        sections['id number'] = lines[24].split(" ")[0]
        temp =  lines[13].split()
        sections['phone'] = ' '.join(temp[1:])
        print(sections)
        self.id_number.value = sections["id number"]
        self.name_txt.value = sections["name"]
        self.phone.value = sections["phone"]
        self.page.snack_bar = SnackBar(
            Text("sucess get from image", size=30),
            bgcolor="green"
        )
        self.page.snack_bar.open=True
        self.page.update()
        # 新增:更新当前UserControl
        self.update()

    def build(self):
        file_picker = FilePicker(on_result=self.pickFile)
        self.page.overlay.append(file_picker)
        return(
            Container(
                content = Column([
                ElevatedButton("Process",
                           bgcolor="blue",
                           color='white',
                           on_click=lambda _ :file_picker.pick_files()),
                Text('you result in image', weight="bold"),
                self.image_preview,
                self.id_number,
                self.name_txt,
                self.phone,
                self.healthy_service,
            ])
        )
    )

def main(page: Page):
    myform = form(page)
    page.add(myform)
    page.update()

flet.app(target=main)

原理说明

Flet中,UserControl是独立的组件单元,它有自己的视图状态。当你修改UserControl内部控件的属性时,需要调用self.update()来告知Flet重新渲染这个UserControl的内容。而直接在main中操作的控件属于页面直接管理,调用page.update()就能同步所有页面控件的状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:00:54