[FXRuby] How to force a paint on a canvas

Hello all,

I am working on a simple turtle graphics demonstration program that I
can use to give a demonstration to several classes of 1st graders. The
problem I am having is that I can draw on the canvas widget, but I can’t
force it repaint after I draw. The canvas code looks like below:

@outputCanvas.connect(SEL_PAINT) do |sender, sel, event|
dc = FXDCWindow.new(@outputCanvas)
dc.background = FXColor::White
dc.foreground = FXColor::White
dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w,
event.rect.h)
dc.foreground = FXColor::Red
@actions.each do |action|
action.do(dc)
end

dc.fillRectangle(0,0,@x,@y)

@x += 10; @y += 10

dc.end

end

on a paint it iterates through a list of actions which do lines and
turns (for now). It works fine except that I have to cover and uncover
the window to see the results.

I tried FXWindow#repaint and FXApplication#repaint to no avail.

Any ideas?

Thanks,

Steve Tuckner

Hello all,

I am working on a simple turtle graphics demonstration program that I
can use to give a demonstration to several classes of 1st graders. The
problem I am having is that I can draw on the canvas widget, but I can’t
force it repaint after I draw. The canvas code looks like below:

@outputCanvas.connect(SEL_PAINT) do |sender, sel, event|
dc = FXDCWindow.new(@outputCanvas)
dc.background = FXColor::White
dc.foreground = FXColor::White
dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w,
event.rect.h)
dc.foreground = FXColor::Red
@actions.each do |action|
action.do(dc)
end

dc.fillRectangle(0,0,@x,@y)

@x += 10; @y += 10

dc.end

end

on a paint it iterates through a list of actions which do lines and
turns (for now). It works fine except that I have to cover and uncover
the window to see the results.

I tried FXWindow#repaint and FXApplication#repaint to no avail.

Any ideas?

Try @outputCanvas.update, although you probably want to reorganize your code
and connect it to SEL_MOTION instead of SEL_PAINT. As you are seeing,
SEL_PAINT only gets sent when the window has been obscured and is
uncovered. Look at scribble.rb in the ‘examples’ directory of the distribution.

···

On Tue, 28 Jan 2003 07:28:34 +0900 Steve Tuckner STUCKNER@MULTITECH.COM wrote:

Thanks,

Steve Tuckner


“Daniel P. Zepeda” <daniel@z,e,p,e,d,a,-,z,o,n,e.net>
(Remove commas for address)

Steve Tuckner wrote:

I am working on a simple turtle graphics demonstration program that I
can use to give a demonstration to several classes of 1st graders. The
problem I am having is that I can draw on the canvas widget, but I can’t
force it repaint after I draw. The canvas code looks like below:

There’s a reasonably good discussion of this in the FOX FAQ:

http://www.fox-toolkit.org/faq.html

under the topic “When do I call flush(), forceRefresh(), refresh() and
update() after a change?”.

As Daniel pointed out in his reply, the function you want to call is
FXCanvas#update, which should mark the drawing canvas as “dirty” and
thus make it a candidate for repainting at some point in the future.
Usually, that time “in the future” arrives pretty quickly (as soon as
you return to the event loop), but it’s an important distinction to
note. As the FAQ states, if you want the repaints to take place
immediately, be sure to follow the call to FXCanvas#update with a call
to FXApp#flush. Since a flush() can be expensive, I’d try it without it
first to see if you’re OK with the delayed results.

Hope this helps,

Lyle

Daniel P. Zepeda wrote:

Try @outputCanvas.update, although you probably want to reorganize your code
and connect it to SEL_MOTION instead of SEL_PAINT. As you are seeing,
SEL_PAINT only gets sent when the window has been obscured and is
uncovered. Look at scribble.rb in the ‘examples’ directory of the distribution.

I agree with everything except the idea about tying this to the
SEL_MOTION message. If you did this, the window would no longer get
painted in response to normal expose events (i.e. covering the window
up, and then uncovering it). Furthermore, all of that repainting in
response to every mouse motion over the canvas would be extremely
inefficient.

Leave the handler code alone, and just add calls to FXCanvas#update
elsewhere in the program as appropriate, e.g. maybe when the kid adds a
new action to the list of commands, or in response to clicking a
“Redraw” button or something.

Thanks to both replies!

It works spiffy now and update works fine for my purposes. I guess I looked
for and invalidate (Windows/Mac background) method or a repaint method.
There was a repaint method but it didn’t do any good. What is that for by
the way?

Thanks again for your help!

Steve Tuckner

···

-----Original Message-----
From: Lyle Johnson [mailto:lyle@users.sourceforge.net]
Sent: Monday, January 27, 2003 6:19 PM
To: ruby-talk@ruby-lang.org
Cc: daniel@zepeda-zone.net
Subject: Re: [FXRuby] How to force a paint on a canvas.

Steve Tuckner wrote:

I am working on a simple turtle graphics demonstration
program that I
can use to give a demonstration to several classes of 1st
graders. The

problem I am having is that I can draw on the canvas widget, but I
can’t
force it repaint after I draw. The canvas code looks like below:

There’s a reasonably good discussion of this in the FOX FAQ:

Frequently Asked Questions

under the topic “When do I call flush(), forceRefresh(),
refresh() and
update() after a change?”.

As Daniel pointed out in his reply, the function you want to call is
FXCanvas#update, which should mark the drawing canvas as “dirty” and
thus make it a candidate for repainting at some point in the future.
Usually, that time “in the future” arrives pretty quickly (as soon as
you return to the event loop), but it’s an important distinction to
note. As the FAQ states, if you want the repaints to take place
immediately, be sure to follow the call to FXCanvas#update
with a call

to FXApp#flush. Since a flush() can be expensive, I’d try it
without it
first to see if you’re OK with the delayed results.

Hope this helps,

Lyle

Daniel P. Zepeda wrote:

Try @outputCanvas.update, although you probably want to reorganize your
code and connect it to SEL_MOTION instead of SEL_PAINT. As you are seeing,
SEL_PAINT only gets sent when the window has been obscured and is
uncovered. Look at scribble.rb in the ‘examples’ directory of the
distribution.

I agree with everything except the idea about tying this to the
SEL_MOTION message. If you did this, the window would no longer get
painted in response to normal expose events (i.e. covering the window
up, and then uncovering it). Furthermore, all of that repainting in
response to every mouse motion over the canvas would be extremely
inefficient.

I agree it is not a good idea to connect the code Steve posted to SEL_MOTION. I
didn’t make myself clear. I said “reorganize your code and connect it to
SEL_MOTION, look at scribble.rb.” What I meant was that if he changed his code
a bit, and connected the changed code to SEL_MOTION like is done in the
scribble example, that he could get the effect of seeing the box drawn by
clicking and dragging. I admit I’m not familiar with “turtles”, (is that like
the thing that the Logo people did in the 70’s, and Dan Kaehler redid for
Smalltalk?) So maybe my suggestion is off the mark.

···

On Tue, 28 Jan 2003 09:39:36 +0900 Lyle Johnson lyle@users.sourceforge.net wrote:

Leave the handler code alone, and just add calls to FXCanvas#update
elsewhere in the program as appropriate, e.g. maybe when the kid adds a
new action to the list of commands, or in response to clicking a
“Redraw” button or something.


“Daniel P. Zepeda” <daniel@z,e,p,e,d,a,-,z,o,n,e.net>
(Remove commas for address)

Steve Tuckner wrote:

It works spiffy now and update works fine for my purposes. I guess I looked
for and invalidate (Windows/Mac background) method or a repaint method.
There was a repaint method but it didn’t do any good. What is that for by
the way?

FXWindow#repaint causes a window to process all of its backlogged
SEL_PAINT messages. Put another way, if some sequence of events has
caused part(s) of a window to become dirty, calling repaint() on that
window should cause the needed SEL_PAINT messages to be fired.

The reason this had no effect in your program was that, as far as FOX
knew, the canvas wasn’t dirty.

Daniel P. Zepeda wrote:

Try @outputCanvas.update, although you probably want to reorganize your
code and connect it to SEL_MOTION instead of SEL_PAINT. As you are
seeing, SEL_PAINT only gets sent when the window has been obscured and is
uncovered. Look at scribble.rb in the ‘examples’ directory of the
distribution.

I agree with everything except the idea about tying this to the
SEL_MOTION message. If you did this, the window would no longer get
painted in response to normal expose events (i.e. covering the window
up, and then uncovering it). Furthermore, all of that repainting in
response to every mouse motion over the canvas would be extremely
inefficient.

I agree it is not a good idea to connect the code Steve posted to SEL_MOTION.
I didn’t make myself clear. I said “reorganize your code and connect it to
SEL_MOTION, look at scribble.rb.” What I meant was that if he changed his
code a bit, and connected the changed code to SEL_MOTION like is done in
the scribble example, that he could get the effect of seeing the box drawn by
clicking and dragging. I admit I’m not familiar with “turtles”, (is that like
the thing that the Logo people did in the 70’s, and Dan Kaehler redid for
Smalltalk?) So maybe my suggestion is off the mark.

And after re-reading it again, I still think I’m not clear enough. I mean
adding code to a handler for SEL_MOTION, and basically leaving the handler
for SEL_PAINT alone.

I think maybe I need some sleep, I’m not even making sense to myself!

···

On Tue, 28 Jan 2003 12:47:37 +0900 “Daniel P. Zepeda” daniel@zepeda-zone.net wrote:

On Tue, 28 Jan 2003 09:39:36 +0900 > Lyle Johnson lyle@users.sourceforge.net wrote:

Leave the handler code alone, and just add calls to FXCanvas#update
elsewhere in the program as appropriate, e.g. maybe when the kid adds a
new action to the list of commands, or in response to clicking a
“Redraw” button or something.


“Daniel P. Zepeda” <daniel@z,e,p,e,d,a,-,z,o,n,e.net>
(Remove commas for address)


“Daniel P. Zepeda” <daniel@z,e,p,e,d,a,-,z,o,n,e.net>
(Remove commas for address)