[fxruby-users] FXDataTarget & widget value update delay

Philippe Lang philippe.lang at attiksystem.ch
Tue Oct 3 17:51:35 EDT 2006


Jeroen van der Zijp wrote:

> On Tuesday 03 October 2006 10:34, Philippe Lang wrote:
>> Hi,
>> 
>> When assigning a new value to an FXDataTarget
> programmatically, it takes a certain time for the widget
> linked to this FXDataTarget to be updated, just as if there
> was some sort of "polling" inside the framework. Delay can be
> as long as 1 second sometimes. Why aren't the widgets updated
> straight away? 
> 
> The GUI gets updated when the event loop is about to block
> for events; as long as there are events [keyboard, mouse,
> repaints, etc], the event loop processes those with priority.
> 
> When all queued-up events have been processed, one would
> normally go to a blocking state [i.e. yield the CPU in some
> system call waiting on the event queue].  In FOX we don't
> yield YET; we instead iterate over the widget tree, and send
> a SEL_UPDATE to the target of each widget.
> 
> Once we've gone through the entire widget tree, THEN we block
> and yield the CPU.  Of course, each time we update one
> widget, we check for events again, to ensure that the
> application reacts instantly when something happens.
> 
> The updating process is therefore mostly invisible in the
> sense that interactive performance is not affected by it:-
> the only time we do updates is when there's nothing else we would be
> doing anyway. 
> 
> However, this does have a few repercussions on the frequency
> of updates; in a very busy system with a large number of
> widgets it may take some time before an entire cycle through the
> widget tree is completed. 
> 
> For this reason, its important to keep the update-handlers
> small and to avoid unnecessary work in then whenever possible.
> 
> The code in getNextEvent() is finely tuned to get great
> performance, but of course I'm not the one writing the update
> handlers!  That is up to the software developer himself;  it
> helps to know what to do and what to avoid.  Hence this mail.

Hi again,

I wrote a test application that updates the widget tree with:

    def update(window)
        window.handle(self, FXSEL(SEL_UPDATE, 0), nil)
        window.children().each { |child|
            update(child)
        }
    end

This is much faster than waiting for the framework to issue a SEL_UPDATE to the widgets of the window. You can see the difference visually.

I'm not sure if this kind of code can be included in FXRuby directly?

Cheers,

Philippe

-----------------------------------------------

#!/usr/bin/ruby

require 'fox16'

include Fox

class MyWindow < FXMainWindow
    
  def initialize(app)

    super(app, "Window", nil, nil, DECOR_ALL, 0, 0, 500, 500)

    # Menu bar stretched along the top of the main window
    menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
  
    # File menu
    filemenu = FXMenuPane.new(self)
    FXMenuTitle.new(menubar, "&File", nil, filemenu)
    FXMenuCommand.new(filemenu, "&Quit\tCtl-Q\tQuit the application",
        nil, app, FXApp::ID_QUIT)

    # Frames
    frame1 = FXMatrix.new(self, 4,
        LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
    
    frame2 = FXMatrix.new(frame1, 4,
        LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
    
    frame3 = FXMatrix.new(frame2, 4,
        LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
    
    frame4 = FXMatrix.new(frame3, 4,
        LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
    
    frame5 = FXMatrix.new(frame4, 4,
        LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED)
    
    @w1 = FXTextField.new(frame1, 5)
    FXTextField.new(frame1, 5)
    FXTextField.new(frame1, 5)
    FXTextField.new(frame1, 5)
    FXTextField.new(frame1, 5)
    FXTextField.new(frame1, 5)
    FXTextField.new(frame1, 5)
    
    @w2 = FXTextField.new(frame2, 5)
    FXTextField.new(frame2, 5)
    FXTextField.new(frame2, 5)
    FXTextField.new(frame2, 5)
    FXTextField.new(frame2, 5)
    FXTextField.new(frame2, 5)
    FXTextField.new(frame2, 5)
    
    @w3 = FXTextField.new(frame3, 5)
    FXTextField.new(frame3, 5)
    FXTextField.new(frame3, 5)
    FXTextField.new(frame3, 5)
    FXTextField.new(frame3, 5)
    FXTextField.new(frame3, 5)
    FXTextField.new(frame3, 5)
    
    @w4 = FXTextField.new(frame4, 5)
    FXTextField.new(frame4, 5)
    FXTextField.new(frame4, 5)
    FXTextField.new(frame4, 5)
    FXTextField.new(frame4, 5)
    FXTextField.new(frame4, 5)
    FXTextField.new(frame4, 5)
    
    @w5 = FXTextField.new(frame5, 5)
    FXTextField.new(frame5, 5)
    FXTextField.new(frame5, 5)
    FXTextField.new(frame5, 5)
    FXTextField.new(frame5, 5)

    @dt1 = FXDataTarget.new("1")
    @dt2 = FXDataTarget.new("1")
    @dt3 = FXDataTarget.new("1")
    @dt4 = FXDataTarget.new("1")
    @dt5 = FXDataTarget.new("1")
    
    @w1.target = @dt1
    @w1.selector = FXDataTarget::ID_VALUE
    
    @w2.target = @dt2
    @w2.selector = FXDataTarget::ID_VALUE
    
    @w3.target = @dt3
    @w3.selector = FXDataTarget::ID_VALUE
    
    @w4.target = @dt4
    @w4.selector = FXDataTarget::ID_VALUE
    
    @w5.target = @dt5
    @w5.selector = FXDataTarget::ID_VALUE

    add_button = FXButton.new(frame5, "Add 1 with individual SEL_UPDATE")
    
    add_button.connect(SEL_COMMAND) do |sender, selector, data|
        @dt1.value = @dt1.value.to_i + 1
        @dt2.value = @dt2.value.to_i + 1
        @dt3.value = @dt3.value.to_i + 1
        @dt4.value = @dt4.value.to_i + 1
        @dt5.value = @dt5.value.to_i + 1
        
        @w1.handle(self, FXSEL(SEL_UPDATE, 0), nil)
        @w2.handle(self, FXSEL(SEL_UPDATE, 0), nil)
        @w3.handle(self, FXSEL(SEL_UPDATE, 0), nil)
        @w4.handle(self, FXSEL(SEL_UPDATE, 0), nil)
        @w5.handle(self, FXSEL(SEL_UPDATE, 0), nil)
    end
    
    add_button2 = FXButton.new(frame5, "Add 1 with recursive SEL_UPDATE")
    
    add_button2.connect(SEL_COMMAND) do |sender, selector, data|
        @dt1.value = @dt1.value.to_i + 1
        @dt2.value = @dt2.value.to_i + 1
        @dt3.value = @dt3.value.to_i + 1
        @dt4.value = @dt4.value.to_i + 1
        @dt5.value = @dt5.value.to_i + 1
        update(self)
    end
    
    def update(window)
        window.handle(self, FXSEL(SEL_UPDATE, 0), nil)
        window.children().each { |child|
            update(child)
        }
    end
    
    add_button3 = FXButton.new(frame5, "Add 1 without SEL_UPDATE")
    
    add_button3.connect(SEL_COMMAND) do |sender, selector, data|
        @dt1.value = @dt1.value.to_i + 1
        @dt2.value = @dt2.value.to_i + 1
        @dt3.value = @dt3.value.to_i + 1
        @dt4.value = @dt4.value.to_i + 1
        @dt5.value = @dt5.value.to_i + 1
    end
    
  end

  def create
    super
    show(PLACEMENT_SCREEN)
  end

end

if __FILE__ == $0
  application = FXApp.new("Attik System", "FXRuby Test")
  MyWindow.new(application)
  application.create
  application.run
end

---------------
Philippe Lang
Attik System

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3125 bytes
Desc: not available
Url : http://rubyforge.org/pipermail/fxruby-users/attachments/20061003/2a18338a/attachment.bin 


More information about the fxruby-users mailing list