Flet CanvasResizeEvent 详解:监听 Canvas 尺寸变化并实现响应式图形重绘
前端跨平台桌面应用移动开发【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址https://gitcode.com/gh_mirrors/fl/flet点击查看免费下载导读CanvasResizeEvent是 Flet 画布Canvas在渲染尺寸发生变化时派发的事件对象它承载画布最新的宽高数据单位为逻辑像素通过Canvas.on_resize回调传递给 Python 侧开发者。本文将以 canvasresizeevent.md 为主题结合源码与官方示例完整讲解该事件的字段语义、底层触发链路Python ↔ Flutter、resize_interval采样节流机制以及如何用它写出随窗口缩放自动重绘的响应式绘图程序。一、事件定义CanvasResizeEvent 是什么CanvasResizeEvent定义在 canvas.py它是一个继承自Event[Canvas]的dataclass源码 docstring 明确说明Event emitted when aCanvasreports a new rendered size. This event is delivered throughCanvas.on_resizeand carries the latest measured dimensions in logical pixels.即当画布实际渲染出来的尺寸发生变化时触发事件中携带的是逻辑像素logical pixels下的最新宽高与设备像素比pixel ratio无关。字段一览字段类型序列化键data_field含义widthfloatw画布新的宽度逻辑像素heightfloath画布新的高度逻辑像素注意data_field元数据Python 侧字段名为width/height而在底层事件通道Flutter → Python中对应的键是w/h。这一点在 Dart 端有直接印证——canvas.dart 触发事件时发送的正是{w: size.width, h: size.height}随后由事件解析层依据data_field反序列化填充为CanvasResizeEvent.width与height。导出路径CanvasResizeEvent与Canvas一起通过以下路径对外公开因此业务代码中最常见的导入方式是import flet.canvas as cv # cv.CanvasResizeEvent也可直接使用flet.canvas.CanvasResizeEvent。其导出位置可见 flet/canvas/init.py 中的__all__列表。二、事件从何而来Canvas.on_resize 与 resize_intervalCanvasResizeEvent不会凭空产生它由Canvas控件的on_resize事件处理器派发。在 canvas.py 中与尺寸变化相关的有两个关键成员resize_interval: Number 10 Sampling interval in milliseconds for on_resize event. Setting to 0 calls :attr:on_resize immediately on every change. on_resize: Optional[EventHandler[CanvasResizeEvent]] None Called when the size of this canvas has changed. on_resize类型为EventHandler[CanvasResizeEvent]回调签名即为(e: CanvasResizeEvent) - None。当画布尺寸变化时被调用。resize_interval采样间隔单位毫秒默认 10。这是事件触发的节流throttle参数——即使底层渲染在连续变化on_resize最多每resize_interval毫秒派发一次避免高频重绘导致 Python 侧回调风暴。设置为0则禁用节流尺寸每次变化都会立即触发。底层触发链路源码印证从 Flutter 侧实现可以完整还原事件产生的过程。在 canvas.dart 的build方法中var resizeInterval widget.control.getInt(resize_interval, 10)!;Dart 端读取resize_interval默认 10随后在自定义画笔FletCustomPainter的onPaintCallback回调中检测尺寸变化onPaintCallback: (size) { var now DateTime.now().millisecondsSinceEpoch; if ((now - _lastResize resizeInterval _lastSize ! size) || _lastSize.isEmpty) { _lastSize size; _lastResize now; widget.control .triggerEvent(resize, {w: size.width, h: size.height}); } },这段代码清晰地揭示了三个事实测量时机尺寸在每次绘制paint时被重新测量因此能实时反映窗口缩放、布局变化带来的实际渲染尺寸。节流逻辑只有「距上次派发超过resize_interval毫秒」且「尺寸确实与上次不同」或首次绘制时才触发resize事件Payload 为{w: ..., h: ...}。通道对接事件名resize与 Python 侧on_resize对应Payload 键w/h与CanvasResizeEvent字段的data_field一一对应完成跨端数据还原。三、官方示例随窗口缩放重绘对角线仓库自带了完整可运行的官方示例 resize/main.py演示了「监听画布尺寸变化 → 动态更新图形坐标」的标准写法import flet as ft import flet.canvas as cv def main(page: ft.Page): def paint_resize(e: cv.CanvasResizeEvent): print(On resize:, e.width, e.height) canvas.shapes[0].x2 e.width canvas.shapes[0].y2 e.height canvas.shapes[1].y1 e.height canvas.shapes[1].x2 e.width canvas.update() page.add( ft.SafeArea( expandTrue, contentft.Container( widthfloat(inf), expandTrue, content( canvas : cv.Canvas( resize_interval10, on_resizepaint_resize, shapes[ cv.Line(x10, y10, x2100, y2100), cv.Line(x10, y1100, x2100, y20), ], ) ), ), ) ) if __name__ __main__: ft.run(main)拆解其中的关键设计事件处理器签名paint_resize(e: cv.CanvasResizeEvent)接收类型化的事件对象直接读取e.width、e.height获得画布当前宽高。画布必须可伸展Container使用widthfloat(inf)配合expandTrueSafeArea同样expandTrue使 Canvas 随页面/窗口尺寸变化。从源码看Canvas.before_update()在expandTrue且未显式设置width/height时会自动填充无穷大值见 canvas.py从而铺满可用空间——这正是画布「能被 resize」的前提。响应式更新图形两条对角线的端点坐标被动态改写为画布边界如第一条线终点(e.width, e.height)随后调用canvas.update()将新坐标同步回 Flutter 端重绘。窗口拉大时对角线随之延伸实现视觉上的「画布跟随窗口缩放」。节流参数resize_interval10与默认值一致实际运行时可尝试调大如 100/200观察回调频率变化或设为0观察无节流时的即时触发。该示例在 pyproject.toml 中被登记为官方 Gallery 示例title Canvas resize、features [on_resize event, responsive line drawing]可作为新建应用时的最小模板参考。四、事件对象继承能力Event 基类CanvasResizeEvent继承自泛型基类Event[Canvas]定义于 control_event.py因此事件处理器中除了e.width/e.height还可以访问以下通用成员成员类型说明e.namestr事件名称此处为resizee.dataAny原始事件载荷dict或str未解析前的原始数据e.controlCanvas派发该事件的画布控件实例可直接访问并修改其属性e.pagePage事件源控件所属的页面若控件未挂载到页面会抛出RuntimeErrore.targetint派发事件控件的内部 id借助e.control可以写出更精简的回调——例如在处理器内直接通过e.control.shapes[...]修改图形而不必依赖外部闭包变量canvas。类型化的EventHandler[CanvasResizeEvent]意味着 IDE 与类型检查器能正确推断e的类型这也是 Flet 事件系统「按控件类型解析事件载荷」机制的体现——相关解析逻辑get_event_field_type同样位于 control_event.py并在 test_events.py 中有对应的类型断言测试。五、实战场景与使用建议1. 响应式绘图最常见的用途就是本节官方示例展示的「坐标跟随画布尺寸」。适用于自适应边框、随窗口缩放的网格线、图表背景、签名板清空重绘等。核心套路固定为三步def on_canvas_resize(e: cv.CanvasResizeEvent): # 1. 根据 e.width / e.height 重新计算图形坐标 # 2. 修改 canvas.shapes 中对应 shape 的属性 # 3. 调用 canvas.update() 推送更新 pass2. 高频场景的节流取舍resize_interval的单位是毫秒默认 10ms 意味着每秒最多约 100 次回调足以保证交互流畅性。如果回调体内包含重计算如逐点重算贝塞尔曲线、遍历上千个 shape建议调大该值50–200ms如果追求极致的即时反馈如拖拽分隔条实时预览可设为0但要注意连续拖动窗口时回调可能非常密集。3. 与布局控件配合只有画布实际占据的空间发生变化事件才会派发。要让画布具备「可 resize」的布局前提通常采用外层容器expandTrue或配合widthfloat(inf)或为Canvas直接设置expandTrue或显式固定width/height后由父级布局如Column、Stack驱动尺寸变化。从源码看Canvas继承自LayoutControl本身具备布局能力且before_update()会在expandTrue时自动补全无穷大尺寸这保证了展开模式下画布能跟随父容器铺满。4. 与其他「尺寸类事件」区分需要注意CanvasResizeEvent与页面级事件如Page的on_resize对应PageResizeEvent作用对象不同前者反映单个画布控件的渲染尺寸后者反映整个页面/窗口尺寸。在test_events.py中可以看到PageResizeEvent的事件类型解析同样依赖get_event_field_type机制二者属于同一套类型化事件体系的不同实例。绘制逻辑若只关心画布本身优先使用Canvas.on_resize无需关心窗口级状态。六、小结与深入学习CanvasResizeEvent是 Flet Canvas 响应式能力的核心入口Python 侧通过Canvas.on_resize接收字段width/height序列化键w/h携带逻辑像素尺寸resize_interval控制派发频率底层由 Flutter 端在每次绘制时测量并节流触发。掌握了它即可让任何绘图应用随窗口缩放实时重绘。继续深入可参考以下仓库资源类型定义与Canvas完整成员sdk/python/packages/flet/src/flet/controls/core/canvas/canvas.py官方可运行示例sdk/python/examples/controls/core/canvas/resize/main.py底层 Flutter 实现与节流逻辑packages/flet/lib/src/controls/canvas.dart事件基类与类型解析机制sdk/python/packages/flet/src/flet/controls/control_event.py事件类型解析测试sdk/python/packages/flet/tests/test_events.pyCanvas 控件总览文档website/docs/controls/canvas/index.md赞分享前端跨平台桌面应用移动开发【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址https://gitcode.com/gh_mirrors/fl/flet点击查看免费下载相关推荐Flet ScreenBrightnessChangeEvent 详解监听并响应屏幕亮度变化事件Flet ScreenBrightnessChangeEvent 详解监听并响应屏幕亮度变化事件 导读 ScreenBrightnessChangeEvent前端跨平台桌面应用移动开发Flet 页面尺寸变化事件 PageResizeEvent 完全指南监听窗口与浏览器尺寸变更构建响应式布局Flet 页面尺寸变化事件 PageResizeEvent 完全指南监听窗口与浏览器尺寸变更构建响应式布局 PageResizeEvent 是 Flet 中前端跨平台桌面应用移动开发Vuetify v-resize 指令详解监听窗口尺寸变化并触发回调Vuetify v resize 指令详解监听窗口尺寸变化并触发回调 v resize 是 Vuetify 提供的一个 Vue 指令用于在浏览器窗口win前端UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考