Kivy - Как перетащить элементы из ScrollView в другой макет? - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь перетащить некоторые изображения, расположенные внутри GridLayout (который действительно находится внутри ScrollView), во внешний макет.

Для перетаскиваемого изображения определено событие on_touch_down, когда при щелчке по изображению родительский элемент изменяется с WidgetMenu на MainLayout, поэтому его можно перетаскивать между этими виджетами.Текущая проблема заключается в том, что при касании изображения DragBehavior теряется.

Полный код:

import kivy
kivy.require("1.9.1")
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.scrollview    import ScrollView
from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout

from kivy.base import runTouchApp
from kivy.lang import Builder

Builder.load_string('''
<WidgetMenu>:
    canvas.before:
        Color:
            rgb: 0.9,0.5,0.3
        RoundedRectangle:
            pos:self.pos
            size: self.size
            radius: [20,]
    orientation: "vertical"
    padding:30

    ScrollView:

        GridLayout:
            cols:1
            size_hint_y:None
            row_default_height:root.height*.15
            height:self.minimum_height
            DragImage:
            DragImage:
            DragImage:


<DragImage>:
    drag_rectangle: self.x, self.y, self.width, self.height
    drag_timeout: 100000000
    drag_distance: 0
    size_hint:None,None
    size:234,34
    canvas:
        Color:
            rgb:1,0,1
        Rectangle:
            pos: self.pos
            size: self.size

<MainLayout>:
    canvas:
        Color:
            rgb:1,1,1
        Rectangle:
            size: self.size
            pos: self.pos
    WidgetMenu:
        size_hint: 0.35,0.9

''')

class MainLayout(FloatLayout):
    pass
class WidgetMenu(BoxLayout):
    pass
class DragImage(DragBehavior,FloatLayout):
    def on_touch_down(self,touch):
        workspace = self.parent.parent.parent.parent
        grid = self.parent
        menu = self.parent.parent.parent
        if "MainLayout" in str(workspace):
            grid.remove_widget(self)
            workspace.remove_widget(menu)
            self.pos = Window.mouse_pos
            workspace.add_widget(self)
        return True

class ScrollApp(App):
    def build(self):
        return MainLayout()

ScrollApp().run()

Пожалуйста, помогите.

1 Ответ

0 голосов
/ 18 января 2019

Две проблемы с вашим кодом заключаются в том, что вы не вызываете супер-метод в вашем on_touch_down, а размещение DragImage на верхнем уровне MainLayout меняет pos DragImage, таким образом изменяя его DragRectangle. Это изменение в DragRectangle оставляет touch.pos вне его, поэтому DragBehavior считает, что касание не на DragImage.

Я исправил обе эти проблемы, вызвав метод super и изменив touch.pos перед передачей его в метод super. Я также добавил некоторый код, чтобы удерживать DragImage в том же положении относительно мыши при нажатии. Также добавлен вызов на self.collide_point(), чтобы игнорировать щелчки не на DragImage.

class DragImage(DragBehavior,FloatLayout):
    def on_touch_down(self,touch):
        if not self.collide_point(*touch.pos):
            return False
        workspace = self.parent.parent.parent.parent
        grid = self.parent
        menu = self.parent.parent.parent
        if "MainLayout" in str(workspace):
            grid.remove_widget(self)
            workspace.remove_widget(menu)

            # the following code assumes that workspace is the entire Window
            self.x = Window.mouse_pos[0] - (touch.pos[0] - self.x)
            self.y = Window.mouse_pos[1] - (touch.pos[1] - self.y)
            workspace.add_widget(self)
            touch.pos = Window.mouse_pos
        return super(DragImage, self).on_touch_down(touch)
...