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

Kivy Python中添加DrawingWidget至现有代码后无法绘图的问题

问题解决:Kivy中DrawingWidget嵌套后无法绘图的问题

问题根源

你的DrawingWidget无法绘图的核心原因是KV文件中给DrawingWidget添加了多余的BoxLayout:这个BoxLayout会覆盖在DrawingWidget的画布之上,拦截所有触摸事件,导致on_touch_down和on_touch_move方法无法触发。同时这个BoxLayout设置了固定高度50,也限制了绘图区域的有效大小。

另外,MyGridLayout中承载DrawingWidget的GridLayout没有设置合适的尺寸参数,导致绘图区域被压缩,进一步影响交互。

修改方案

1. 修正KV文件

移除DrawingWidget内部的BoxLayout,并调整布局参数让绘图区域有足够空间:

<MyGridLayout>:
    ScrollView:
        size: root.width, root.height
        GridLayout:
            cols:1
            padding:9,9,9,9
            size_hint_y: None
            height: self.minimum_height
          
            GridLayout:
                cols:3
                size_hint_y:.5
                height: 100
                Label:
                Button:
                    text:'Enter Activity'
                    on_press:root.sendmatt()
                    size_hint_x:3
                    size_hint_y:1
                Label:
            GridLayout:
                cols:1
                size_hint_y: 2
                height: 400
                DrawingWidget:
                    size_hint: 1, 1

<DrawingWidget>:
    # 移除多余的BoxLayout,保留画布逻辑即可

2. 调整Python代码逻辑

补充按钮点击方法并优化触摸事件处理逻辑:

class MyGridLayout(Widget):
    def __init__(self, **kwargs):
        super(MyGridLayout, self).__init__(**kwargs)
    
    def sendmatt(self):
        print("Button pressed")

class DrawingWidget(Widget):
    def __init__(self, **kwargs):
        super(DrawingWidget, self).__init__(**kwargs)

        with self.canvas:
            Color(1, 1, 1, 1)
            self.rect = Rectangle(size=self.size, pos=self.pos)
        self.bind(pos=self.update_rectangle, size=self.update_rectangle)

    def update_rectangle(self, instance, value):
        self.rect.pos = self.pos
        self.rect.size = self.size

    def on_touch_down(self, touch):
        if not self.collide_point(*touch.pos):
            return False

        with self.canvas:
            Color(0, 0, 0, 1)
            self.line = Line(points=[touch.pos[0], touch.pos[1]], width=2)
        return True

    def on_touch_move(self, touch):
        if not self.collide_point(*touch.pos):
            return False

        if hasattr(self, 'line'):
            self.line.points.extend([touch.pos[0], touch.pos[1]])
        return True

    def on_touch_up(self, touch):
        if not self.collide_point(*touch.pos):
            return False
        return True

class funcswspinnerall(App):
    def build(self):
        return MyGridLayout()

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

关键说明

  • 移除DrawingWidget内的BoxLayout后,触摸事件能直接传递到DrawingWidget的触摸处理方法,确保绘图逻辑正常触发。
  • 设置DrawingWidget的size_hint:1,1让它占满父容器,保证绘图区域足够大。
  • 在触摸处理方法中返回True,明确标记事件已被处理,避免事件继续向下传递导致干扰。

内容的提问来源于stack exchange,提问作者Michael McCone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 05:40:30