Question

I'm quite new to Kivy & Python so please excuse the poor code/explanation!

When the touch down event is activated I want a section of code to continuously run until the touch up event is activated.

My current method is using a global variable which is manipulated by both events. But the loop doesn't seem to register the change in the global variable.

Is there anyway to make this method work. Or alternatively another method which would be more suitable?

    touched_down = 1

def on_touch_down(self, touch):
    global touched_down 
    touched_down = 1
    self.move()

def on_touch_up(self, touch):
    global touched_down 
    touched_down = 0

def move(self):
    while (touched_down == 1):
        <----- code ----->

Thanks!

Was it helpful?

Solution

1) Don't use globals. This should technically work, but it's bad practice and in this case there's no downside to simply adding a variable to your class. NotNone has this very moment posted an example of how to do so with a kivy property, which adds some other behaviour you may find convenient later.

2) Your move function isn't compatible with an eventloop driven gui like kivy (or many other gui libraries). The problem is that the while function is a blocking call - all of kivy's normal tasks can't be performed until the move function terminates. Detecting and propagating touch is one of these things, so on_touch_up will never be called, and the touched_down variable will never become False.

You probably instead want to do something like:

from kivy.clock import Clock

def on_touch_down(self, touch):
    Clock.schedule_interval(self.incremental_move, 0)

def on_touch_up(self, touch):
    Clock.unschedule(self.incremental_move)

def incremental_move(self, dt):
    # write code for movement in the time dt here

Using the clock like this inserts the movement into the normal kivy eventloop, so it's called every frame without blocking everything else.

It might also be more natural to have an update function that is always scheduled (and does other things too), and use a self.touched_down attribute as above to optionally perform movement during that function.

OTHER TIPS

I think using a custom property could solve your problem. I am not able to test this, but something like this should work.

class MyWidget(Widget):
    touched_down = NumericProperty(0)

    def on_touch_down(self, touch):
        self.touched_down = 1
        self.move()

    def on_touch_up(self, touch): 
        self.touched_down = 0

    def move(self):
        while self.touched_down:
            <----- code ----->

In my opinion properties are some of the very best features of Kivy, so take a look at them if they aren't familiar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top