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

如何在Kivy中重写on_touch_down后恢复按钮的on_press点击功能

问题原因

Kivy的触摸事件遵循冒泡分发规则,你重写了Touch控件的三个触摸事件方法后,没有对触摸位置做判断,所有触摸事件都直接被绘图逻辑拦截,没有传递给作为子控件的按钮,因此按钮的点击事件完全失效。

修复步骤

  1. 在三个触摸事件方法开头增加子控件碰撞判断:如果触摸点落在任意子控件(即你的功能按钮)上,就调用父类方法将事件分发给子控件,不执行绘图逻辑
  2. 补全KV文件中矩形按钮缺失的on_press属性,不然切换矩形工具的逻辑不会生效

修改后的完整代码

Python文件代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.graphics import Line
from kivy.graphics import Color
from kivy.lang import Builder
from kivy.core.window import Window

Builder.load_file("main.kv")

class Touch(Widget):
    def __init__(self, **kwargs):
        super(Touch, self).__init__(**kwargs)
        self.active_tool = "Line"
        with self.canvas:
            Color(0, 0, 0, 1, mode="rgba")
            self.lines = [Line(points = [0, 0, 0, 0], width = 2)]
            self.rectangles = [Line(points = [0, 0, 0, 0, 0, 0, 0, 0], width = 2)]
            
    def on_touch_down(self, touch):
        # 判断触摸是否在子控件上
        for child in self.children:
            if child.collide_point(*touch.pos):
                return super().on_touch_down(touch)
        if self.active_tool == "Line":
            self.lines[-1].points = [touch.x, touch.y]
        elif self.active_tool == "Rectangle":
            self.rectangles[-1].points = [touch.x, touch.y]
        return True
    
    def on_touch_move(self, touch):
        # 判断触摸是否在子控件上
        for child in self.children:
            if child.collide_point(*touch.pos):
                return super().on_touch_move(touch)
        if self.active_tool == "Line":
            self.lines[-1].points = [self.lines[-1].points[0], self.lines[-1].points[1], touch.x, touch.y]
        elif self.active_tool == "Rectangle":
            self.rectangles[-1].points = [self.rectangles[-1].points[0], self.rectangles[-1].points[1], touch.x, self.rectangles[-1].points[1], touch.x, touch.y, self.rectangles[-1].points[0], touch.y, self.rectangles[-1].points[0], self.rectangles[-1].points[1]]
        return True
    
    def on_touch_up(self, touch):
        # 判断触摸是否在子控件上
        for child in self.children:
            if child.collide_point(*touch.pos):
                return super().on_touch_up(touch)
        if self.active_tool == "Line":
            with self.canvas:
                Color(0, 0, 0, 1, mode="rgba")
                self.lines.append(Line(points = [0, 0, 0, 0], width = 2))
        elif self.active_tool == "Rectangle":
            with self.canvas:
                self.rectangles.append(Line(points = [0, 0, 0, 0, 0, 0, 0, 0], width = 2))
        return True

class DrawingApp(App):
    def build(self):
        return Touch()


if __name__ == "__main__":
    DrawingApp().run()

KV文件代码

<CustButton@Button>:
    color: 0, 0, 0, 1
    size: 40, 40
    background_color: .88, .88, .88, 1

<Touch>
    canvas.before:
        Color:
            rgba: (1, 1, 1, 1)
        Rectangle:
            pos: self.pos
            size: self.size

    CustButton:
        pos: root.x, root.height - 50
        background_normal: "img/straight_line_icon.png"
        on_press: root.active_tool = "Line"

    CustButton:
        pos: root.x, root.height - 100
        background_normal: "img/rectangle_icon.png"
        on_press: root.active_tool = "Rectangle" # 补全矩形按钮的点击逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:42:02