如何设置用户可以使用 Kivy DragBehavior 拖动项目的区域?

How to set area where user can drag items with Kivy DragBehavior?

我是 Kivy 的新手,我正在寻找一种方法来仅在选择的布局内拖动图像,而不是在所有 window 周围。我试图在 kv 文件中使用 drag_rectangle 选项进行操作,但这并没有以预期的行为结束。有什么方法可以设置用户可以拖动项目的区域,如果存在,如何设置?

感谢您的回复。

这是我的代码:

from kivy.config import Config

Config.set('input', 'mouse', 'mouse,disable_multitouch')

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import DragBehavior
from kivy.uix.image import Image


class DragLabel(DragBehavior, Image):
    pass


class Pattern(FloatLayout):

    def create_pattern(self):
        A = DragLabel(source="some.png", pos=(0, 0))
        self.add_widget(A)

class MainScreen(BoxLayout):
    pass


class AberationsApp(App):

    def build(self):
        return MainScreen()


window = AberationsApp()
window.run()

我的 kv 文件:

<DragLabel>:
    drag_rectangle: self.x/10, self.y/10, root.width, root.height
    drag_timeout: 10000000
    drag_distance: 0
    on_touch_move: print(self.x, self.y, self.size)


<Pattern>:


<MainScreen>:
    size_hint: 1, 1
    Pattern:
        size_hint: .8, 1
        id: Created_Pattern
    Button:
        size_hint: .2, 1
        text:"Load_points!"
        on_press: print(self.size, root.size)
        on_release: Created_Pattern.create_pattern()

好的,我解决了这个问题。

我必须了解 DragBehavior 的工作原理。显然,Kivy 网站上有文档,您可以找到与可拖动项目的所有可能交互。 (https://kivy.org/doc/stable/_modules/kivy/uix/behaviors/drag.html)

函数 on_touch_move(self, touch) 解决了我的问题。

此外,我还使用了 Layouts 中的一些方法,以确保我的图像会根据 window.

的大小按比例更改其位置

这是我的代码:

from kivy.config import Config

Config.set('input', 'mouse', 'mouse,disable_multitouch')

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import DragBehavior
from kivy.uix.image import Image
from kivy.metrics import sp


class DragLabel(DragBehavior, Image):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.previous_size = [1, 1]

    def do_layout(self, *args):
        self.x = self.x * self.width / self.previous_size[0]
        self.y = self.x * self.height / self.previous_size[1]
        if self.x > self.width:
            self.x = .85 * self.width
        if self.y > self.height:
            self.y = .85 * self.height
        self.previous_size = [self.width, self.height]

    def on_size(self, *args):
        self.do_layout()

    def on_touch_move(self, touch):
        if self._get_uid('svavoid') in touch.ud or \
            self._drag_touch is not touch:
            return super(DragBehavior, self).on_touch_move(touch) or \
               self._get_uid() in touch.ud
        if touch.grab_current is not self:
            return True

        uid = self._get_uid()
        ud = touch.ud[uid]
        mode = ud['mode']
        if mode == 'unknown':
            ud['dx'] += abs(touch.dx)
            ud['dy'] += abs(touch.dy)
            if ud['dx'] > sp(self.drag_distance):
                mode = 'drag'
            if ud['dy'] > sp(self.drag_distance):
                mode = 'drag'
            ud['mode'] = mode
        if mode == 'drag':
            previous_x_position = self.x
            previous_y_position = self.y
            new_x_position = previous_x_position + touch.dx
            new_y_position = previous_y_position + touch.dy
            if .85 * self.size[0] >= new_x_position >= 0 and .85 * self.size[1] >= new_y_position >= 0:
                self.x = new_x_position
                self.y = new_y_position
        return True


class Pattern(FloatLayout):

    def create_pattern(self):
        A = DragLabel(source="some.png", pos=(0, 0))
        self.add_widget(A)


class MainScreen(BoxLayout):
    pass


class AberationsApp(App):

    def build(self):
        return MainScreen()


window = AberationsApp()
window.run()

和kv文件:

<DragLabel>:
    drag_rectangle: self.x, self.y, root.width, root.height

<Pattern>:

<MainScreen>:
    size_hint: 1, 1
    Pattern:
        size_hint: .8, 1
        id: Created_Pattern
    Button:
        size_hint: .2, 1
        text:"Load points!"
        on_release: Created_Pattern.create_pattern()