[wxruby-users] Tearing in my buffered animation test script...

Jay McGavren
Sat, 01 Dec 2007 20:55:10 -0000

Excellent, excellent!  All tearing is now gone on Windows.  (I meant
to mention my platform before, but forgot.)

I kept evt_paint, which I need just in case the window needs redrawing
(or at least, I will in my final application).  But I created a
separate routine that just calls Window.paint, and that''s what I use
in my main animation loop (as well as evt_paint).  And draw_bitmap is
a lot cleaner, as well, so thanks for pointing that out.  Revised code
is below.

You''ve saved me days of headaches, so many thanks!

-Jay McGavren
http://jay.mcgavren.com/zyps


require ''rubygems''
require ''wx''

class MyApp < Wx::App

  def on_init

    #Containing frame.
    frame = Wx::Frame.new(nil, :size => [300, 300])
    frame.show

    #Offscreen drawing buffer.
    buffer = Wx::Bitmap.new(300, 300)

    #Displays drawing.
    window = Wx::Window.new(frame, :size => [300, 300])
    window.evt_paint do |event|
      update_window(window, buffer)
    end

    #Animate.
    (1..40).each do |i|
      #Clear screen.
      buffer.draw do |surface|
        surface.pen = Wx::Pen.new(Wx::Colour.new(0, 0, 0), 0)
        surface.brush = Wx::BLACK_BRUSH
        surface.draw_rectangle(0, 0, 300, 300)
      end
      #Draw line.
      buffer.draw do |surface|
        surface.pen = Wx::Pen.new(
          Wx::Colour.new(128, 255, 128),
          3
        )
        surface.pen.cap = Wx::CAP_ROUND
        surface.draw_line(i, 0, i+100, 100)
      end
      #Update screen.
      update_window(window, buffer)
      sleep 0.1
    end

  end

  def update_window(window, buffer)
    window.paint do |dc|
      #Copy the buffer to the viewable window.
      dc.draw_bitmap(buffer, 0, 0, false)
    end
  end

end

app = MyApp.new
app.main_loop

> On 12/1/07, Mario Steele <mario at ruby-im.net> wrote:
> > Two other things.
> > 1.) If your doing the actual painting when evt_paint() is called, then
you
> > do not need to create a ClientDC  (Which is what window.paint does)
> > 2.) You can skip evt_paint() and window.refresh /window.update all
> > together, and just call window.paint, to paint to the window, when
your
> > finished with the painting on the Buffer.
> >
> > Just a couple of suggestions for ya, which should take care of the
flicker
> > and tearing.
> >
> > Mario Steele
>
> Just a quick follow up.  What I meant to say, was that you need to use one,
> or the other, as your basically creating two DC''s within a single
event,
> which would be causing the flicker.  So, you need to either create a Thread
> to draw it, or you need to take out the paint and draw within the
> evt_paint() proc.  Sorry if that didn''t make sense earlier. ;-)