Forum: Ruby-Gnome 2 Can't force any Gtk objects to redraw

Posted by Eric C. (eric_c)
on 2012-03-10 07:26
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
Posted by Ian McIntosh (Guest)
on 2012-03-10 08:30
(Received via mailing list)
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. <ruby-forum-incoming@andreas-s.net>:
Posted by Andrea Dallera (edwin_bolthar)
on 2012-03-10 09:26
(Received via mailing list)
 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
 
--
 
http://usingimho.wordpress.com
http://github.com/bolthar
From: "Ian McIntosh" ian@openanswers.org
To: ruby-gnome2-devel-en@lists.sourceforge.net
Cc:
Date: Fri, 9 Mar 2012 23:29:23 -0800
Subject: Re: [ruby-gnome2-devel-en] Can't force any Gtk objects to 
redraw
Posted by Eric C. (eric_c)
on 2012-03-10 23:49
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.  :) 
HaHaHa

Yours,
Eric
Posted by Vincent Carmona (vinc-mai)
on 2012-03-13 19:05
(Received via mailing list)
Le 10 mars 2012 23:49, Eric C. <ruby-forum-incoming@andreas-s.net> 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/.
> https://lists.sourceforge.net/lists/listinfo/ruby-...
>



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.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.