Can't force any Gtk objects to redraw

Hi y’all:

I’m having a problem with getting anything to paint on the screen
IMMEDIATELY. Here’s what I’m trying to do:

I’m downloading the names of all my rubygems and version numbers using
their API. So, its making about 20 http requests in a row. When the
user clicks the button to list his/her rubygems, the program seems to
hang while these names/versions are being downloaded. I need to have
the program oputput something during this time, so I tried updating a
Gtk::TextView:

def refresh()
return unless @gems = @api.get_obj_url("/api/v1/gems.yaml")
@gems.each do |gem|
gem_info = @api.get_obj_url("/api/v1/versions/#{gem[‘name’]}.yaml")
@main.shell.buffer.text += "loading gem: " + gem[‘name’] + “\n”
end
end

I tried for hours to get the text to update on the screen while each gem
is being downloaded. I tried:

@main.shell.queue_draw
@main.builder[“scrollShell”].queue_draw
@main.builder[“window1”].hide
@main.builder[“window1”].show_all
@main.shell.show

But nothing has any effect. It always updates the textbox AFTER all the
gems are downloaded.

So I tried making a popup window with a progress bar on it. But I had
the same problem. I can’t disply the window until AFTER the loop
completes.

What am I missing?

Thanks,
Eric

Call this after telling a widget to do something:

module Gtk
def self.clear_queue
while events_pending? do main_iteration_do(blocking = false) end
end
end

2012/3/9 Eric C. [email protected]:

Hi Eric,

it seems that the requests you're doing are synchronous. Most likely 

what Ian has suggested works but still, if you have some downloading to
do you better put it on another thread.

in refresh, try to do something like this instead of what you’ve
wrote:gem_infos = []def refresh
return unless @gems = @api.get_obj_url(“/api/v1/gems.yaml”)
@gems.each do |gem| @main.shell.buffer.text += “loading gem: " +
gem[‘name’] + “\n” Thread.new do gem_infos <<
@api.get_obj_url(”/api/v1/versions/#{gem[‘name’]}.yaml") end end
end

This is not a “polite” thing to do with threads but it should give you
an idea on how to approach a problem like this (if you have a heavy task
you should put it on a different thread anyway, no matter if you need to
do that for interface reasons)Andrea

From: “Ian McIntosh” [email protected]
To: [email protected]
Cc:
Date: Fri, 9 Mar 2012 23:29:23 -0800
Subject: Re: [ruby-gnome2-devel-en] Can’t force any Gtk objects to
redraw

Excellent! Thanks.

Ian,

I tried a similar solution earlier, but it only showed the window
without anything in it. Also, I read that using that method may make MS
Windows crash (big suprise!).
But using a thread worked perfectly. In
fact, when I put the downloading code in its own thread, I didn’t even
need to output text to show the progress because my listview that shows
all the gems was being updated in REAL TIME!!! Awesome.

This was absolutely the best result possible because now when someone
clicks the tab to see remote gems, the listview comes alive and gems
start
popping-up. Its perfect.

Here’s the version that works:

def refresh()
return if @t
@t = Thread.new do |t|
@main.shell.buffer.text += “\nContacting rubygems.org…”
self.model.clear
return unless @gems = get_obj_url(“/api/v1/gems.yaml”)
@gems.each do |gem|
gem_info = get_obj_url(“/api/v1/versions/#{gem[‘name’]}.yaml”)
gem_info.each do |info|
self.add_row(RUBY_ICON, “#{gem[‘name’]} (#{info[‘number’]})”)
end
end
t.join
end
@t = false
end

I only have a few more things to do now, and I’ll be finished. :slight_smile:
HaHaHa

Yours,
Eric

Le 10 mars 2012 23:49, Eric C. [email protected] a
crit :

all the gems was being updated in REAL TIME!!! Awesome.
@t = Thread.new do |t|
end
Posted via http://www.ruby-forum.com/.
ruby-gnome2-devel-en List Signup and Options

Hi.

I always thought that calling Gtk methods in a thread was a bad idea…
IS it not the case anymore ?

When I need to do work in a thread and update a gtk widget I use the
Queue
class.
The working thread push “event” in the queue whereas in gtk main loop
GLib::Timeout
pops events from the queue.