Racket/gui: how to use canvas%'s init-auto-scrollbar method

I'm developing a new canvas by subclassing canvas%. I would like for my new canvas to manage the scrollbars automatically and am attempting to setup automatic scrollbars with init-auto-scrollbars.

My thought is that I need to call init-auto-scrollbars from my on-paint method after drawing, because at that point I will know the size needed for my virtual canvas. Unfortunately, init-auto-scrollbars is triggering another on-paint call, leading to an infinite loop.

How else can I set the virtual size of the canvas? Is there a better place to do this than on-paint? Or is the answer to just use manual scrollbars?

I am curious how is it possible to know the size only after drawing it? The on-paint method only receives a draw context, dc instance, so everything that you need to draw should already be present in the canvas% instance, and you could compute the size at any time, not just while drawing it.

In any case, you can use queue-callback as shown below, but, as you noticed, this results in another call to on-paint, since you changed the virtual size. This will result in your application drawing more than it is needed. You should only call it if the virtual size changes, for example inside a when form:

  (lambda ()
    (init-auto-scrollbars ...)))


Thanks for the response. This is kind of what I expected. I am primarily rendering text snips, so I have to run through a potentially large number of snips and calculate their size. I have to do this anyway while drawing, so I was hoping there was some way to update the virtual size from on-paint. Of course, only calling init-auto-scrollbars when the virtual size actually changes is a reasonable solution, although it triggers an additional on-paint call.

I was a little surprised that init-auto-scrollbars actually triggers a full on-paint. I guess it is the (send wx set-scrollbars ...) that does it. And I suppose it makes sense because this could potentially change the viewable canvas area and not just the rendering of the scrollbars themselves(I'm making some assumptions here).