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

Canvas异常行为:点击btn按钮缩放时意外改变btn1尺寸

问题分析与解决方案

首先得先修正你代码里的一个基础错误:你用了Layout这个抽象基类,它不能直接实例化,而且也没有text和orientation属性,应该换成BoxLayout才能正常运行。

接下来咱们拆解你遇到的核心问题:

1. 为什么点击btn会“改变”btn1的尺寸?

你看到的btn1尺寸变化其实是视觉错觉——btn1的实际size属性根本没动!原因是你用了BoxLayout,它会按size_hint给子控件分配空间:btn和btn1各占父容器高度的50%。当你给btn的canvas添加Scale指令后,btn的绘制内容被缩放变小,但它的布局占位尺寸还是原来的50%高度,所以看起来btn1好像“变大”了,实际上只是btn的视觉区域缩小,让出了更多空白而已。

另外你的代码还有个逻辑问题:每次点击都往canvas里新增一个Scale指令,而不是修改已有指令,这会导致缩放效果不断累积,进一步加剧视觉上的混乱。

2. 为什么canvas.before会同时影响两个按钮?

这要从Kivy的Canvas绘图机制说起:

  • canvas.before:这里的指令会在控件自身内容(比如Button的背景、文字)绘制之前执行
  • canvas:默认画布,包含控件自带的绘制内容
  • canvas.after:指令会在控件自身内容绘制之后执行

变换类指令(比如Scale)的本质是修改当前的绘图上下文矩阵,这个修改会影响后续所有的绘图操作。当你把Scale添加到btn.canvas.before时:

  1. 这个Scale会先于btn的内容执行,修改了绘图上下文的缩放比例
  2. 如果你每次点击都新增一个Scale指令,这些指令会累积起来,导致绘图上下文的缩放比例越来越小
  3. 虽然Kivy会在绘制每个控件前后保存/恢复上下文状态,但重复添加的Scale指令会打破这个逻辑,导致btn1绘制时也继承了被修改的上下文,最终看起来两个按钮都被缩放了

而canvas.after的指令是在btn自身内容绘制完成后执行的,它只会影响你在after里新增的绘图内容,不会干扰btn的默认绘制,也不会影响btn1——因为BoxLayout绘制btn1前会重置上下文状态。

3. 正确的实现方式

不要每次点击都新增Scale指令,而是在btn初始化时就创建一个Scale指令并保存引用,每次点击只修改它的缩放比例:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.graphics import Scale

class TutorialApp(App):
    def build(self):
        bl = BoxLayout(orientation='vertical')
        btn = Button(text='OK', size_hint=(1,0.5))
        btn1 = Button(text='OK1', size_hint=(1,0.5))
        
        # 在btn的canvas.before中初始化Scale指令并保存引用
        with btn.canvas.before:
            btn.scale_inst = Scale(xyz=(1, 1, 1))
        
        def btn_click(elem):
            if elem.scale_inst.x < 0.2:
                return
            new_scale = elem.scale_inst.x * 0.8
            elem.scale_inst.xyz = (new_scale, new_scale, 1)
            print(new_scale)
        
        btn.bind(on_press=btn_click)
        bl.add_widget(btn)
        bl.add_widget(btn1)
        return bl

if __name__ == '__main__':
    TutorialApp().run()

这样修改后,每次点击只会更新已有的Scale指令,不会累积新增,而且只会影响btn自身的绘制,完全不会干扰btn1的显示。

内容的提问来源于stack exchange,提问作者Александр

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:00:00