[wxruby-users] paint_buffered

Alex Fenton alex at pressure.to
Mon Nov 3 19:52:02 EST 2008


Anton Hörnquist wrote:
> Alex Fenton wrote:
>   
>> It would be good to see some code that we can actually run, and more
>> information about the app - eg is the refreshing event-driven (the user
>> doees something, the display changes) or time-driven? 
> Sure! Find memu.rb attached. It's a little hack, a monome emulator. You 
> will need rosc by hans fugal for it to work - hans.fugal.net/src/rosc/. 
> See www.monome.org for details about the actual device.

Thanks, looks interesting although I have only a hazy idea what it's 
about. Please don't take this the wrong way, but if you're sending in 
code for advice it's much preferred that the code is self-contained (as 
yours is) and doesn't have external dependencies that need to be 
installed (as yours does). I and others on this list are really happy to 
try things out and advise, but it's too much to expect people to 
download, compile and install third-party libs to do that.
>> Depending on this different things might help - eg preparing drawing in
>> idle time, only updating voided parts of the canvas, etc
>
>
> The MemuWindow is refreshed when a user presses or releases one of the 
> buttons on the virtual device (mouse cursor and 
> evt_left_down/evt_left_up). The box around the button is thickened. 
> Also, when certain osc parameters are received, the leds within the 
> buttons are lit up!
>   
I haven't tried it out, but from reviewing your script perhaps I can 
make a few suggestions:

First, and most important, it looks like you're repainting the whole 64 
buttons when, for any given event, only one has changed state. An 
alternate and more efficient approach might be to make each LED a 
separate widget, an instance of a class inheriting from Wx::Window. It 
knows its state, and draws its own rectangle. The TargetControl class in 
the events.rb sample would be an example to look at for this.

You could then layout the buttons using a 8x8 Wx::GridSizer, store them 
in a two dimensional array (faster lookup than your buttons.detect 
method), then when an event is received, change the state of the 
relevant button and call refresh (or update) on it alone. This means 
that a much smaller amount of drawing has to be done for each change. It 
would also make your handling of left-down and left-up simpler as you 
wouldn't have to test which LED might have been hit.

Second, you might see whether, if each LED has only an on and off state 
and these look the same, whether it is faster to cache an image for each 
state and do draw_bitmap for each button. It may or may not be faster 
than drawing each one with primitives like draw_rectangle.

Third, you could try playing around with, instead of having the server 
in a different ruby thread, polling it for messages in evt_idle or 
directly in a timer (Wx::Timer.every(20) { server.serve }). Also, is it 
possible to have update the UI based only on server messages - ie 
evt_left_down only notifies the server of change of state, and the 
server notifies back to update the GUI? This design is generally more 
scalable, in my experience, than having the state-changing event handler 
also update the UI.
> There is really no complex drawing going on, just a bunch of rectangles 
> :), but it's rather important that the stuff is updated in realtime. 
> Perhaps Ruby aint the ideal language for this.
Ruby's certainly slow, and while wxRuby's a decently fast GUI toolkit, 
the SWIG wrapping has significant overhead to each method call. That 
said, I used Jay McGavren's Zyps library, which draws a lot of 
primitives from scratch on a timed basis, and was able to get pretty 
smooth animation (definitely more than 20fps I think). You might find 
those wxruby-users threads in Dec 2007 / Jan 2008 of interest.

hth
alex


More information about the wxruby-users mailing list