Clock.unschedule 在 kivy 中使用 bind() 引用时不起作用
Clock.unschedule not working when referenced with bind() in kivy
我正在为 android 使用 kivy 制作一款游戏,玩家可以通过触摸屏幕上的特定区域来控制。我创建了不可见的按钮 (char_controls),当按下该按钮时,角色会移动。松开手指的那一刻,我希望角色停止。
我已经为每个按钮绑定了一个函数,该函数在字符 class 中的 move_up 函数上调用 Clock.schedule_interval(现在只能使用向上按钮)。释放按钮时,它会调用另一个函数,该函数应该取消对原始函数的调度(Clock.unschedule)。然而,它并没有这样做,角色继续移动。
当我使用 kivy 的 bind() 函数将按钮的 on_press 和 on_release 行为绑定到另一个 class 中定义的函数时,我是否滥用了它?我注意到当我使用 self 来引用 move_up 时,我得到了一个 AttributeError: 'Button' object has no attribute 'move_up' — 我必须将 move_up 函数称为 character.move_up 即使我在字符 class 中引用它。如果问题与 bind() 函数无关,我怎样才能让程序取消调度 move_up 函数?
下面是我的代码:
from kivy.uix.widget import Widget
from kivy.graphics import Canvas, Rectangle, Color
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.properties import *
from kivy.core.window import Window
from main import *
from render import Layer
class char_controls(FloatLayout):
'''controls where the character moves. There are 4 regions where the player can tap:
the top third to go up, the bottom third to go down, the center left to go left
and the center right to go right. They are buttons.'''
def __init__(self, **kwargs):
super(char_controls, self).__init__(**kwargs)
self.opacity = 0
self.size = (Window.width, Window.height)
anchor_bc = AnchorLayout(anchor_x = 'center', anchor_y = 'bottom')
down_btn = Button(text='', size_hint = (1, 0.3333))
down_btn.bind(on_press=character.move_down, on_release=character.stop)
down_btn.bind(on_press=Layer.move_down, on_release=Layer.stop)
anchor_bc.add_widget(down_btn)
self.add_widget(anchor_bc)
anchor_cl = AnchorLayout(anchor_x = 'left', anchor_y = 'center')
left_btn = Button(text='', size_hint = (0.5, 0.3333))
left_btn.bind(on_press=character.move_left, on_release=character.stop)
left_btn.bind(on_press=Layer.move_left, on_release=Layer.stop)
anchor_cl.add_widget(left_btn)
self.add_widget(anchor_cl)
anchor_cr = AnchorLayout(anchor_x = 'right', anchor_y = 'center')
right_btn = Button(text='', size_hint = (0.5, 0.3333))
right_btn.bind(on_press=character.move_right, on_release=character.stop)
right_btn.bind(on_press=Layer.move_right, on_release=Layer.stop)
anchor_cr.add_widget(right_btn)
self.add_widget(anchor_cr)
#button of interest
anchor_tc = AnchorLayout(anchor_x = 'center', anchor_y = 'top')
up_btn = Button(text='', size_hint = (1, 0.3333))
up_btn.bind(on_press=character.schedule_up, on_release=character.stop)
up_btn.bind(on_press=Layer.move_up, on_release=Layer.stop)
anchor_tc.add_widget(up_btn)
self.add_widget(anchor_tc)
class character(Widget):
'''The character class.'''
x_pos = 0
y_pos = 0
pos = (x_pos, y_pos)
def __init__(self, **kwargs):
super(character, self).__init__(**kwargs)
with self.canvas:
Color(1., 0, 0)
character.sprite = Rectangle(pos=self.pos, size=(32, 32))
#is there a cleaner way to call the movement functions than this? (Eg lambda)
def schedule_up(self):
Clock.schedule_interval(character.move_up, 1/30.)
def move_up(self):
character.y_pos += 1
character.pos = (character.x_pos, character.y_pos)
character.sprite.pos = character.pos
print('run')
def move_down(self):
print('down')
def move_right(self):
print('right')
def move_left(self):
print('left')
def stop(self):
Clock.unschedule(character.move_up) #this is not actually unscheduling the move_up function.
print('stop') #prints, so the function is working
提前致谢!
观看控制台:
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
class Test(BoxLayout):
def __init__(self, **kw):
super(Test,self).__init__(**kw)
from kivy.clock import Clock
func1=Test.foo
print func1
Clock.schedule_interval(func1,1)
func2=Test.foo
print func2
print func1 is func2 # <--------------------Here(False) ^^
Clock.unschedule(func2)
def foo(self):
print 'bar'
runTouchApp(Test())
您正在使用两个不同的东西 character.<function>
,它们被安排在 class 中(如果您可以 self
访问,我觉得很奇怪)并且您取消了 的安排self.<function>
另一个你只用相同方式调用的函数。
第一个是未绑定的方法Test.foo
,第二个是绑定到一个class另一个不是同一个函数的未绑定,因此你是取消安排不正确的功能,即尚未安排的功能。要么到处使用相同的措辞,要么正确使用。
另外你想要的是class交流,这在这个标签下的一些问题中有解释,例如 - 使用主应用 class 处理连接。
我不太确定你是否在滥用 bind()
因为我在 kv 中做这些事情,但你应该能够同时使用不同的键盘,即 bind(on_press=...,on_release=...)
我正在为 android 使用 kivy 制作一款游戏,玩家可以通过触摸屏幕上的特定区域来控制。我创建了不可见的按钮 (char_controls),当按下该按钮时,角色会移动。松开手指的那一刻,我希望角色停止。
我已经为每个按钮绑定了一个函数,该函数在字符 class 中的 move_up 函数上调用 Clock.schedule_interval(现在只能使用向上按钮)。释放按钮时,它会调用另一个函数,该函数应该取消对原始函数的调度(Clock.unschedule)。然而,它并没有这样做,角色继续移动。
当我使用 kivy 的 bind() 函数将按钮的 on_press 和 on_release 行为绑定到另一个 class 中定义的函数时,我是否滥用了它?我注意到当我使用 self 来引用 move_up 时,我得到了一个 AttributeError: 'Button' object has no attribute 'move_up' — 我必须将 move_up 函数称为 character.move_up 即使我在字符 class 中引用它。如果问题与 bind() 函数无关,我怎样才能让程序取消调度 move_up 函数?
下面是我的代码:
from kivy.uix.widget import Widget
from kivy.graphics import Canvas, Rectangle, Color
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.properties import *
from kivy.core.window import Window
from main import *
from render import Layer
class char_controls(FloatLayout):
'''controls where the character moves. There are 4 regions where the player can tap:
the top third to go up, the bottom third to go down, the center left to go left
and the center right to go right. They are buttons.'''
def __init__(self, **kwargs):
super(char_controls, self).__init__(**kwargs)
self.opacity = 0
self.size = (Window.width, Window.height)
anchor_bc = AnchorLayout(anchor_x = 'center', anchor_y = 'bottom')
down_btn = Button(text='', size_hint = (1, 0.3333))
down_btn.bind(on_press=character.move_down, on_release=character.stop)
down_btn.bind(on_press=Layer.move_down, on_release=Layer.stop)
anchor_bc.add_widget(down_btn)
self.add_widget(anchor_bc)
anchor_cl = AnchorLayout(anchor_x = 'left', anchor_y = 'center')
left_btn = Button(text='', size_hint = (0.5, 0.3333))
left_btn.bind(on_press=character.move_left, on_release=character.stop)
left_btn.bind(on_press=Layer.move_left, on_release=Layer.stop)
anchor_cl.add_widget(left_btn)
self.add_widget(anchor_cl)
anchor_cr = AnchorLayout(anchor_x = 'right', anchor_y = 'center')
right_btn = Button(text='', size_hint = (0.5, 0.3333))
right_btn.bind(on_press=character.move_right, on_release=character.stop)
right_btn.bind(on_press=Layer.move_right, on_release=Layer.stop)
anchor_cr.add_widget(right_btn)
self.add_widget(anchor_cr)
#button of interest
anchor_tc = AnchorLayout(anchor_x = 'center', anchor_y = 'top')
up_btn = Button(text='', size_hint = (1, 0.3333))
up_btn.bind(on_press=character.schedule_up, on_release=character.stop)
up_btn.bind(on_press=Layer.move_up, on_release=Layer.stop)
anchor_tc.add_widget(up_btn)
self.add_widget(anchor_tc)
class character(Widget):
'''The character class.'''
x_pos = 0
y_pos = 0
pos = (x_pos, y_pos)
def __init__(self, **kwargs):
super(character, self).__init__(**kwargs)
with self.canvas:
Color(1., 0, 0)
character.sprite = Rectangle(pos=self.pos, size=(32, 32))
#is there a cleaner way to call the movement functions than this? (Eg lambda)
def schedule_up(self):
Clock.schedule_interval(character.move_up, 1/30.)
def move_up(self):
character.y_pos += 1
character.pos = (character.x_pos, character.y_pos)
character.sprite.pos = character.pos
print('run')
def move_down(self):
print('down')
def move_right(self):
print('right')
def move_left(self):
print('left')
def stop(self):
Clock.unschedule(character.move_up) #this is not actually unscheduling the move_up function.
print('stop') #prints, so the function is working
提前致谢!
观看控制台:
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
class Test(BoxLayout):
def __init__(self, **kw):
super(Test,self).__init__(**kw)
from kivy.clock import Clock
func1=Test.foo
print func1
Clock.schedule_interval(func1,1)
func2=Test.foo
print func2
print func1 is func2 # <--------------------Here(False) ^^
Clock.unschedule(func2)
def foo(self):
print 'bar'
runTouchApp(Test())
您正在使用两个不同的东西 character.<function>
,它们被安排在 class 中(如果您可以 self
访问,我觉得很奇怪)并且您取消了 的安排 另一个你只用相同方式调用的函数。self.<function>
第一个是未绑定的方法Test.foo
,第二个是绑定到一个class另一个不是同一个函数的未绑定,因此你是取消安排不正确的功能,即尚未安排的功能。要么到处使用相同的措辞,要么正确使用。
另外你想要的是class交流,这在这个标签下的一些问题中有解释,例如
我不太确定你是否在滥用 bind()
因为我在 kv 中做这些事情,但你应该能够同时使用不同的键盘,即 bind(on_press=...,on_release=...)