Baxorr
Baxorr

Reputation: 318

How do I make on_touch_down widget specific?

I'm trying to create a simple drawing app in kivy but i'm having some issues with the

on_touch_down

function as it regards the entire class and not just a specific widget. So when I use the on touch down and on touch move functions to draw on the canvas it affects and effectively disables the touch down functions bound to buttons. Here's the code where the button doesn't work.

python code:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Line
from kivy.graphics import *
from kivy.uix.widget import Widget
class MyScreenManager(ScreenManager):
    pass

class MenuScreen(Screen):
    pass

class DrawScreen(Screen):
    def on_touch_down(self, touch):
        with self.canvas.before:
            Color(1, 0, 0)
            touch.ud["line"] = Line(points=(touch.x, touch.y), width=5)

    def on_touch_move(self, touch):
        touch.ud["line"].points += (touch.x, touch.y)



class DrawApp(App):
    def build(self):
        return MyScreenManager()

DrawApp().run()

kivy code:

<MenuButton@Button>:
    font_size: 65
    size_hint: 0.4, 0.25

<MyScreenManager>:
    MenuScreen:
        id: menu
        name: "menu"

    DrawScreen:
        id: draw
        name: "draw"

<MenuScreen>:
    canvas.before:
        Color:
            rgba: 1,1,1,1
        Rectangle:
            size: self.size
            pos: self.pos

    MenuButton:
        text: "Draw"
        on_release: root.manager.current = "draw"
        pos_hint:{"center_x":0.5, "center_y":0.6}
    MenuButton:
        text: "Quit"
        on_release: app.stop()
        pos_hint:{"center_x":0.5, "center_y":0.3}

<DrawScreen>:
    canvas.before:
        Color:
            rgba: 1,1,1,1
        Rectangle:
            size: self.size
            pos: self.pos


    Button:
        id: but
        size_hint: 0.2,0.1
        pos_hint_x: 0 + self.width
        font_size: 30
        text: "Back"
        on_release: root.manager.current = "menu"

I managed to find a simple work around by using collide_point, here's my workaround code:

class DrawScreen(Screen):
    def on_touch_down(self, touch):
        but = self.ids.but
        if but.collide_point(touch.x, touch.y):
            self.manager.current = "menu"

        else:
            with self.canvas.before:
                Color(1, 0, 0)
                touch.ud["line"] = Line(points=(touch.x, touch.y), width=5)

    def on_touch_move(self, touch):
        touch.ud["line"].points += (touch.x, touch.y)

But while this works it brings up a whole world of new problems like me having to manually configure every button to change source when held down and the function not running until the button is released. It also means that everything I add to the class has to be added to the if statement.

I'm quite positive that there has to be a simpler way. My first thought was that maybe one could add the on touch down to only affect one widget? My second thought was that maybe if would be better to not draw on the canvas or something?

Any help or pointers are appreciated, thanks!

Upvotes: 4

Views: 3746

Answers (1)

sp________
sp________

Reputation: 2645

when you overwrite a method, you must return the same method of the super class

something like this:

...

class DrawScreen(Screen):
    def on_touch_down(self, touch):
        with self.canvas.before:
            Color(1, 0, 0)
            touch.ud["line"] = Line(points=(touch.x, touch.y), width=5)
        return super(DrawScreen, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        touch.ud["line"].points += (touch.x, touch.y)
        return super(DrawScreen, self).on_touch_move(touch)

Upvotes: 3

Related Questions