Reputation: 11
I'm new to Kivy and I'm looking for a way to drag Images only inside choosen Layout, not around all the window. I tried to manipulate with drag_rectangle
option in kv file, but this not ended with expected behavior. Is there any way to set area when user could drag items and if it exists, how it could be done?
Thanks for your reply.
Here is my code:
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()
My kv file:
<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()
Upvotes: 0
Views: 289
Reputation: 11
Ok, I solved this.
I had to understand how DragBehavior works. Apparently, there is documentation on Kivy website, when you can find every possible interaction with draggable items. (https://kivy.org/doc/stable/_modules/kivy/uix/behaviors/drag.html)
Function on_touch_move(self, touch)
solved my problem.
Additonaly I used some methods from Layouts in order to make sure, that my Images will change their position proportionally to size of my window.
Here is my code:
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()
And kv file:
<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()
Upvotes: 1