Kivy (Python) - Ellipse Click Event

2019-07-13 11:15发布

问题:

I'm trying to translate the beginnings of a simple canvas app I wrote in JavaScript to the Kivy framework. I have been able to distribute vertices along the perimeter of a circle, but I have been unsuccessful in registering click events on each vertex whether attempted in Python or Kv language. A nice start might be changing the size of any vertex clicked. Any tips, feedback, solutions welcome.

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.graphics import *
from kivy.properties import NumericProperty
from random import randint
import math

class Vertex(Widget):
    def __init__(self, position=(50,50), **kwargs):
        super(Vertex, self).__init__(**kwargs)
        self.position = position
        self.size = (10,10)


    def draw(self):
     with self.canvas:
        Color(1., 0, 0)
        Ellipse(pos=self.position, size=self.size)


class ChromaticCircle(Widget):
    vertices = []

    def __init__(self, radius=100, **kwargs):
        super(ChromaticCircle, self).__init__(**kwargs)
        self.radius = radius
        self.draw()

    def draw(self):
        interval = (math.pi * 2) / 12

        with self.canvas:
            Color(1., 0, 0)

            for i in range(1, 13):
                angle = (math.radians(360) / 12) * (i + 9)
                position = ((self.center_x + 200) + (self.radius*math.cos(angle)), (self.center_y + 200)+(self.radius)*math.sin(angle))
                self.vertices.append(Vertex(position))

            for j in range(len(self.vertices)):
                self.vertices[j].draw()


class MyApp(App):
    def build(self):
        return ChromaticCircle()

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

回答1:

You can capture clicks on your Vertex widget by using the collide_point method in the on_touch_down method to check if a Touch event occurs within a Vertex:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.graphics import *
from kivy.properties import NumericProperty
from random import randint
import math

class Vertex(Widget):
    def __init__(self, position=(50,50), **kwargs):
        super(Vertex, self).__init__(**kwargs)
        self.position = position
        self.size = (10,10)
        self.pos = position    # need to set the `pos` as `collide_point` uses it

    def draw(self):
     with self.canvas:
        Color(1., 0, 0)
        Ellipse(pos=self.position, size=self.size)


class ChromaticCircle(Widget):
    vertices = []

    def __init__(self, radius=100, **kwargs):
        super(ChromaticCircle, self).__init__(**kwargs)
        self.radius = radius
        self.draw()

    def on_touch_down(self, touch):
        # check if the touch is on a Vertex
        for vert in self.vertices:
            if vert.collide_point(touch.x, touch.y):
                print('click on vertex: ' + str(vert.pos))
                return True
        return super(ChromaticCircle, self).on_touch_down(touch)

    def draw(self):
        interval = (math.pi * 2) / 12

        with self.canvas:
            Color(1., 0, 0)

            for i in range(1, 13):
                angle = (math.radians(360) / 12) * (i + 9)
                position = ((self.center_x + 200) + (self.radius*math.cos(angle)), (self.center_y + 200)+(self.radius)*math.sin(angle))
                print('adding vertex at ' + str(position))
                self.vertices.append(Vertex(position))

            for j in range(len(self.vertices)):
                self.vertices[j].draw()


class MyApp(App):
    def build(self):
        return ChromaticCircle()

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

There are some additional details that you may want to consider. The pos of the Ellipse is the lower left corner, so your vertex position is not at the center of the drawn Ellipse.