KIVY collide_point RelativeLayout против StencilView - PullRequest
0 голосов
/ 03 апреля 2020

Я начал изучать KIVY из Kivy - Интерактивные приложения и игры в Python - Второе издание Роберто Уллоа ". Я пытался понять collide_point с примером программы.

В RelativeLayout с приведенным ниже примером кода Я могу определить, когда щелкнуть мышью по горизонтальной линии. Но если я использую StencilView, я не могу перехватить событие касания.

Любая помощь, пожалуйста

from kivy.app import App
from kivy.graphics import Line
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.stencilview import StencilView


class MyPaintWidget(Scatter):

    def __init__(self, **kwargs) :
        self.selected = None
        self.touched = False
        super(MyPaintWidget, self).__init__(**kwargs)

    def create_figure(self,  **kwargs):
        (ix,iy) = self.to_local(*self.pos)
        (fx,fy) = self.to_local(self.pos[0] + self.size[0], self.pos[1] + self.size[1])
        print ("ix " + str(ix) + " iy " + str(iy) + " fx " + str(fx) + " fy " + str(fy))
        self.canvas.add(Line( points=[ix, iy, fx, fy], width=1))
        return self

    def on_touch_down(self, touch):
        if self.collide_point(touch.x, touch.y):
           #This print I get for RelativeLayout
           #But for StencilView it does not work when I touch the line
           print("Hi you touched the line")

class MyPaintApp(App):

    def build(self):
        #If parent is StencilView unable to click
        #but if parent is RelativeLayout, I am able to get collide_point
        #parent = StencilView()
        parent = RelativeLayout()
        #parent = Scatter()
        ix = 100.
        iy = 100.
        fx = 200.
        fy = 100.
        pos = (min(ix, fx), min(iy, fy))
        size = (abs(fx-ix), abs(fy-iy))

        self.painter = MyPaintWidget(pos=pos, size=size)
        parent.add_widget(self.painter.create_figure())
        return parent

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

1 Ответ

1 голос
/ 04 апреля 2020

Документация для StencilView гласит:

Примечание

StencilView не является макетом. Следовательно, вы должны управлять размером и положением своих детей напрямую. Вы можете комбинировать (подклассить оба) StencilView и Layout для достижения поведения макета.

Таким образом, size, который вы установили для его дочерних элементов, будет использоваться, а size_hint игнорируется , Это приводит к size для ваших MyPaintWidget из (100.0, 0.0) для ваших расчетов. И высота 0 никогда не вернет значение True для collide_point().

Однако при использовании RelativeLayout, size_hint не игнорируется, и так как значение по умолчанию для size_hint равно (1,1), ваш MyPaintWidget будет иметь такой же размер, как ваш App. Вычисленные значения size игнорируются, и вы получаете результаты True для большинства ваших вызовов collide_point().

Чтобы получить согласованные результаты, добавьте size_hint=(None, None) к своему MyPaintWidget(pos=pos, size=size). Конечно, с height 0 вы никогда не столкнетесь.

...