Перемещение нескольких виджетов в Киви самостоятельно

1

Я пытаюсь создать королевскую игру Ur с питоном, используя Kivy libs.

То, что я пытаюсь сделать, это создать доску (что сделано, но впереди более сложная работа) и 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
    Вы спрашиваете, как сделать перетаскивание? Если это так, подумайте о том, чтобы заставить ваши подвижные части расширять DragBehavior .
Теги:
kivy

2 ответа

0

класс CircleWidget

  1. Нарисуйте эллипс на холсте.
  2. Свяжите pos и размер с обратным вызовом, методом перерисовки.
  3. Внесите методы on_touch_down, on_touch_up и on_touch_move для каждого Circlewidget.

пример

main.py

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 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 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 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()

Выход

Изображение 174551 Изображение 174551

0

В вашем случае вы перезаписываете self.canvas, поэтому после цикла self.canvas будет только последним элементом, поэтому вы заметите, что когда вы перемещаете элемент и хотите переместить другой элемент, который перемещал предыдущие шаги.

Я рекомендую вам избегать выполнения грязной работы, у kivy есть многие из тех функций, которые реализованы с помощью Behavior s, в этом случае правильная вещь - использовать 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()

Изображение 174551

  • 0
    Спасибо, работал более или менее. Теперь они отказываются менять цвет, хотя ...
  • 0
    @ MartinGontšarov В вашем примере, который вы указываете, я не вижу ничего о цвете, какую часть вы имеете в виду? какой цвет?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню