FXRuby problem

I’m trying to write a small FXRuby program that will
capture 6 pictures from a web source and place them as
buttons on my window. After that I want to have the
buttons to update with a new picture once every second
or so.
This is the work in progress I have a small
explanation below
=========== BEGIN CODE ==============

#!/usr/bin/env ruby

require "fox"
require "cam.rb"
include Fox
include Cam

class TestWindow < FXMainWindow
def initialize(app)
@app = app
# Invoke the base class initialize first
super(@app, “Test”, nil, nil, DECOR_ALL, 0,
0,640,480)
@picture_matrix = FXMatrix.new(self, 2,
LAYOUT_TOP|LAYOUT_FILL_ROW)

@photo_array = []
(1..6).each do |j|
  @photo_array[j] = FXButton.new(@picture_matrix,

“photo #{j}”, create_photo_icon(j), app,
FXApp::ID_QUIT, ICON_UNDER_TEXT|JUSTIFY_BOTTOM)

  #@photo_array[j] = FXImage.new

end

end

def create
super
show(PLACEMENT_SCREEN)

@photo1Thread = Thread.new(@photo_array[1]) do

photo1|
while true

    photo1=FXButton.new(@picture_matrix, "photo

1", create_photo_icon(1), @app, FXApp::ID_QUIT,
ICON_UNDER_TEXT|JUSTIFY_BOTTOM)
sleep(1)
end
end

end

def create_photo_icon(i)
getImageData(i) #This saves a picture capture as
"photo#{i}.jpg" (it’s in the cam module)
p i

icon=FXJPGIcon.new(@app,File.open(“photo#{i}.jpg”,“rb”).read)
icon.scale(120,150)
return icon
end
end

def run
application = FXApp.new(“DirList”, “FoxTest”)
application.init(ARGV)
TestWindow.new(application)
application.create
application.run
end

run

======END CODE==========

in the create method is a thred that is supped to be
updating button 1 every second, (It will hopefully be
expanded to all 6 buttons an a round-robin fasion)
But the picture on the button is not updating and I
can’t figure out why. I’ve tried everything like
repaints and refreses and it simply ignores the new
button information. Why? Can anyone help?

-Thanks
Joshua

···

Do you Yahoo!?
New DSL Internet Access from SBC & Yahoo!
http://sbc.yahoo.com

enforcer technolgy wrote:

I’m trying to write a small FXRuby program that will
capture 6 pictures from a web source and place them as
buttons on my window. After that I want to have the
buttons to update with a new picture once every second
or so.

<… snip …>

in the create method is a thread that is supposed to be
updating button 1 every second, (It will hopefully be
expanded to all 6 buttons an a round-robin fasion)
But the picture on the button is not updating and I
can’t figure out why. I’ve tried everything like
repaints and refreses and it simply ignores the new
button information. Why? Can anyone help?

Let’s focus on the thread that you set up in the TestWindow#create
method since that’s where the problem lies. Your version of the thread
procedure looks like this:

 @photo1Thread = Thread.new(@photo_array[1]) do |photo1|
   while true
     photo1 = FXButton.new(@picture_matrix,
       "photo 1", create_photo_icon(1),
       @app, FXApp::ID_QUIT,
       ICON_UNDER_TEXT|JUSTIFY_BOTTOM)
     sleep(1)
   end
 end

The first problem is that you’re constructing a new FXButton instance
every time the “while” loop runs, when all you really want to do is
replace the old icon with a new one. So the first change is to modify
the button (photo1) directly:

 @photo1Thread = Thread.new(@photo_array[1]) do |photo1|
   while true
     photo1.icon = create_photo_icon(1)
     sleep(1)
   end
 end

The next change has to do with FOX’s two-step construction and creation
process (see http://www.fox-toolkit.org/faq.html#ILLEGALICON). Since
your TestWindow#create_photo_icon constructs the icon but doesn’t call
create() on it, we need to be sure to do that:

 @photo1Thread = Thread.new(@photo_array[1]) do |photo1|
   while true
     new_icon = create_photo_icon(1)
     new_icon.create
     photo1.icon = new_icon
     sleep(1)
   end
 end

Finally, one more possible change related to memory use. When you
replace the icon previously stored on the button with the new_icon, the
old one is no longer needed and so at some point it will be
garbage-collected. However, if your images are large and you want to
keep the memory use low as much as possible, you can force the GC to run
as soon as you switch icons by adding a call to GC.start:

 @photo1Thread = Thread.new(@photo_array[1]) do |photo1|
   while true
     new_icon = create_photo_icon(1)
     new_icon.create
     photo1.icon = new_icon
     GC.start
     sleep(1)
   end
 end

A side note, unrelated to this question, is that you don’t have to save
a reference to the application in an instance variable (@app). It is
always available via the getApp() instance method, e.g.

 def create_photo_icon(i)
   getImageData(i)
   icon = FXJPGIcon.new(getApp(),
     File.open("photo#{i}.jpg", "rb").read)
   icon.scale(120, 150)
   icon
 end

Hope this helps,

Lyle