class Scaled(Widget): def __init__(self, **kwargs): super(Scaled, self).__init__(**kwargs) self.elements = [] self.pointsize = 5 # this multiplies by two according to kivy docs with self.canvas: self._fbo = Fbo(size=self.size) self._rect = Rectangle(texture=self._fbo.texture) with self._fbo: Color(1, 1, 1) self._fborect = Rectangle(size=self._fbo.size) Color(0, 0, 1) self._points = Point(pointsize=self.pointsize) self._fbo.add_reload_observer(self._clear_fbo) self.bind(pos=self._update_rect, size=self._update_rect) def drawpoint(self, x, y): self.elements.append([x, y]) self._points.add_point(x, y) def draw(self, matrix): self._points.points = [] self._clear_fbo() for point in matrix: x = int(point[0] * (self.pointsize * 2) + self.pointsize) y = int(point[1] * (self.pointsize * 2) + self.pointsize) self.drawpoint(x, y) # RELOADING THE BUFFER AT ANY CHANGE def _clear_fbo(self, fbo=None): ''' This will reload the framebufferer either by the call of the observer or by the deletion of a point''' if fbo is None: fbo = self._fbo fbo.bind() fbo.clear_buffer() fbo.add(Color(1, 1, 1)) fbo.add(self._fborect) fbo.add(Color(0, 0, 1)) fbo.add(self._points) fbo.release() def _update_rect(self, instance, value): self._fbo.size = instance.size self._fborect.size = instance.size self._rect.size = instance.size self._rect.pos = instance.pos self._rect.texture = self._fbo.texture
class Scaled(Widget): def __init__(self, **kwargs): super(Scaled, self).__init__(**kwargs) self.elements = [] self.pointsize = 5 # this multiplies by two according to kivy docs with self.canvas: self._fbo = Fbo(size=self.size) self._rect = Rectangle(texture=self._fbo.texture) with self._fbo: Color(1, 1, 1) self._fborect = Rectangle(size=self._fbo.size) Color(0, 0, 1) self._points = Point(pointsize=self.pointsize) self._fbo.add_reload_observer(self._clear_fbo) self.bind(pos=self._update_rect, size=self._update_rect) def drawpoint(self, x, y): self.elements.append([x, y]) self._points.add_point(x, y) def draw(self, matrix): self._points.points = [] self._clear_fbo() for point in matrix: x = int(point[0] * (self.pointsize * 2) + self.pointsize) y = int(point[1] * (self.pointsize * 2) + self.pointsize) self.drawpoint(x, y) # RELOADING THE BUFFER AT ANY CHANGE def _clear_fbo(self, fbo=None): """ This will reload the framebufferer either by the call of the observer or by the deletion of a point""" if fbo is None: fbo = self._fbo fbo.bind() fbo.clear_buffer() fbo.add(Color(1, 1, 1)) fbo.add(self._fborect) fbo.add(Color(0, 0, 1)) fbo.add(self._points) fbo.release() def _update_rect(self, instance, value): self._fbo.size = instance.size self._fborect.size = instance.size self._rect.size = instance.size self._rect.pos = instance.pos self._rect.texture = self._fbo.texture
def test_point_add(self): from kivy.uix.widget import Widget from kivy.graphics import Point, Color r = self.render wid = Widget() with wid.canvas: Color(1, 1, 1) p = Point(pointsize=10) p.add_point(10, 10) p.add_point(90, 10) p.add_point(10, 90) p.add_point(50, 50) p.add_point(10, 50) p.add_point(50, 10) r(wid)
class Grid( Widget ): point_size = NumericProperty(10) def __init__(self, **kwargs): super(Grid, self).__init__(**kwargs) # Which elements exist in the grid in the normalized coordinates self.elements = [] # If active, it can't be modified self.active = False # To the canvas, we add the FrameBufferObject and the rect to show it with self.canvas: self.fbo = Fbo(size=self.size) self.rect = Rectangle(texture=self.fbo.texture) # Color(1,0,0) # self.rect = Rectangle(size = self.size, pos = self.pos) # To the FrameBufferObject I set the color and add the point list with self.fbo: Color(1,1,1) self.points = Point( pointsize=self.point_size ) # add some observers to the fbo, changes for the point_size (grid # resizing) and widget resizing self.fbo.add_reload_observer(self._populate_fbo) self.bind( point_size = self._reshape ) self.bind( size = self._update_rect, pos = self._update_rect ) def on_touch_down(self, touch): ''' Handle adding/removing points when the grid is not active''' if not self.active and self.collide_point(*touch.pos): # Move to a 0,0 from where the widget starts x = touch.x - self.x y = touch.y - self.y self.add_point( [x,y] ) return True return super(Grid, self).on_touch_down(touch) def normalize(self, coords): ''' normalization of coordinates, it will transform any given point in the widget to its corresponding normalized coords ''' # TODO: Create a picture to describe what are the normalized coordinates if type(coords) is tuple: coords = list(coords) if type(coords) is list: for ind in range(len(coords)): coords[ind] = int( coords[ind] // ( self.points.pointsize * 2 ) ) return coords else: return int( coords // ( self.points.pointsize * 2 ) ) def adjust(self, coords): ''' adjustment of a normalized coordinate to the real coordinate using the current point size as a guide ''' if type(coords) is tuple: coords = list(coords) if type(coords) is list: for ind in range(len(coords)): coords[ind] = int( coords[ind] * ( self.points.pointsize * 2 ) + self.points.pointsize ) return coords else: return int( coords * ( self.points.pointsize * 2 ) + self.points.pointsize ) def add_point(self, point, redraw=True): ''' method to add a point to the grid if it doesn't exist if it's there, remove it''' point = self.normalize(point) if point in self.elements: where = self.elements.index( point ) # Steal the reference to the vector of points points = self.points.points self.points.points = [] # Clean the desired point del(points[where*2]) del(points[where*2]) # Reassign the property for the context to know (kivy weird things) self.points.points = points # Remove from the historical del(self.elements[where]) # Redraw if asked for if redraw: self._populate_fbo(self.fbo) else: # add the normalized coords to the element list # it has to be copied because the adjust method will modify # the elements in points self.elements.append(point[:]) # add the point to the visible points using the adjusted coordinates # the * leading self.adjust is to unpack the resulting array self.points.add_point( *self.adjust(point) ) # print(self.elements) def next(self, instance): if len(self.elements) == 0: return # calculate the survivors nextgen = automaton.survivors(self.elements) # print(nextgen) # calculate any possible newborns nextgen += automaton.births(self.elements) # print(nextgen) # replace the current elements self.elements = nextgen # The vector comes with minivectors within, which is fine for the # list of elements but doesn't work for the adjustment of points in # the screen nextgen = [ i for cell in nextgen for i in cell ] # adjust the elements to the actual coordinates nextgen = self.adjust( nextgen ) # assign the vector back self.points.points = nextgen # redraw self._populate_fbo() def clear(self, instance): self.elements = [] self.points.points = [] self._populate_fbo() # RELOADING THE BUFFER AT ANY CHANGE def _populate_fbo(self, fbo = None): ''' This will reload the framebufferer either by the call of the observer or by the deletion of a point''' if fbo is None: fbo = self.fbo fbo.bind() fbo.clear_buffer() fbo.add(self.points) fbo.release() def _reshape(self, instance, value): # There are no elements if len(self.elements) == 0: # We just update the points to be drawn self.points.pointsize = self.point_size # If we do have elements else: # steal the reference to the vector points = self.points.points self.points.points = [] # normalize using current value points = self.normalize( points ) # reassing the value self.points.pointsize = self.point_size # adjust using new value points = self.adjust( points ) # assign the vector back self.points.points = points # redraw self._populate_fbo() # REDRAWING THE FBO AND THE def _update_rect( self, instance, value ): self.fbo.size = instance.size self.rect.size = instance.size self.rect.pos = instance.pos self.rect.texture = self.fbo.texture
def update_canvas(self, *args): for i, value in enumerate(self.values): self._previous_values.append(None) if self.needles_props: props = self.needles_props[i] color = Color(* props.get('color') or \ ((i%3)*.5, ((i+1)%3)*.5, ((i+2)%3*.5))) length = props.get('length') or 1.0 width = props.get('width') or 1.0 else: color = Color((i % 3) * .5, ((i + 1) % 3) * .5, ((i + 2) % 3 * .5)) length = 1.0 width = 2.0 self._needles_props.append({ 'color': color, 'width': width, 'length': length }) self._needles.append(InstructionGroup()) self.canvas.clear() x0, y0 = self.pos with self.canvas: e_width = self.width / 2 e_height = self.height / 2 # Default color Color(1, 1, 1) # Labels if self.labels: for value, text in self.labels: angle = self.begin - \ ((self.begin-self.end) / (self.maxi - self.mini) * value) pos = ellipse(x0 + e_width, y0 + e_height, e_width - 30, e_height - 30, angle) self._labels.append( Label( text=text, color=(1, 1, 1, .5), pos=pos, size=('1dp', '1dp'), #self.texture_size, font_size='20sp', bold=True)) x1, y1 = ellipse(x0 + e_width, y0 + e_height, e_width, e_height, angle) x2, y2 = ellipse(x0 + e_width, y0 + e_height, e_width - 10, e_height - 10, angle) Line( points=[x1, y1, x2, y2], width=2, #cap = 'round', close=False) else: # Default : label on dizains for i in range(0, -self.mini + self.maxi + 1, 10): angle = self.begin - \ ((self.begin-self.end) / (self.maxi - self.mini) * i) pos = ellipse(x0 + e_width, y0 + e_height, e_width - 30, e_height - 30, angle) self._labels.append( Label( text='%d' % (i + self.mini), color=(1, 1, 1, .5), pos=pos, size=('1dp', '1dp'), #self.texture_size, font_size='20sp', bold=True)) x1, y1 = ellipse(x0 + e_width, y0 + e_height, e_width, e_height, angle) x2, y2 = ellipse(x0 + e_width, y0 + e_height, e_width - 10, e_height - 10, angle) Line( points=[x1, y1, x2, y2], width=2, #cap = 'round', close=False) # Graduations p = Point() if self.graduations: pass # XXX TODO else: # Default : point on units for i in range(0, -self.mini + self.maxi + 1): angle = self.begin - \ ((self.begin-self.end) / (self.maxi - self.mini) * i) if i % 10 == 0: # Label, no graduation continue x, y = ellipse(x0 + e_width, y0 + e_height, e_width - 5, e_height - 5, angle) p.add_point(x, y) # Save values used in update_values to display needle(s) self._e_width = e_width self._e_height = e_height self._scale = (self.begin - self.end) / (self.maxi - self.mini) self._x0, self._y0 = self.pos[0] + e_width, self.pos[1] + e_height self._ready = True # Display needle(s) self.update_values()