Одной из проблем является использование класса Widget
в качестве контейнера для других Widgets
. Вы должны использовать класс Layout
, чтобы содержать другие Widgets
, в противном случае такие вещи, как pos_hint
, не будут иметь никакого эффекта. Поэтому я изменил ваш код, чтобы MyBackground
продлил FloatLayout
. Также, использование collide_point()
- хорошая идея, но обычно, когда вы переопределяете метод класса, вы также должны вызывать переопределенный метод, используя super()
. Имея это в виду, вот ваш измененный код, который, я думаю, будет работать так, как вы и предполагали:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color, Line, Rectangle
from kivy.uix.textinput import TextInput
from kivy.uix.floatlayout import FloatLayout
from math import *
isLine=False
length=0
class MyBackground(FloatLayout):
def __init__(self, **kwargs):
super(MyBackground, self).__init__(**kwargs)
with self.canvas:
self.bg = Rectangle(source='chouettes3.jpg', pos=self.pos, size=self.size)
self.bind(pos=self.update_bg)
self.bind(size=self.update_bg)
def update_bg(self, *args):
self.bg.pos = self.pos
self.bg.size = self.size
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
with self.canvas:
self.canvas.clear()
d=15
Color(1, 0, 0, 1)
Rectangle(pos=(touch.x-d/2,touch.y-d/2),size=(d,d))
touch.ud['line'] = Line(points=(touch.x, touch.y), width=3)
return super(MyPaintWidget, self).on_touch_down(touch)
def on_touch_up(self, touch):
if 'line' not in touch.ud:
return super(MyPaintWidget, self).on_touch_up(touch)
if self.collide_point(*touch.pos):
touch.ud['line'].points += [touch.x, touch.y]
points=touch.ud['line'].points
length=sqrt(((points[0]-points[2])**2)+((points[1]-points[3])**2))
print (length)
with self.canvas:
d=15
Rectangle(pos=(touch.x-d/2,touch.y-d/2),size=(d,d))
return super(MyPaintWidget, self).on_touch_up(touch)
class MyPaintApp(App):
def build(self):
parent = MyBackground()
painter = MyPaintWidget(pos_hint={'x':0., 'center_y':0.5}, size_hint=(1, 1))
self.textinput = TextInput(text='Hello world', pos=(0,0), size_hint=(0.1,0.1))
parent.add_widget(painter)
parent.add_widget(self.textinput)
return parent
if __name__ == '__main__':
MyPaintApp().run()
Я также удалил неиспользуемый код в методе build()
.
Как код остается, щелкнув по TextInput
, вы не начнете новую строку, но вы можете закончить строку за TextInput
. Если вы не хотите, чтобы это происходило, вы можете добавить проверку столкновения в методе on_touch_up()
, чтобы обработать его, как показано ниже:
def on_touch_up(self, touch):
if 'line' not in touch.ud:
return super(MyPaintWidget, self).on_touch_up(touch)
ti = App.get_running_app().textinput
if self.collide_point(*touch.pos) and not ti.collide_point(*touch.pos):
touch.ud['line'].points += [touch.x, touch.y]
points=touch.ud['line'].points
length=sqrt(((points[0]-points[2])**2)+((points[1]-points[3])**2))
print (length)
with self.canvas:
d=15
Rectangle(pos=(touch.x-d/2,touch.y-d/2),size=(d,d))
else:
self.canvas.clear()
return super(MyPaintWidget, self).on_touch_up(touch)