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

Kivy框架中如何实现控件从触摸触发到离开期间持续调用函数

实现方案

步骤1:修改Python逻辑代码

首先导入Kivy的时钟调度模块,新增长按重复执行的控制逻辑,移除原函数内的阻塞sleep:

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock # 新增导入时钟模块
import socket

kivy.require("1.9.0")

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

class MyRoot(BoxLayout):
    def __init__(self):
        self.command = ""
        self.vol = 0
        self.scheduled_task = None # 存储当前正在执行的定时任务
        super(MyRoot, self).__init__()

    # 新增:启动重复执行
    def start_repeat(self, func, interval, *args):
        # 先停止之前可能存在的任务,避免冲突
        self.stop_repeat()
        # 定时每隔interval秒执行一次func
        self.scheduled_task = Clock.schedule_interval(lambda dt: func(), interval)

    # 新增:停止重复执行
    def stop_repeat(self):
        if self.scheduled_task is not None:
            self.scheduled_task.cancel()
            self.scheduled_task = None

    def shutdown(self):
        self.command = "shutdown"
        self.send_message()

    def tangAmLuong(self):
        self.command = "tang_am_luong"
        self.send_message()
        if self.vol <= 98:
            self.vol += 2
            self.volume_text.text = str(self.vol)
        # 移除原来的time.sleep(0.1),用Clock的间隔控制执行频率

    def giamAmLuong(self):
        self.command = "giam_am_luong"
        self.send_message()
        if self.vol >= 2:
            self.vol -= 2
            self.volume_text.text = str(self.vol)
        # 移除原来的time.sleep(0.1)

    def trai(self):
        self.command = "sang_trai"
        self.send_message()

    def phai(self):
        self.command = "sang_phai"
        self.send_message()

    def len(self):
        self.command = "len"
        self.send_message()

    def xuong(self):
        self.command = "xuong"
        self.send_message()

    def chuot_trai(self):
        self.command = "chuot_trai"
        self.send_message()

    def chuot_phai(self):
        self.command = "chuot_phai"
        self.send_message()

    def send_message(self):
        client.send(f"{self.nickname_text.text}: {self.command}".encode("utf-8"))

    def connect_to_server(self):
        if self.nickname_text != "":
            client.connect((self.ip_text.text, 9999))
            self.send_message()

class style(App):
    def build(self):
        return MyRoot()

webChat = style()
webChat.run()

步骤2:修改KV布局文件

给需要长按持续触发的按钮新增on_release事件,修改on_press事件绑定启动重复执行的逻辑,按需设置执行间隔(示例里设为0.1秒,可自行调整):

ip_text: ip_text
nickname_text: nickname_text
connect_btn: connect_btn
connection_grid: connection_grid
shutdown_btn: shutdown_btn
tangal_btn: tangal_btn
giamal_btn: giamal_btn
volume_text: volume_text

orientation: 'vertical'

GridLayout:
    id: connection_grid
    rows: 1
    cols: 2
    padding: 10
    spacing: 10
    height: 125
    size_hint: (1, None)
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: "Server IP"
            font_size: 42
            color: 0.92, 0.45, 0, 1
        TextInput:
            id: ip_text
            size_hint: (1, None)
            height: 50
            font_size: 36
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: "Nickname"
            font_size: 42
            color: 0.92, 0.45, 0, 1
        TextInput:
            id: nickname_text
            size_hint: (1, None)
            height: 50
            font_size: 36
Button:
    id: connect_btn
    text: "Connect"
    font_size: 32
    size: 100, 50
    size_hint: (1, None)
    height: 50
    on_press: root.connect_to_server()
Button:
    id: shutdown_btn
    text: "Tắt máy"
    font_size: 32
    size: 100, 50
    size_hint: (1, None)
    height: 50
    on_press: root.shutdown()
Button:
    id: tangal_btn
    text: "Tăng âm lương"
    font_size: 32
    size: 100, 50
    size_hint: (1, None)
    height: 50
    on_press: root.start_repeat(root.tangAmLuong, 0.1)
    on_release: root.stop_repeat()
Button:
    id: giamal_btn
    text: "Giảm âm lượng"
    font_size: 32
    size: 100, 50
    size_hint: (1, None)
    height: 50
    on_press: root.start_repeat(root.giamAmLuong, 0.1)
    on_release: root.stop_repeat()
Label:
    id: volume_text
    text: "0"
    font_size: 36
GridLayout:
    rows: 3
    cols: 3
    Button:
        text: "Chuột Trái"
        font_size: 14
        on_press: root.chuot_trai()
    Button:
        text: "Lên"
        font_size: 14
        on_press: root.start_repeat(root.len, 0.05) # 鼠标移动可以设置更短的间隔更跟手
        on_release: root.stop_repeat()
    Button:
        text: "Chuột Phải"
        font_size: 14
        on_press: root.chuot_phai()
    Button:
        text: "Trái"
        font_size: 14
        on_press: root.start_repeat(root.trai, 0.05)
        on_release: root.stop_repeat()
    Label:
        text: ""
        font_size: 14
    Button:
        text: "Phải"
        font_size: 14
        on_press: root.start_repeat(root.phai, 0.05)
        on_release: root.stop_repeat()
    Label:
        text: ""
        font_size: 14
    Button:
        text: "Xuống"
        font_size: 14
        on_press: root.start_repeat(root.xuong, 0.05)
        on_release: root.stop_repeat()
    Label:
        text: ""
        font_size: 14

注意事项

  • 执行间隔可根据需求调整,数值越小触发频率越高
  • 不要在被调度的功能函数里加time.sleep(),会阻塞Kivy主线程导致界面卡顿
  • 如果需要支持多点触摸同时触发多个按钮,可以把self.scheduled_task改成字典,按按钮ID存储不同的调度任务即可

内容的提问来源于stack exchange,提问作者Hùng Nguyễn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:45:07