【问题标题】:kivy bind() takes exactly 2 positional arguments (0 given)kivy bind() 正好采用 2 个位置参数(给定 0)
【发布时间】:2018-05-23 23:43:13
【问题描述】:

我正在使用 kivy 在 python() 中构建电梯系统 GUI。我正在编写它,以便当按下楼层的向上按钮时,将调用一个函数,该函数将生成一个请求并将其发送到系统。我现在正在尝试使用以下方法将该功能绑定到向上按钮:

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

编译器给我发了一个错误:

TypeError: bind() takes exactly 2 positional arguments (0 given)

有解决办法吗? Python初学者,如果这是一个非常简单的问题,请道歉。

下面是.py文件中的相关代码:

from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from random import randint

class FloorRequestStatus:
    up = 0
    down = 1

class Request:
    def __init__(self, start, status, destination, waiting_time):
        self.start = start
        self.status = status
        self.destination = destination
        self.waiting_time = waiting_time

class Floor(GridLayout):
    up_count = NumericProperty(0)
    down_count = NumericProperty(0)
    floor_index = NumericProperty(0)

    up_button = ObjectProperty(Button)
    down_button = ObjectProperty(Button)

class FloorSystem(BoxLayout):
    floor1 = ObjectProperty(Floor)  # type:Floor
    floor2 = ObjectProperty()
    floor3 = ObjectProperty()
    floor4 = ObjectProperty()

    floors = [floor1, floor2, floor3, floor4]

    request_queue = []

    def __init__(self, **kwargs):
        super(FloorSystem, self).__init__(**kwargs)
        self.floor1.up_button.bind(on_press=self.up_pressed(1))

    def generate_destination(self, floor_index, status):
        if status == FloorRequestStatus.up:
            return randint(floor_index + 1, 20)
        if status == FloorRequestStatus.down:
            return randint(0, floor_index - 1)

    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)

这些是.kv文件中的相关代码:

#:kivy 1.0.9

<Floor@GridLayout>
    floor_index: 0
    pos: 200,200
    rows: 1
    spacing: 1

    GridLayout:
        size_hint_x: 35
        cols: 1

        Button:
            id: up_button
            size_hint_y: 50
            text: 'up'
            on_press: root.up_count += 1

        Button:
            id:down_button
            size_hint_y: 50
            text: 'down'
            on_press: root.down_count += 1

    Label:
        id: floor_label
        size_hint_x: 65
        text: root.label_text
        background_color: 1,1,1,1
        text: str(root.floor_index) + 'F (' + str(root.up_count) + ',' + str(root.down_count) + ')'

        canvas:
            Color:
                rgba: .3, .5, 1, .4
            Rectangle:
                size: self.size
                pos: self.pos

<FloorSystem>
    floor1: floor1
    floor2: floor2
    floor3: floor3
    floor4: floor4

    orientation: 'vertical'
    size_hint: None, None
    width: 160
    height: 700
    spacing: 2

    Floor:
        id: floor4
        floor_index: 4

    Floor:
        id: floor3
        floor_index: 3

    Floor:
        id: floor2
        floor_index: 2

    Floor:
        id: floor1
        floor_index: 1

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    参考原代码会遇到如下错误。

    错误

             self.floor1.up_button.bind(on_press=self.up_pressed(1))
         TypeError: descriptor 'bind' of 'kivy._event.EventDispatcher' object needs an argument
    

    说明

    发生上述错误是因为 up_button 连接到 Button 类 而没有连接到 Button 对象。如果您将打印语句 print(self.floor1.up_button) 插入您的程序中,您将看到不同之处。

    Event dispatcher

    通常,属性回调使用 2 个参数(对象和属性的新值)调用,事件回调使用一个参数(对象)。

    解决方案

    Python 脚本 - 删除按钮

    替换:

    up_button = ObjectProperty(Button)
    down_button = ObjectProperty(Button)
    

    与:

    up_button = ObjectProperty(None)
    down_button = ObjectProperty(None)
    

    kv 文件 - 连接对象属性

    <Floor@GridLayout>
        up_button: up_button
        down_button: down_button
    
        floor_index: 0
        ...
    

    按钮绑定

    至于绑定,可以使用偏函数。

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

    示例

    main.py

    ​​>
    from kivy.uix.label import Label
    from kivy.uix.button import Button
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.gridlayout import GridLayout
    from kivy.properties import ObjectProperty, NumericProperty
    from random import randint
    from functools import partial
    
    
    class FloorRequestStatus:
        up = 0
        down = 1
    
    
    class Request:
        def __init__(self, start, status, destination, waiting_time):
            self.start = start
            self.status = status
            self.destination = destination
            self.waiting_time = waiting_time
    
    
    class Floor(GridLayout):
        up_count = NumericProperty(0)
        down_count = NumericProperty(0)
        floor_index = NumericProperty(0)
    
        up_button = ObjectProperty(None)
        down_button = ObjectProperty(None)
    
    
    class FloorSystem(BoxLayout):
        floor1 = ObjectProperty(None)
        floor2 = ObjectProperty(None)
        floor3 = ObjectProperty(None)
        floor4 = ObjectProperty(None)
    
        floors = [floor1, floor2, floor3, floor4]
    
        request_queue = []
    
        def __init__(self, **kwargs):
            super(FloorSystem, self).__init__(**kwargs)
            self.floor1.up_button.bind(on_press=partial(self.up_pressed, 1))
    
        def generate_destination(self, floor_index, status):
            if status == FloorRequestStatus.up:
                return randint(floor_index + 1, 20)
            if status == FloorRequestStatus.down:
                return randint(0, floor_index - 1)
    
        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)
    
    
    class TestApp(App):
        def build(self):
            return FloorSystem()
    
    
    if __name__ == "__main__":
        TestApp().run()
    

    test.kv

    #:kivy 1.10.0
    
    <Floor@GridLayout>
        up_button: up_button
        down_button: down_button
    
        floor_index: 0
        pos: 200,200
        rows: 1
        spacing: 1
    
        GridLayout:
            size_hint_x: 35
            cols: 1
    
            Button:
                id: up_button
                size_hint_y: 50
                text: 'up'
                on_press: root.up_count += 1
    
            Button:
                id:down_button
                size_hint_y: 50
                text: 'down'
                on_press: root.down_count += 1
    
        Label:
            id: floor_label
            size_hint_x: 65
            text: root.label_text
            background_color: 1,1,1,1
            text: str(root.floor_index) + 'F (' + str(root.up_count) + ',' + str(root.down_count) + ')'
    
            canvas:
                Color:
                    rgba: .3, .5, 1, .4
                Rectangle:
                    size: self.size
                    pos: self.pos
    
    <FloorSystem>
        floor1: floor1
        floor2: floor2
        floor3: floor3
        floor4: floor4
    
        orientation: 'vertical'
        size_hint: None, None
        width: 160
        height: 700
        spacing: 2
    
        Floor:
            id: floor4
            floor_index: 4
    
        Floor:
            id: floor3
            floor_index: 3
    
        Floor:
            id: floor2
            floor_index: 2
    
        Floor:
            id: floor1
            floor_index: 1
    

    输出

    【讨论】:

    • 谢谢!一个非常详细的解释。实际上还有一个错误,我在创建 floor1 时使用 Floor 类而不是 Floor 对象,即 ObjectProperty。
    • @GaryYuan:不客气。不需要在 `floor1 = ObjectProperty(Floor())' 中实例化 Floor,因为 ObjectProperty floor1 已经连接到实例化的子小部件 floor1 kv 文件 中。因此,该程序可以正常工作并且没有引发错误。我已删除 Floor() 以避免混淆。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多