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

Kivy+Python开发中无法获取自定义LongTouchButton按钮id求助

Kivy自定义按钮获取id的解决方案

错误原因说明

  • Kivy 中ids是父控件的属性,存储的是父控件下所有子控件的id映射,你在LongTouchButton实例内部调用self.ids,拿到的是按钮自身内部子控件的id集合,并不是你在KV文件中给按钮设置的bt1/bt2标识
  • 你代码中两个按钮的text属性均设置为"self.id",且你尝试访问的self.ids.bt1并不存在于按钮的内部id集合中,所以判断逻辑失效
  • self.ids是字典类型,直接和字符串"bt2"对比类型不匹配,永远返回False

最优解决方案:给按钮添加自定义标识属性

这是耦合度最低、实现最简单的方案,步骤如下:

1. 修改Python代码,给自定义按钮类添加标识属性

from kivymd.uix.behaviors import TouchBehavior
from kivymd.uix.button import MDIconButton
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.core.window import Window
from kivymd.app import MDApp

class MainApp(MDApp):   
    def __init__(self, **kwargs):
        super().__init__(**kwargs)          
        self.kv =Builder.load_file('kv file') # 替换为你的kv文件实际路径
        Window.maximize() # 窗口初始尺寸
        
    def build(self):
        return self.kv

class LongTouchButton(MDIconButton, TouchBehavior): 
    # 自定义属性,用来存储按钮的唯一标识
    btn_id = ""
    def __init__(self,**kwargs):
        super().__init__(**kwargs)
        self.duration_long_touch = 2    # 长按功能触发时长

    def on_long_touch(self,*args):
        # 直接通过self.btn_id区分触发长按的按钮
        print(f"长按触发,按钮id:{self.btn_id}")
        self.m = True
        self.while_long()

    def on_release(self, *args):
        self.m = False

    def while_long(self, *args):
        if self.m:
            print(f"LOOP! 来自按钮:{self.btn_id}")
            Clock.schedule_once(self.while_long, .5)
    
    def prints(self,*args):
        # 按自定义标识判断执行对应逻辑
        if self.btn_id == "bt1":         
            print("BUTTON 1 IS PRESSED")
            # 执行function1
        elif self.btn_id == "bt2":                  
            print("BUTTON 2 IS PRESSED")
            # 执行function2

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

2. 修改KV文件,给每个按钮赋值自定义标识

FloatLayout:
    orientation: "vertical"
    MDToolbar:
        title: "ACESS TO ID WITH PROBLEM"
        text_color: app.theme_cls.primary_color
        md_bg_color: 0, 0.3, 0.6, 1
        
    MDFloatLayout:              
        LongTouchButton:
            id: bt1
            btn_id: "bt1" # 和你要的标识保持一致即可
            text: "bt1"
            user_font_size : 80
            pos_hint: {"center_x": .3, "center_y": .5}
            on_press: self.prints()
        
        LongTouchButton:
            id: bt2
            btn_id: "bt2" # 和你要的标识保持一致即可
            text: "bt2"
            user_font_size : 80
            pos_hint: {"center_x": .7, "center_y": .5}
            on_press: self.prints()

可选替代方案:通过父布局id对比

如果不想加自定义属性,也可以直接和父布局存储的控件实例对比,判断逻辑如下:

from kivymd.app import App

def prints(self,*args):
    root = App.get_running_app().root
    if self == root.ids['bt1']:
        print("BUTTON 1 IS PRESSED")
    elif self == root.ids['bt2']:
        print("BUTTON 2 IS PRESSED")

这种方法不需要修改KV文件,但耦合度较高,父布局层级变更后需要同步修改代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:06:11