kivy bind()只需2个位置参数(给定0)

时间:2018-05-10 09:30:50

标签: python kivy kivy-language

我正在使用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

1 个答案:

答案 0 :(得分:0)

参考原始代码,您将遇到以下错误。

错误

         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文件 - Hookup ObjectProperties

<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

输出

enter image description here