Sunday, June 29, 2014

39. DragBehavior

Any widget can get DragBehavior. That means it can be dragged around. We can, of course, write code to on_touch_down, and on_touch_move, to simulate same behavior. However, using the DragBehavior class, reduces code, and thus error in typing.




To use DragBehavior, it must be imported from kivy.uix.behaviors module. We update a StringProperty to indicate current state; that is, whether we are dragging or not.




A horse-shaped widget inherits DragBehavior. The behavior must be the first argument. The kind of widget is the second argument, here it is the base class Widget. We find the status by using on_touch_move. First, we find touch position, as well as position of horse widget, and initialize the four numbers, that we will use, in the next step. Often, you will write shorter variable names, to make code clearer.




The positions are used in this logical statement. The reason, we use this, rather than collide_point, is that not all horse points, should be clickable, and draggable. Only a portion of the horse widget is draggable. It corresponds to the saddle region of the horse. These numbers were found from a graphics program, GIMP. The details, about the image coordinates, will be shown later. Finally, we pass the on_touch_move to the DragBehavior class so it can receive that event as well, and respond to it.


# ex39.py

from kivy.uix.widget import Widget
from kivy.uix.behaviors import DragBehavior
from kivy.app import App
from kivy.properties import StringProperty

class Horse(DragBehavior,Widget):
    horse_state=StringProperty('Not Dragging')
    def on_touch_move(self,touch):
        tx,ty = touch.pos
        sx,sy = self.pos
        if sx+52>=tx>sx+36 and sy+53>=ty>sy+28:
            self.horse_state = 'Dragging'
        return super(Horse, self).on_touch_move(touch)
    
class Ex39(Widget):
    pass
       
class Ex39App(App):
    def build(self):
        return Ex39()

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



The horse image is obtained from opengameart.org. You can get it by searching for horse. The original picture is 50 pixels by 37 pixels. First, it is scaled up 2 times so the new size is 100 by 74 pixels. To get the saddle coordinates you can open the image in a graphics program. The list of these coordinates is shown next.




In the kv file, we give three drag variables. The drag_rectangle represents region where dragging can occur. In our example, it is the saddle region. It is a region 16 by 25 pixels in size. Further, it is 36 pixels right from the left edge and 28 pixels above the bottom edge. The values of drag_timeout, and drag_distance, will rarely have to be changed. You may choose the default, but these seem to be more responsive.




Here we use on_touch_up to write 'Not Dragging'. We don't check where the touch is removed as it does not make a difference. We also don't need to call to super class from the kv file.




The background color is blue, and a Label indicates the purpose of the program at the top of screen.




Finally, we have an instance of the Horse class. In the pos, we give the initial position. Finally, the Label indicates the value of horse_state variable.


# ex39.kv

<Horse>:
    size: 100,74
    drag_rectangle: self.x+36, self.y+28, 16, 25
    drag_timeout: 10000000
    drag_distance: 0
    on_touch_up: self.horse_state = 'Not Dragging'
    canvas:
        Rectangle:
            pos: self.pos
            size: self.size
            source: 'horse.png'
    
<Ex39>:
    canvas:
        Color:
            rgb: 0,0,1
        Rectangle:
            size: root.width,root.height
            pos: 0,0
    Label:
        pos: 300,root.top-100
        text:
            ('[size=32][color=CC8811]'
            'Drag horse saddle to move horse'
            '[/color][/size]')
        markup: True
    Horse:
        id: horse_id
        pos: root.width/2.5,root.height/2
    Label:
        pos: 300,100
        text:
            ('[size=32][color=CC8811]'+
            horse_id.horse_state+
            '[/color][/size]')
        markup: True

        



This is the result while dragging the horse widget after touching the saddle. Even though, here, we used on_touch_down and on_touch_move, we rarely will ever need to. After all, it hardly matters if the program knows it is dragging as you will have visual cues. But that is where you will place any code to take place whenever dragging occurs. There are other behaviors in Kivy which can be given to widgets. To control them, besides declaring which behavior our widget implements, we will change the properties they have from within the kv file.




3 comments:

  1. Python:

    Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.

    https://www.emexotechnologies.com/online-courses/python-training-in-electronic-city/

    ReplyDelete
  2. Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.

    Python Training in electronic city

    ReplyDelete