我有两个三个嵌套的小部件来处理on_touch_down事件,点击第一个父级,事件被感知到第二个,然后是第三个。通过这次点击,第三个小部件应该在它的画布上绘制,但这不会发生。
我理解画布对象及其组的动态。所以我真的不明白为什么会发生这种情况
class Spline_guide(DragBehavior, Button):
def __init__(self, **kw):
super(Spline_guide, self).__init__(**kw)
self.bind(pos = self.update_spline , size = self.update_spline)
def update_spline(self, *l):
self.pos = self.parent.pos
return self
def show_spline(self,*l):
print 'show spline'
with self.canvas:
Color(0,1,0)
######## THIS ISTRUCTION DOESN'T WORK
Ellipse(pos = (100,100), size = (100,100))
return self
def hide_spline(self, *l):
print 'hide spline'
self.canvas.clear()
return self
class Editable_point(DragBehavior, Widget):
def __init__(self, name,x,y, **kw):
super(Editable_point, self).__init__(**kw)
self.drag_rectangle = (0,0 ,800,300)
self.drag_timeout = 10000000
self.drag_distance = 0
self.name = name
self.pos = (x - DOT_DIMENSION / 2,y - DOT_DIMENSION / 2)
self.size = (DOT_DIMENSION, DOT_DIMENSION)
self.spline = Spline_guide()
self.add_widget(self.spline)
self.SHOW_SPLINE = False
self.bind(pos = self.check_pos)
def check_pos(self, *l):
self.area = self.parent.parent
self.x = self.x if self.x > self.area.x else self.area.x
self.y = self.y if self.y > self.area.y else self.area.y
return self
def draw_point(self):
self.area = self.parent.parent
self.drag_rectangle = (self.area.x, self.area.y, self.area.width, self.area.height)
self.canvas.clear()
with self.canvas:
Color(1,0,0)
Ellipse(pos=self.pos, size=self.size)
return self
def on_enter(self, pop):
def wrap(l):
if l.text in ['start','stop']:
print 'you can not use start or stop as name'
pop.dismiss()
return wrap
if self.name in ['start','stop']:
pop.dismiss()
print 'you can not edit the name of start or stop point'
return wrap
self.name = l.text
pop.dismiss()
return wrap
def show_info(self, *l):
graph = self.parent.parent.graph
X_OFFSET = graph._plot_area.x + self.parent.x - DOT_DIMENSION / 2
Y_OFFSET = graph._plot_area.y + self.parent.y - DOT_DIMENSION / 2
_x = self.x - X_OFFSET
_y = self.y - Y_OFFSET
x, y = normalize(graph.xmin,graph.ymin,graph.xmax,graph.ymax,graph._plot_area.width,graph._plot_area.height, _x, _y)
point_name = TextInput(text=self.name, multiline = False)
point_info = Popup(title ="X: {} Y: {}".format(x,y), content = point_name, size_hint=(None,None), size=(200,100))
point_name.bind(on_text_validate=self.on_enter(point_info))
point_info.open()
return self
def on_touch_down(self, *l):
if self.SHOW_SPLINE:
self.SHOW_SPLINE = False
self.spline.hide_spline()
else:
self.SHOW_SPLINE = True
self.spline.show_spline()
return self
class Editable_line(Widget):
def __init__(self, **kw):
super(Editable_line, self).__init__(**kw)
self._old_ = [100,100]
self.old_pos = [0,0]
self.bind(pos=self.update_line, size=self.update_line)
def replace_start_stop(self, new_elem):
elem = filter(lambda x: x.name == new_elem.name, [ i for i in self.children if hasattr(i,'name')])
if elem: self.remove_widget(elem[0])
self.add_widget(new_elem)
return self
def update_points(self):
r_x = float(Window.size[0]) / float(self._old_[0])
r_y = float(Window.size[1]) / float(self._old_[1])
for p in [ i for i in self.children if hasattr(i,'name')]:
new_x = p.x * r_x
new_y = p.y * r_y
p.x = new_x
p.y = new_y
p.size = (DOT_DIMENSION, DOT_DIMENSION)
return self
def update_line(self, *a):
self.pos = self.parent.pos
self.size = self.parent.size
self.parent.graph.pos = self.pos
self.parent.graph.size = self.size
self.parent.graph._redraw_size()
#Coordinate per start e stop personalizzare sul graph
y = self.parent.graph._plot_area.y + self.y
x = self.parent.graph._plot_area.x + self.x
h = self.parent.graph._plot_area.height
w = self.parent.graph._plot_area.width
self.replace_start_stop(Editable_point('start', x, y + h / 2))
self.replace_start_stop(Editable_point('stop', x + w, y + h / 2))
self.update_points()
self._old_ = Window.size
return self.draw_line()
def sort_points(self):
self.children = sorted(self.children , key=attrgetter('x'))
return self
def control_presence(self,coordinates):
x = int(coordinates.x)
y = int(coordinates.y)
x_range = range(x-DOT_DIMENSION, x+DOT_DIMENSION)
y_range = range(y-DOT_DIMENSION, y+DOT_DIMENSION)
for p in [ i for i in self.children if hasattr(i,'name')]:
if int(p.x) in x_range and int(p.y) in y_range: return p
return False
def on_touch_down(self,coordinates):
#add points
p = self.control_presence(coordinates)
if p:
if not coordinates.is_double_tap:
return p.on_touch_down(coordinates)
return p.show_info(coordinates)
x = int(coordinates.x)
y = int(coordinates.y)
p = Editable_point('new point', x, y)
p.size = (DOT_DIMENSION, DOT_DIMENSION)
self.add_widget(p)
return self.draw_line()
def remove_point(self,coordinates):
p = self.control_presence(coordinates)
if p:
if p.name in ['start','stop']: print 'you can\'t delete start or stop point' else: self.remove_widget(p)
return self.draw_line()
def draw_line(self):
self.sort_points()
self.canvas.before.clear()
_l = list()
for p in [ i for i in self.children if hasattr(i,'name')]:
_l.append(p.x + DOT_DIMENSION/2)
_l.append(p.y + DOT_DIMENSION/2)
p.draw_point()
with self.canvas.before:
Color(0,0.8,1)
Line(points=_l, witdth = LINE_WIDTH)
return self
def on_touch_move(self, coordinates):
p = self.control_presence(coordinates)
if p:
if p.name in ['start','stop']:
return self.parent.on_touch_up(coordinates)
p.on_touch_move(coordinates)
self.draw_line()
return self
这是我的一段代码,展示了如何链接类。 Spline_guide没有绘制任何内容。想法?
答案 0 :(得分:1)
Widget
的 Widget
将在后者Widget
的{{1}}中绘制。当您致电canvas
时(即self.canvas.clear()
),您将移除所有儿童画布。
您可以使用Editable_point
或canvas.before
代替您的绘图,也可以保存说明并稍后修改:
canvas.after
然后你根本不需要清除def __init__(self, **kwargs):
...
with self.canvas:
self.draw_color = Color(0, 1, 0, 1)
self.draw_ellipse = Ellipse(pos=self.pos, size=self.size)
def draw_point(self):
...
self.draw_ellipse.pos = self.pos
self.draw_ellipse.size = self.size
。这是首选解决方案,因为它提供了最佳性能。