Перемещение нескольких виджетов в Киви самостоятельно - PullRequest
0 голосов
/ 26 сентября 2018

Я пытаюсь создать королевскую игру Ur с python, используя 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()

Кроме того, я забыл отредактировать позиции всех фигур, чтобы быть следующимидруг к другу, но это не сложная задача.

Помогаете ли вы перемещать их один за другим?

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

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

Выход

Img01 - App startup Img02 - Moved multiple widgets independently

0 голосов
/ 26 сентября 2018

В вашем случае вы перезаписываете 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()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...