我正在使用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
答案 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)
,您将看到差异。
通常,使用2个参数(对象和属性的新值)调用属性回调,并使用一个参数(对象)调用事件回调。
替换:
up_button = ObjectProperty(Button)
down_button = ObjectProperty(Button)
使用:
up_button = ObjectProperty(None)
down_button = ObjectProperty(None)
<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))
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()
#: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