こちらの続きです。
ルーティングを行いたい1 - C#ATIA
こちらも関連してます。
Canvasでon_hoverイベント3 - C#ATIA
早い話が、くっ付けました。
# python using-flet import flet as ft import flet.canvas as cv import math def main(page: ft.Page): canvasWidth = 600 canvasHeight = 600 stroke_paint = ft.Paint(stroke_width=5, style=ft.PaintingStyle.STROKE) line_paint = ft.Paint(stroke_width=1, style=ft.PaintingStyle.STROKE) fill_paint = ft.Paint(style=ft.PaintingStyle.FILL, color=ft.colors.BLACK) def on_hover(e: ft.DragStartEvent) -> None: x=e.local_x-(canvasWidth*0.5) y=(e.local_y-(canvasHeight*0.5))*-1 shapes = [s for s in canvas.shapes if isinstance(s, cv.Circle)] change_color(shapes, e.local_x, e.local_y) pos.value = f"{x},{y}" pos.update() def on_exit(e: ft.DragStartEvent) -> None: pos.value = "-" pos.update() def is_hover(shape, x, y) -> None: return math.sqrt( (shape.x - x)*(shape.x - x) + (shape.y - y)*(shape.y - y) ) < shape.radius def change_color(shapes, x, y) -> None: for shape in reversed(shapes): if is_hover(shape, x, y): shape.paint.color = ft.colors.RED elif shape.paint.color != ft.colors.BLACK: shape.paint.color = ft.colors.BLACK shape.update() def create_circle(e: ft.DragStartEvent) -> None: canvas.shapes = canvas.shapes[:3] canvas.update() lst = e.control.value.split("\n") for txt in lst: info = txt.split(",") if len(info) < 3: continue if not all([is_float(v) for v in info]): continue canvas.shapes.append( cv.Circle( x=float(info[0])+(canvasWidth*0.5), y=(float(info[1])*-1)+(canvasHeight*0.5), radius=float(info[2])*0.5, paint=fill_paint, ) ) canvas.update() def is_float(value) -> bool: try: float(value) return True except: return False gd = ft.GestureDetector( hover_interval=10, on_hover=on_hover, on_exit=on_exit, ) canvas = cv.Canvas( [ cv.Rect(0,0,canvasWidth,canvasHeight,10,stroke_paint), cv.Line(canvasWidth*0.5,0,canvasWidth*0.5,canvasHeight,line_paint), cv.Line(0,canvasHeight*0.5,canvasWidth,canvasHeight*0.5,line_paint), ], width=canvasWidth, height=canvasHeight, content=gd, ) pos = ft.Text( "-", size=30, ) view1: ft.View = ft.View( "/", [ ft.Text(), ft.ElevatedButton( "Go to canvas", on_click=lambda _: page.go("/canvas")), ] ) view2: ft.View = ft.View( "/canvas", [ ft.Row( controls=[ canvas, ft.Column( controls=[ ft.Container( bgcolor=ft.colors.BLUE_100, alignment=ft.alignment.top_center, width=200, content=pos ), ft.TextField( multiline=True, max_lines=10, on_change=create_circle, ), ft.ElevatedButton( "Go to Home", on_click=lambda _: page.go("/") ), ] ), ] ), ] ) def route_change(route): page.views.clear() page.views.append(view1) if page.route == "/canvas": # to canvas page.views.append(view2) else: # to home view1.controls[0].value = view2.controls[0].controls[1].controls[1].value page.update() def view_pop(view): page.views.pop() top_view = page.views[-1] page.go(top_view.route) page.on_route_change = route_change page.on_view_pop = view_pop page.theme_mode = ft.ThemeMode.LIGHT page.title = "Routing Test" page.views.clear() page.go(page.route) if __name__ == "__main__": ft.app(target=main)
起動時はこんな感じです。
ボタンの上にはft.Textが配置されていますが、文字が空の為見ええません。
ボタンを押した際は、例のcanvasが表示されます。
適当に円を設定し、元のビューに戻ります。
canvas側の文字が反映されます。
異なるビューでのデータ受け渡しも出来ました。