[fxruby-users] Getting fewer paints per second than I expected
Joel VanderWerf
vjoel at path.berkeley.edu
Sun Nov 5 18:22:06 EST 2006
Wayne Conrad wrote:
> I've got a program that puts 20 text labels in the main window. Each
> label updates itself to a global counter on SEL_UPDATE. The counter
> increments 10 times a second.
>
> To my surprise, the labels skip counter updates. I expected to see
> each label painting a new timer value 10 times per second. Instead,
> each label paints about 3 times per second. CPU is about 100% idle
> when the program is running.
>
> Have I made a newbie mistake? Is this a question for the regular Fox
> list?
I verified your observations with fox16 (fxruby): updates skip and cpu <
1%. In addition I checked that the timer is really called 10 times
per second (it turns out to be between 9 and 10 times per second,
actually, probably due to the time it takes to re-register the timer).
It may be that using SEL_UPDATE works better in pure fox than in fxruby,
but in my experience it's better to take control of the updates yourself
if you want them done promptly. You can do this by setting up an
observer relationship and using that to set the label text when the
variable changes.
This is part of the reason I wrote the observable[1] and foxtails[2]
libraries. Here's a modification of your code that updates about 10
times per second. I had to use a text field in this example instead of a
label because I had never thought of making label text connect to a
variable, but it would not be hard to do. It still runs with <1% cpu,
though probably a bit more than using SEL_UPDATE. FoxTails won't scale
up to huge numbers of widgets as well as pure fox, of course, because
(a) it has an extra layer of ruby code on top of fxruby and (b) is it
eager rather than lazy about updates. (I feel that the laziness of
updates in fxruby, especially menu items, is a serious problem.)
require 'foxtails'
include Fox
include FoxTails
class Main
extend Observable
observable :i
def initialize
self.i = 0
end
def run
@app = FXApp.new
main = FXMainWindow.new(@app, File.basename(__FILE__))
FXButton.new(main, "&Quit") do |button|
button.layoutHints = LAYOUT_CENTER_X
button.connect(SEL_COMMAND) do
exit
end
end
20.times do
FTTextField.new(main, 10, self, :i)
end
main.show(PLACEMENT_SCREEN)
start_timer
@app.create
@app.run
end
private
def start_timer
@app.addTimeout(100, method(:timer))
end
def timer(sender, sel, data)
self.i += 1
start_timer
end
end
Main.new.run if $0 == __FILE__
That example didn't do any formatting, but there is a #field method that
lets you use various %-escapes to do formatting and also to line things
up using a FXMartix, perform validation, group radio buttons, add check
buttons, and so on. These are all connected (in both directions) to ruby
attrs using the observable mechanism.
In this case, just add your fields using the following code instead of
the above:
main.extend FTField
# normally, you define a window class and include FTField
20.times do
main.field "current value is %04d", [self, :i]
end
The static text "current value os" is displayed as a label, and the
dynamic text is displayed in a text field (but it could be a label with
a little work).
Check out foxtails/examples/fields.rb for more.
[1] http://raa.ruby-lang.org/project/observable/
[2] http://raa.ruby-lang.org/project/foxtails/
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
More information about the fxruby-users
mailing list