Nick Camps
Nick Camps

Reputation: 111

Output touch position from custom kivy widget to labels

I am trying to create an app that draws a small ellipse at the point where I click my mouse. Then if I click again, I want it to delete the old ellipse and draw a new one at the new mouse click location. I have gotten this part to work. The next step is to get the mouse click location to print to the text of two labels. For some reason I can't figure out how to properly reference the label text to update it. My code is below. The ColorLoopWidget is mostly based off of the A Simple Paint App in the Kivy tutorials.

main.py

from kivy.config import Config
Config.set('graphics', 'width', '1000')
Config.set('graphics', 'height', '500')
Config.set('graphics', 'resizable', 0)
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.graphics import Color, Ellipse, Line

Builder.load_file('hueLayout.kv')

class ColorLoopWidget(Widget):
    xlabel = ObjectProperty
    ylabel = ObjectProperty
    def on_touch_down(self, touch):
        with self.canvas:
            self.canvas.clear()
            d = 10
            Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d,d))
            touch.ud['line'] = Line(points=(touch.x, touch.y))
##            self.xlabel.text = 'x: '+str(touch.x)
##            self.ylabel.text = 'y: '+str(touch.y)

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



class HueLayout(Widget):
    colorloopwidget = ObjectProperty
    xlabel = ObjectProperty
    ylabel = ObjectProperty

##    def on_touch_down():
##        ColorLoopWidget.on_touch_down()
##
##    def on_touch_move():
##        ColorLoopWidget.on_touch_move()

    def clear_canvas(self):
        self.colorloopwidget.canvas.clear()


class HueApp(App):
    def build(self):
        return HueLayout()

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

HueLayout.kv

<HueLayout>:
    colorloopwidget: colorloopwidget
    xlabel: xlabel
    ylabel: ylabel

    BoxLayout:
        size: 1000, 500
        orientation: 'horizontal'

        ColorLoopWidget:
            id: colorloopwidget
            size: 500, 500

        BoxLayout:
            orientation: 'vertical'
            Button:
                text: 'Clear'
                on_release: root.clear_canvas()
            Label:
                id: xlabel
                text: 'x: '
                size_hint_y: 0.2
            Label:
                id: ylabel
                text: 'y: '
                size_hint_y: 0.2

Upvotes: 2

Views: 2157

Answers (1)

inclement
inclement

Reputation: 29478

Two problems:

1) You do xlabel = ObjectProperty, but this just doesn't instantiate an ObjectProperty, it sets xlabel to ObjectProperty itself. You instead want to do xlabel = ObjectProperty(), the brackets create an instance of ObjectProperty.

2) Your on_touch_down method is in the ColorLoopWidget, and tries (in your commented out code) to reference self.xlabel and self.ylabel. This doesn't work because those properties are never set; if you check the kv you see that HueLayout has xlabel: xlabel and ylabel: ylabel but the interior ColorLoopWidget does not. The code below adds these properties, so that the ColorLoopWidget knows about the labels and its on_touch_down method is able to reference them.

The following code fixes both issues, and seems to work fine for me.

main.py:

from kivy.config import Config
Config.set('graphics', 'width', '1000')
Config.set('graphics', 'height', '500')
Config.set('graphics', 'resizable', 0)
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.graphics import Color, Ellipse, Line

Builder.load_file('hueLayout.kv')

class ColorLoopWidget(Widget):
    xlabel = ObjectProperty()
    ylabel = ObjectProperty()
    def on_touch_down(self, touch):
        with self.canvas:
            self.canvas.clear()
            d = 10
            Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d,d))
            touch.ud['line'] = Line(points=(touch.x, touch.y))
            self.xlabel.text = 'x: '+str(touch.x)
            self.ylabel.text = 'y: '+str(touch.y)

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



class HueLayout(Widget):
    colorloopwidget = ObjectProperty()
    xlabel = ObjectProperty()
    ylabel = ObjectProperty()

##    def on_touch_down():
##        ColorLoopWidget.on_touch_down()
##
##    def on_touch_move():
##        ColorLoopWidget.on_touch_move()

    def clear_canvas(self):
        self.colorloopwidget.canvas.clear()


class HueApp(App):
    def build(self):
        return HueLayout()

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

hueLayout.kv:

<HueLayout>:
    colorloopwidget: colorloopwidget
    xlabel: xlabel
    ylabel: ylabel

    BoxLayout:
        size: 1000, 500
        orientation: 'horizontal'

        ColorLoopWidget:
            xlabel: xlabel
            ylabel: ylabel
            id: colorloopwidget
            size: 500, 500

        BoxLayout:
            orientation: 'vertical'
            Button:
                text: 'Clear'
                on_release: root.clear_canvas()
            Label:
                id: xlabel
                text: 'x: '
                size_hint_y: 0.2
            Label:
                id: ylabel
                text: 'y: '
                size_hint_y: 0.2

Upvotes: 4

Related Questions