bug: ft. Container component cannot be resized
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
从提供的 BaseCanvas.expand_canvas 复现开始,检查 Flet 0.84 中 ft.Stack 内的 ft.Container 如何处理 width、height 和 update()。将其行为与报告中提到的早期 Flet 版本进行比较。完成标准是:点击 "+chicun" 后,canvas 能够明显扩展,同时保留现有的拖动和缩放行为。
由索引模型根据 Issue 内容生成。
描述
Duplicate Check
- I have searched the opened issues and there are no duplicates
Describe the bug
I originally wanted to make an infinite canvas, I have implemented the canvas drag, zoom, offset and other functions, and the last function is missing, that is, to expand the size of the canvas, but I found that when I used the method of self.canvas_container.width=xxx, I found that it was not feasible when I changed the size, why is that? , I remember that there was no bug in the previous version
Code sample
Code
import flet as ft
from typing import Any, Optional, cast, Callable
import asyncio
from dataclasses import field
@ft.control
class BaseCanvas(ft.GestureDetector):
max_scale: float = 3
scale_step: float = 0.25
min_scale: float = 0.25
def init(self):
self.cumulative_offset_x = self.cumulative_offset_y = 0
self.current_scale = 1
self.window_container_size = None
self.scaled_canvas_size = ()
self.scale_offset_x = 0
self.scale_offset_y = 0
self.canvas_container = ft.Container(
bgcolor=ft.Colors.BLUE_100,
content=ft.Stack(
controls=[
self.module_container((50, 50)),
self.module_container((50, 600)),
self.module_container((1000, 50)),
self.module_container((1000, 600)),
],
),
)
# self.content = ft.Container(
# expand=True,
# bgcolor=ft.Colors.AMBER,
# clip_behavior=ft.ClipBehavior.HARD_EDGE,
# content=self.canvas_container,
# on_size_change=lambda e: self.get_window_container_size(e),
# )
# ft.Stack
self.content = ft.Container(
expand=True,
bgcolor=ft.Colors.AMBER,
clip_behavior=ft.ClipBehavior.HARD_EDGE,
content=ft.Stack([self.canvas_container]),
on_size_change=lambda e: self.get_window_container_size(e),
)
self.on_scroll = self.canvas_zoom_event
self.on_pan_update = self.drag_canvas_event
self.on_hover = self.mouse_hover_event
def module_container(self, pos):
module = ft.Container(
bgcolor=ft.Colors.GREEN,
width=70,
content=ft.Column(
[
ft.Container(width=70, content=ft.Text(f"项目 {j}"))
for j in range(10)
]
),
)
return ft.GestureDetector(
mouse_cursor=ft.MouseCursor.MOVE,
drag_interval=5,
left=pos[0],
top=pos[1],
content=module,
)
def get_window_container_size(self, e):
self.window_container_size = (e.width, e.height)
print(self.window_container_size)
def canvas_zoom_event(self, e: ft.ScrollEvent[ft.GestureDetector]):
"""Zoom centered on mouse position"""
canvas_width, canvas_height = (
self.window_container_size if self.window_container_size else (500, 600)
)
x_center = canvas_width / 2
y_center = canvas_height / 2
x = (self.mouse_pos_canvas[0] - x_center) / x_center
y = (self.mouse_pos_canvas[1] - y_center) / y_center
if e.scroll_delta.y > 0: # zoom in
if self.current_scale + self.scale_step <= self.max_scale:
self.current_scale += self.scale_step
else:
return
else: # zoom out
if self.current_scale - self.scale_step >= self.min_scale:
self.current_scale -= self.scale_step
else:
return
self.canvas_container.scale = ft.Scale(
alignment=ft.Alignment(x, y), scale=self.current_scale
)
self.scale_offset_x = (self.current_scale - 1) * (
x_center - self.mouse_pos_canvas[0]
)
self.scale_offset_y = (self.current_scale - 1) * (
y_center - self.mouse_pos_canvas[1]
)
mouse_container_x, mouse_container_y = self.mouse_pos_container
mouse_canvas_x, mouse_canvas_y = self.mouse_pos_canvas
self.cumulative_offset_x = (
mouse_container_x - mouse_canvas_x
) / canvas_width
self.cumulative_offset_y = (
mouse_container_y - mouse_canvas_y
) / canvas_height
self.canvas_container.offset = ft.Offset(
self.cumulative_offset_x, self.cumulative_offset_y
)
self.canvas_container.update()
print(f"当前缩放级别:{self.current_scale}")
print(f"当前缩放中心:{(x, y)}")
print(f"当前缩放偏移:{self.scale_offset_x, self.scale_offset_y}")
def drag_canvas_event(self, e: ft.DragUpdateEvent[ft.GestureDetector]):
"""Handle canvas dragging, update offset"""
if e.local_delta is None:
return
self.cumulative_offset_x += (
e.local_delta.x / self.window_container_size[0]
if self.window_container_size
else 500
)
self.cumulative_offset_y += (
e.local_delta.y / self.window_container_size[1]
if self.window_container_size
else 600
)
self.canvas_top_left_pos = self.mouse_pos_convert(
(0, 0), convert_type="canvas_to_container"
)
print(f"当前画布左上角在容器中的位置:{self.canvas_top_left_pos}")
self.canvas_container.offset = ft.Offset(
self.cumulative_offset_x, self.cumulative_offset_y
)
print(f"当前偏移量:{self.cumulative_offset_x, self.cumulative_offset_y}")
self.canvas_container.update()
def mouse_hover_event(self, e: ft.HoverEvent[ft.GestureDetector]) -> None:
"""Handle mouse hover, compute canvas coordinates"""
if e.local_delta is None:
return
mouse_container_x = e.local_position.x
mouse_container_y = e.local_position.y
self.mouse_pos_container = (mouse_container_x, mouse_container_y)
self.mouse_pos_canvas = self.mouse_pos_convert(
self.mouse_pos_container, convert_type="container_to_canvas"
)
def mouse_pos_convert(self, pos, convert_type="container_to_canvas"):
x, y = pos
canvas_width, canvas_height = (
self.window_container_size if self.window_container_size else (500, 600)
)
scaled_width = float(canvas_width) * self.current_scale
scaled_height = float(canvas_height) * self.current_scale
actual_left = (
(self.cumulative_offset_x * canvas_width)
+ self.scale_offset_x
+ (canvas_width - scaled_width) / 2
)
actual_top = (
(self.cumulative_offset_y * canvas_height)
+ self.scale_offset_y
+ (canvas_height - scaled_height) / 2
)
if convert_type == "container_to_canvas":
new_x = (x - actual_left) / self.current_scale
new_y = (y - actual_top) / self.current_scale
elif convert_type == "canvas_to_container":
new_x = x * self.current_scale + actual_left
new_y = y * self.current_scale + actual_top
converted_pos = (new_x, new_y)
return converted_pos
def expand_canvas(self):
canvas_width, canvas_height = (
self.window_container_size if self.window_container_size else (500, 600)
)
self.canvas_container.width = canvas_width + 200
self.canvas_container.height = canvas_height + 200
print(f"扩张前{canvas_width, canvas_height}")
print(f"扩张后{self.canvas_container.width, self.canvas_container.height}")
self.window_container_size=(self.canvas_container.width, self.canvas_container.height)
self.canvas_container.update()
if __name__ == "__main__":
def main(page: ft.Page):
canvas = BaseCanvas()
page.add(
ft.Button("+chicun", on_click=lambda e: canvas.expand_canvas()),
ft.Container(expand=True, content=canvas),
)
ft.run(main)
To reproduce
step:
- Run the displayed code.
- Click the "+chicun" button (size expansion function).
(A screen recording of the reproduction is attached)
Expected behavior
No response
Screenshots / Videos
Captures
Operating System
Windows
Operating system details
11
Flet version
0.84
Regression
Yes, it used to work in a previous Flet version (please specify the version in additional details)
Suggestions
No response
Logs
Logs
[Paste your logs here]
Additional details
No response
- 主要语言
- Python
- 星标
- 17.4k
- 派生
- 737
- 平均合并
- 1 天 14 小时
- 30 天内合并 PR
- 62
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
flet-dev/flet 的其他 Issue
-
feature request
难度 2/5 1-3 小时 新手友好度 66/100
flet-dev/flet#6985 · 2 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
flet build: common [tool.flet.deep_linking] is ignored on Android and iOS可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭bug packaging platform: mobile
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
bug: `flet test` fails with `ModuleNotFoundError: No module named 'pydantic_core._pydantic_core'`可能已有人在做 @ndonkoHenri 于 1 天前认领。 未关闭bug
flet-dev/flet#7022 · 3 条评论 · 1 个 reaction · 已指派 1 人 ·
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 79/100
aws-samples/sample-per-model-bedrock#639 ·
维护者通常 1 天内回复
-
bug
难度 1/5 1 小时以内 新手友好度 86/100
awslabs/visual-asset-management-system#937 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 79/100
project-codeflare/codeflare-sdk#1195 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 65/100
pandas-dev/pandas-stubs#2051 ·
维护者通常 1 天内回复