我正在尝试使用Kivy库使用python创建Ur的皇家游戏。
我想做的是创建一个棋盘(已经完成,但是还需要做更复杂的工作),并为每个玩家创建7个棋子(图)。我设法创建了全部7个,但不知道如何独立地操作它们或完全不动。
我找到了一个代码,该代码允许我使用鼠标移动对象,但是只需要移动鼠标位于其上方的对象即可。有点像只抓住需要的棋子,而不是一直吸引女王。
代码:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Ellipse
from kivy.clock import Clock
from random import random
class CircleWidget(Widget):
def __init__(self, **kwargs):
Widget.__init__(self, **kwargs)
self.size = (50,50)
for i in range(0, 7):
self.circle = Ellipse(pos = self.pos, size = self.size)
self.canvas.add(self.circle)
# handle position change
def on_pos(self, obj, new_pos):
self.circle.pos = new_pos # when widget moves, so does the graphic instruction
class RootWidget(Widget):
def __init__(self, **kwargs):
Widget.__init__(self, **kwargs)
self.cw = CircleWidget()
self.add_widget(self.cw)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
touch.grab(self)
# do whatever else here
def on_touch_move(self, touch):
if touch.grab_current is self:
print("This prints all the time...")
self.cw.pos = (touch.x,touch.y)
def on_touch_up(self, touch):
if touch.grab_current is self:
touch.ungrab(self)
# and finish up here
def update(self, dt):
print("No idea why I need this")
class MyApp(App):
def build(self):
rw = RootWidget()
# call update() every second
Clock.schedule_interval(rw.update, 1.0)
return rw
MyApp().run()
此外,我忘了将所有图形的位置都编辑为彼此相邻,但这并不是一项艰巨的任务。
任何帮助他们一步一步地移动吗?
答案 0 :(得分:0)
在您的情况下,您将覆盖self.canvas,因此在循环之后self.canvas将仅是最后一个元素,因此您会注意到,当您移动一个元素并想移动另一个元素时,先前移动的项目就会移动。
我建议您避免进行肮脏的工作,kivy具有许多通过Behavior
实现的功能,在这种情况下,正确的做法是使用DragBehavior
,我的解决方案将实现在.kv中绘制的代码,因为作为一种声明性语言,该绑定很容易保存行,如on_pos
和其他绑定(如drag_rectangle)。
另一方面,CircleWidget必须实现一个圆圈,而不是7个圆圈,因为圆圈的位置会有所不同,在您的情况下,您使它们看起来像一个圆圈。
解决方案:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.clock import Clock
from kivy.lang import Builder
kv = '''
<CircleWidget>:
size: 50, 50
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0
canvas:
Ellipse:
pos: root.pos
size: root.size
'''
Builder.load_string(kv)
class CircleWidget(DragBehavior, Widget):
pass
class RootWidget(Widget):
def __init__(self, **kwargs):
Widget.__init__(self, **kwargs)
for i in range(7):
cw = CircleWidget()
self.add_widget(cw)
def update(self, dt):
print("No idea why I need this")
class MyApp(App):
def build(self):
rw = RootWidget()
# call update() every second
Clock.schedule_interval(rw.update, 1.0)
return rw
MyApp().run()
答案 1 :(得分:0)
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Ellipse, Color
from kivy.core.window import Window
from random import randint
class CircleWidget(Widget):
def __init__(self, **kwargs):
super(CircleWidget, self).__init__(**kwargs)
self.size = (50, 50)
with self.canvas:
Color(0, 0, 1, 0.5)
self.circle = Ellipse(pos=self.pos, size=self.size)
self.bind(pos=self.redraw, size=self.redraw)
def redraw(self, *args):
self.circle.size = self.size
self.circle.pos = self.pos
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
# if the touch collides with our widget, let's grab it
touch.grab(self)
# and accept the touch.
return True
return super(CircleWidget, self).on_touch_down(touch)
def on_touch_up(self, touch):
# check if it's a grabbed touch event
if touch.grab_current is self:
# don't forget to ungrab ourself, or you might have side effects
touch.ungrab(self)
# and accept the last up
return True
return super(CircleWidget, self).on_touch_up(touch)
def on_touch_move(self, touch):
# check if it's a grabbed touch event
if touch.grab_current is self:
self.pos = touch.pos
# and accept the last move
return True
return super(CircleWidget, self).on_touch_move(touch)
class RootWidget(Widget):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
for i in range(8):
self.add_widget(CircleWidget(pos=(randint(0, Window.width - 50), randint(0, Window.height - 50))))
class MyApp(App):
def build(self):
return RootWidget()
if __name__ == "__main__":
MyApp().run()