API Review RT:17407 Canvas Node

Daniel Zwolenski zonski at googlemail.com
Tue Apr 24 17:48:39 PDT 2012


It's still totally possible to resize it though, either through direct calls or by binding the height/width to its container. Don't we then have all the problems you mention whether it's easy or hard, frequent or infrequent to change the bounds? The only way to avoid that would be to make size readonly and pass the dimensions to the constructor. 

On desktops, with resizable windows, and different shape displays, I cant come up with a single use case where I'd not want my Canvas to grow with its window? Maybe a full screen game but since jfx allows the user to exit full screen at whim the ui would need to support resizing anyway. Anyone got any good use cases where they don't want to resize? 

If Canvas is not resizable then the first thing I will do with it is create a custom ResizableCanvas component that extends BorderPane and has a Canvas in it with its bounds bound to the BorderPane. Now it's resizable. Just seems like an unnecessary step, and I'll still be faced with all the issues you mention. I'd rather we had solutions/best-practices for this straight off the shelf. 

As an aside, scrolling I would implement without a scroll pane (more like panning), since most of my use cases are boundless (eg a timeline on a gant chart). I would have my own 'offset' and on mouse drag (or avatar move) I would want to redraw the current display offset by the amount moved and then patch the remaining space. I'd do similar stuff for zoom. 

This is one way the canvas is easier than a SceneGraph for me anyway. In a scene graph I have to create all the nodes in the scene. In a canvas I can cheat and just draw what's in the clip rect. I could create/destroy nodes that intersect with the clip rect but this hurts my head and 'feels' inefficient (not sure if it is or isn't). 


On 25/04/2012, at 8:08 AM, Jim Graham <james.graham at oracle.com> wrote:

> This issue is that if it can be resized fairly commonly by standard facilities then it really needs to be designed around a repaint mechanism.  This is why awt.Canvas and swing.Component have "paint[Content](Graphics)" style methods that are the intended way to render your content.
> 
> Canvas is acting like a retained "painting" in that you render once and then leave it alone for its lifetime.  While it is true that you can directly call the setWidth/Height() methods and it will gain or lose pixels, the scene graph is not in the habit of doing that for you.  If this were designed as a managed node then any time you put it in a layout container it would suddenly get resized by 3rd parties.  The most common example of:
> 
>   Canvas cv = new Canvas(w,h);
>   GraphicsContext gc = cv.getGraphicsContext2D();
>   gc.fillRect(...);
>   borderpane.setCenter(cv);
> 
> would fail because your canvas would not yet have gone through layout.
> 
> So, yes, it is possible for them to detect resizing with the current scheme, but it is not enough for them to "be able to" deal with resizing and damage - the "manageable" model would invite a significant amount of resizing, scrolling, and other types of damage that the above rendering practice just wouldn't be able to deal with.
> 
> Also, scrolling would tend to require you to re-render.  You can't listen to size properties to discover when to repaint for scrolling.  I suppose we could modify the position of the canvas somehow to indicate scrolling, but that isn't as direct as "this part is damaged - repair it now" and the location would only be loosely tied to potential damage and any loose association there that we promote would not cover all possible cases where the Canvas could be damaged.
> 
> So, if we want to invite a layout-able "pane" like awt.Canvas or swing.Panel, then we have to create a fundamentally different top-level design.  I'm not saying we can't do it - but it isn't something to lightly graft onto the current Canvas API...
> 
>           ...jim
> 
> On 4/23/12 3:27 PM, Daniel Zwolenski wrote:
>> Sorry, I'm not following the problem.
>> 
>> Wouldn't the height and width properties provide the callback to say 'I have been resized'? This would include the amount resized-by so the developer could just render the new area if they want (or redraw the whole scene, etc). If the developer chooses not to patch/repaint then that's their choice.
>> 
>> HTML has never had good layout manager concepts so for me it is not the best benchmark in this topic.
>> 
>> What's the requirement to repaint on every frame? I don't follow that.
>> 
>> 
>> On 24/04/2012, at 6:11 AM, Kevin Rushforth<kevin.rushforth at oracle.com>  wrote:
>> 
>>> I wrote:
>>>> I can't think of any reason it should not be resizable.
>>> 
>>> Good think I'm not the only one thinking about it, then. :)
>>> 
>>> Yes, this would be an issue. So unless/until we are ready to deal with this, my earlier suggestion of binding to the width/height property, and adding your own listeners is probably the way to go.
>>> 
>>> -- Kevin
>>> 
>>> 
>>> Jim Graham wrote:
>>>> We would have to deal with damage repair.  Right now it is a persistent rendering, not an area to be "repainted" on every frame.
>>>> 
>>>> If we wanted it to be dynamically and asynchronously resizable we would have to switch to (or provide?) a call-back model of rendering and you would have to keep enough state to be able to render it again on every frame.  HTML5 Canvas demos are not rendered that way, though they can be at their own will - they simply clear the entire canvas and re-render on every pulse.  Or, they just render the new stuff.  Their call.  If they change size, like you can with Canvas, then they are responsible for changing the size and rendering the new stuff - just like if you manually modify the size of our Canvas.
>>>> 
>>>>           ...jim
>>>> 
>>>> On 4/23/12 5:36 AM, Kevin Rushforth wrote:
>>>>> If Canvas were a "Resizable" node then yes, it could do that. Off-hand,
>>>>> I can't think of any reason it should not be resizable.
>>>>> 
>>>>> -- Kevin
>>>>> 
>>>>> 
>>>>> Daniel Zwolenski wrote:
>>>>>>> A Canvas node is a fixed size, so it only resizes when you tell it
>>>>>>> to. If you want it to track the size of the Scene (or similar), you
>>>>>>> could bind its width and height properties and react to change
>>>>>>> notifications.
>>>>>> 
>>>>>> Any reason why Canvas wouldn't just adhere to the Layout algorithm of
>>>>>> the Container it is in? Eg if in a BorderPane center then fill, if in
>>>>>> a GridPane take up that cell, etc. If we want to fix size then we
>>>>>> would use min/max constraints.
>>>>>> That would seem the most sensible and useful thing to me.



More information about the openjfx-dev mailing list