Wayne Conrad
2006-Nov-05 17:27 UTC
[fxruby-users] Getting fewer paints per second than I expected
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? Fox 1.4.34, FXRuby 1.4.7, Debian testing. Program follows. #!/usr/bin/ruby1.8 require ''fox14'' include Fox class Main def initialize @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 FXLabel.new(main, format_count) do |label| label.connect(SEL_UPDATE) do label.text = format_count end end end main.show(PLACEMENT_SCREEN) start_timer @app.create @app.run end private def format_count "%04d" % @i end def start_timer @app.addTimeout(100, method(:timer)) end def timer(sender, sel, data) @i += 1 start_timer end end Main.new.run if $0 == __FILE__
Joel VanderWerf
2006-Nov-05 23:22 UTC
[fxruby-users] Getting fewer paints per second than I expected
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
Joel VanderWerf
2006-Nov-06 00:32 UTC
[fxruby-users] Getting fewer paints per second than I expected
Joel VanderWerf wrote: ...> 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....> [1] http://raa.ruby-lang.org/project/observable/ > [2] http://raa.ruby-lang.org/project/foxtails/Sourceforge seems to be down so just for the heck of it here is another example (going a bit OT) of fields with the matrix, validation, radio/check, and observable features. The output of the program, after entering data as shown in the attached PNG, is as follows: $ ruby ship-fields.rb [#<Ship foo, sailboat, (1.0,2.0), enabled=false>, #<Ship bar, speedboat, (3.0,4.0), enabled=true>] The full program is attached, but this is the heart of it: matrix = FXMatrix.new(self, 8, MATRIX_BY_COLUMNS|FRAME_THICK|LAYOUT_FILL_X) # The %| character separates fields into different cells of the matrix. field(matrix, " %| name %| x %| y %| speedboat %| sailboat %| steamer %| enabled") # this just adds some header labels ships = [Ship.new, Ship.new] ships.each_with_index do |ship, i| f = field(matrix, "#{i} %| %s %| %6.2f %| %6.2f %| %r %| %r %| %r %| %v", # %r is radio, %v is check [ship, :name], [ship, :x], [ship, :y], [[ship, :kind], "speedboat"], [[ship, :kind], "sailboat"], [[ship, :kind], "steamer"], [ship, :enabled] ) f.valid([ship, :x]) {|x| x >= 0 and x < 100} f.valid([ship, :y]) {|y| y >= 0 and y < 100} -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407 -------------- next part -------------- A non-text attachment was scrubbed... Name: ship-fields.png Type: image/png Size: 5529 bytes Desc: not available Url : http://rubyforge.org/pipermail/fxruby-users/attachments/20061105/075759e4/attachment.png -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: ship-fields.rb Url: http://rubyforge.org/pipermail/fxruby-users/attachments/20061105/075759e4/attachment.pl