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

Kivy开发电梯GUI时bind()函数参数异常的解决方法求助

Fixing Kivy Button Binding Error in Your Elevator GUI

Hey there! Let's break down why that TypeError is popping up and get your elevator request system working smoothly.

The Root Cause of the Error

When you wrote:

self.floor1.up_button.bind(on_press=self.up_pressed(1))

You’re immediately calling the up_pressed(1) function instead of passing the function itself to bind(). This returns None (since your function has no return statement), and bind() gets confused because it expects a callable function, not None. On top of that, Kivy’s on_press callback automatically passes the pressed button instance as the first argument to your function—your current up_pressed doesn’t account for this extra parameter.

This is the cleanest way to pass extra arguments to your callback function. Here’s how to adjust your code:

  1. First, import partial from functools at the top of your .py file:
from functools import partial
  1. Update the up_pressed function to accept the button instance (even if you don’t use it):
def up_pressed(self, floor_index, instance):
    # 'instance' is the button that was pressed; we don't need it here but must accept it
    a_request = Request(
        floor_index, 
        FloorRequestStatus.up, 
        self.generate_destination(floor_index, FloorRequestStatus.up), 
        0
    )
    self.request_queue.append(a_request)
    print(f"Up request added from floor {floor_index}")  # Optional: Verify the request works
  1. Fix the binding in your __init__ method:
def __init__(self, **kwargs):
    super(FloorSystem, self).__init__(**kwargs)
    # Fix the floors list to use instance attributes (not class attributes)
    self.floors = [self.floor1, self.floor2, self.floor3, self.floor4]
    # Use partial to bind the floor index to up_pressed
    self.floor1.up_button.bind(on_press=partial(self.up_pressed, 1))
    
    # Bonus: Loop to bind all floors at once (avoids repetitive code)
    # for floor_num, floor in enumerate(self.floors, start=1):
    #     floor.up_button.bind(on_press=partial(self.up_pressed, floor_num))

Solution 2: Use a Lambda Function

If you don’t want to import functools, a lambda can wrap your function call for simple cases:

def __init__(self, **kwargs):
    super(FloorSystem, self).__init__(**kwargs)
    self.floors = [self.floor1, self.floor2, self.floor3, self.floor4]
    # Lambda captures the button instance and calls up_pressed with the floor index
    self.floor1.up_button.bind(on_press=lambda btn: self.up_pressed(1))

Then adjust up_pressed to skip the instance parameter:

def up_pressed(self, floor_index):
    a_request = Request(
        floor_index, 
        FloorRequestStatus.up, 
        self.generate_destination(floor_index, FloorRequestStatus.up), 
        0
    )
    self.request_queue.append(a_request)

Quick Additional Fixes

  • In your Floor class, set up_button = ObjectProperty(None) instead of ObjectProperty(Button)—Kivy will automatically assign the button with id: up_button from your .kv file to this property.
  • The floors list in FloorSystem was defined as a class attribute, which won’t work correctly with instance-specific floor1/floor2 etc. Move it inside __init__ as shown above to use instance attributes.

Testing the Fix

Run your app again, press the floor 1 up button, and check the request_queue—it should now add a new Request object each time the button is pressed.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:01:13