ui.Path attributes- would be great if there were mor
@omz, it seems a shame ui.path objects can't contain more attrs than they do. Like stroke and fill colors for example. They are normally short lived objects so should not be a memory issue. But it makes it a little harder to make generic func/methods. Maybe I am missing something. But the below method is flawed even its been called in a Ui.GState() context. Same as ui.shadow, I think would be nice if could be connected to the ui.Path.
I guess it's this way because of the Objective C, iOS frame work. I still mention it, in case I am missing something so simple.
The below is flawed without a lot of extra Params.
def draw_shape(self, shape = 'rect', r = None, stroke = False, fill = False): if not r: r = self.bounds if shape is 'rect': s = ui.Path.rect(*r) elif shape is 'oval': s = ui.Path.rect(*r) else: s = ui.Path.rounded_rect(*r, * self.corner_radius) if stroke: s.stroke() if fill: s.fill()
@Phuket2 what other attributes do you think would be good?
@cook , actually my example is very bad and just wrong. Even so, I think it's still valid idea. As far as I know, if you stroke a ui.'path and then fill a ui.path, the only way to do with different colors is to do it inline. Meaning you have to call ui.set_color in between each call. So you can not pass around a ui.Path and render independently without referencing some vars. Same with the ui.shadow, would be great if it could be applied to a ui.Path.rect etc... Rather than just a global drawing state.
Maybe I haven't thought this through enough. But it appears to me it really limits writing generic ui.Path type code. If you look at line_width for a path, it's a attr, not a ui drawing context global
I think about a function like the below. But I guess what I am really trying to say is that it would be great if ui.Path objects could be fully qualified with Attrs. Then they could be passed around to func/methods and be rendered in completeness at anytime.
There are a lot more attrs than I have shown in my example, was just to give a idea
Edit, btw ui.Path can not be subclassed, I tried 😱
def make_circle(w): # standalone ui.Path r = ui.Rect(0, 0, w, w) s = ui.Path.oval(*r) s.line_width = .5 #valid s.fill_color = 'silver' #invalid s.stroke_color = 'black' #invalid s.shadow = ('yellow', 1, 1, 8) #invalid return s
A path just contains geometry. It draws itself using the current drawing context. It is the drawing context that contains color info.
What you want is a sort of PathOperations class
class PathOp(object): def __init__(self): self._p=ui.Path() self.ops()= # contains a list of method/args def draw(self): for op in self.ops: op(*op) def getattr(self,attr): if attr in self.__dict__.keys(): return self.__dict__[attr] elif hasattr(self._p, attr): return getattr(self._p) elif hasattr(ui, attr): # maybe filter for specific methods like set color return self.wrapper(getattr(ui,attr)) else raise KeyError() def wrapper(self, method): def wrap(*args): self.ops.append(method,args) return wrap
This might not actually be valid, I did not try to run it. The idea is to stire a set of operations, along with a path. Then draw() runs through the drawing operations.
As an aside you can get a few extra path options in objc, objcinstance(somepath)
This discussion is similar to SVG vs HTMLCanvas discussion. The current APIs are like Canvas APIs and @Phuket2's proposal seems to be in line with SVG. @Phuket, may be you can look at SVG and it may not be difficult to implement SVG like design using Canvas APIs..
@JonB , really what I want is something that make sense. line_width is not really geometry. But it's included in the path attrs. Well, I guess I depends on your meaning of geometry.
But I know I can be so wrong.
I know the API is the way it is. It frustrates me, as it does not seem natural. However, often I forget I am using Python on top of iOS. Possibly, you can subclass ui.Path in Objective C, which would make this conversation mute.
Anyway, thank you. I will at your suggestion in more detail.
i agree it is wierd that the drawing context linewidth is overridden by a path's version, but, the line dash and color is set by the context.
I think this may be because paths can do hit detection, optionally checking hit on the filled or stroked portion, so the path needs to know the width. Also, i am wondering if ther is some rendering optimization that can be done once when setting the line width (i.e the actual drawing must compute three curves, the center, inside and outside)-- so by saving the line width in the path, it can optimize redrawing the path multiple times.
Thanks guys. I was just having a little tantrum 😱 I have a hard time as it is with drawing graphics. Just like it for some solutions rather than relying on views and controls in the hope of having something faster and more light weight.
Due to my lack of experience, I keep refactoring trying to come up with something that feels natural to use and reduce the need for lots of lines of code that for the most part is repetitive. I will try maying a shape object. Not sure why, but I have been avoiding this for simple shapes.
Oh well....an another adventure 😱
@Phuket2 I don't have much to add other than what JonB has said... just classing it.
But I really understand what you mean - to have easier ways to accomplish something so simple. Such as:
a = ui.Path.oval(fill_color=red, frame=(0,0,100,100), stroke=1, stroke_color=green, opacity=0.5)
I think that what you're after are similar things that we find in SVG graphic design. For me the ui.Path doesn't seem so different than this... it's just that you have to code in a lot of stuff to get it going. But it seems that there's just certain things in the UI that require this step by step. I also kind of want to try classing just to see.