usage of DragBehavior in Kivy

社会主义新天地 提交于 2021-01-29 11:04:10

问题


I'm new for python and kivy, and struggling with them.

I wanted to implement drag and drop function (a function that when a image is dragged to another image and dropped on it, do something.) with kivy.

What I want to do are the following three things;

  • know the id of the element that the user has been holding now.
  • know the id of the element that the user is on hover.
  • know the id of the element which was under the pointer when the user has dropped what he had.

I thought this would be useful to deal with them, so I wrote down the python script and .kivy file following. However, it dosen't work as I intended.

there are many problems which I don't know how to solve;

  • print(self.id) returns None.
  • Even though I am dragging only 1 element, on_touch_up prints None twice.
  • once you dragged and dropped a image, the image cannot be dragged anymore.

python file:

from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.behaviors import DragBehavior
from kivy.properties import BooleanProperty
from kivy.properties import ObjectProperty
from kivy.factory import Factory
from kivy.core.window import Window


class HoverBehavior(object):
    """Hover behavior.
    :Events:
        `on_enter`
            Fired when mouse enter the bbox of the widget.
        `on_leave`
            Fired when the mouse exit the widget
    """

    hovered = BooleanProperty(False)
    border_point = ObjectProperty(None)
    '''Contains the last relevant point received by the Hoverable. This can
    be used in `on_enter` or `on_leave` in order to know where was dispatched the event.
    '''

    def __init__(self, **kwargs):
        self.register_event_type('on_enter')
        self.register_event_type('on_leave')
        Window.bind(mouse_pos=self.on_mouse_pos)
        super(HoverBehavior, self).__init__(**kwargs)

    def on_mouse_pos(self, *args):
        if not self.get_root_window():
            return  # do proceed if I'm not displayed <=> If have no parent
        pos = args[1]
        # Next line to_widget allow to compensate for relative layout
        inside = self.collide_point(*self.to_widget(*pos))
        if self.hovered == inside:
            # We have already done what was needed
            return
        self.border_point = pos
        self.hovered = inside
        if inside:
            self.dispatch('on_enter')
        else:
            self.dispatch('on_leave')

    def on_enter(self):
        pass

    def on_leave(self):
        pass


Factory.register('HoverBehavior', HoverBehavior)


class DraggableImage(DragBehavior, HoverBehavior, Image):
    def __init__(self, **args):
        super(DraggableImage, self).__init__(**args)
        self.source_file = ""
        self.is_on_hover = False

    def on_enter(self):
        self.source_file = self.source
        self.source = "green.png"
        self.is_on_hover = True
        print(self.id)

    def on_leave(self):
        self.source = self.source_file
        self.is_on_hover = False
        print(self.id)

    def on_touch_up(self, touch):
        if self.is_on_hover:
            print(self.id)


class TestApp(App):
    def build(self):
        pass


if __name__ == '__main__':
    TestApp().run()

test.kivy:

<DraggableImage>
    drag_rectangle: self.x, self.y, self.width, self.height
    drag_timeout: 10000000
    drag_distance: 0

BoxLayout:
    orientation: "horizontal"
    DraggableImage:
        id: "left_left"
        source: "red.png"
    DraggableImage:
        id: "left_right"
        source: "yellow.png"
    DraggableImage:
        id: "right_left"
        source: "red.png"
    DraggableImage:
        id: "right_right"
        source: "yellow.png"

回答1:


Create a StringProperty named, name for example. Don't use id, because id is used in kv.
Change your class and kv as so:

from kivy.properties import StringProperty

class DraggableImage(DragBehavior, HoverBehavior, Image):

    name = StringProperty("")

    def __init__(self, **args):
        super(DraggableImage, self).__init__(**args)
        self.source_file = ""
        self.is_on_hover = False

    def on_enter(self):
        self.source_file = self.source
        self.source = "green.png"
        self.is_on_hover = True
        print(self.name)

    def on_leave(self):
        self.source = self.source_file
        self.is_on_hover = False
        print(self.name)

    def on_touch_up(self, touch):
        if self.is_on_hover:
            print(self.name)




KV = """

<DraggableImage>:
    drag_rectangle: self.x, self.y, self.width, self.height
    drag_timeout: 10000000
    drag_distance: 0

BoxLayout:
    orientation: "horizontal"
    DraggableImage:
        name: "left_left"
        source: "red.png"
    DraggableImage:
        name: "left_right"
        source: "yellow.png"
    DraggableImage:
        name: "right_left"
        source: "red.png"
    DraggableImage:
        name: "right_right"
        source: "yellow.png"

"""


来源:https://stackoverflow.com/questions/47607951/usage-of-dragbehavior-in-kivy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!