Gtk::ProgressBar set_fraction doesn't work

Hello,

i have some problems with the Gtk::ProgressBar. I download a file and i want to show a progressbar. The method below creates a new dialog with a bar and starts the download for each file. The puts-line work very well and i can see a dialog, there is no update. Does anybody know whats going wrong?

Thanks to all the people in this great community,
  Patrick

def download_podcasts(liststore_podcasts)
         dialog = Gtk::Dialog.new("Download",
                                  $main_application_window,
                                  Gtk::Dialog::DESTROY_WITH_PARENT)

         bar = Gtk::ProgressBar.new
         bar.fraction = 0.0

         dialog.vbox.add(bar)
         dialog.show_all

         liststore_podcasts.each do |model,path,row|
                 row[3].download do |received, total|
                         bar.fraction = received.to_f / total.to_f
                         bar.text = (bar.fraction * 100).to_s + "%"
                         puts received.to_s + " / " + total.to_s + " = " + bar.fraction.to_s
                 end
         end

         dialog.destroy
end

Patrick Plattes wrote:

Hello,

i have some problems with the Gtk::ProgressBar. I download a file and i
want to show a progressbar. The method below creates a new dialog with a
bar and starts the download for each file. The puts-line work very well
and i can see a dialog, there is no update. Does anybody know whats
going wrong?

The thread in which your process is running, that would update the progress
bar, is busy downloading your file, so it cannot update the progressbar
dislay. This is a very common problem, normally solved by creating a
separate thread to perform the download, thus freeing the display thread to
perform updates. Unfortunately, because of how threads are implemented in
Ruby, this approach often doesn't work.

I have not had any success updating progress bars using worker threads and
the Qt GUI library, you may have a different experience with
GTk:ProgressBar.

···

--
Paul Lutus
http://www.arachnoid.com

Hi,

In <12n5dc9ofnuge4@corp.supernews.com>
  "Re: Gtk::ProgressBar set_fraction doesn't work" on Sun, 3 Dec 2006 20:35:11 +0900,

···

Paul Lutus <nospam@nosite.zzz> wrote:

> i have some problems with the Gtk::ProgressBar. I download a file and i
> want to show a progressbar. The method below creates a new dialog with a
> bar and starts the download for each file. The puts-line work very well
> and i can see a dialog, there is no update. Does anybody know whats
> going wrong?

The thread in which your process is running, that would update the progress
bar, is busy downloading your file, so it cannot update the progressbar
dislay. This is a very common problem, normally solved by creating a
separate thread to perform the download, thus freeing the display thread to
perform updates. Unfortunately, because of how threads are implemented in
Ruby, this approach often doesn't work.

I have not had any success updating progress bars using worker threads and
the Qt GUI library, you may have a different experience with
GTk:ProgressBar.

Gtk.idle_add may help you.

Thanks,
--
kou

Paul Lutus schrieb:

I have not had any success updating progress bars using worker threads and
the Qt GUI library, you may have a different experience with
GTk:ProgressBar.

I found an interesting link:

"You are probably doing all the changes within a function without returning control to gtk_main(). This may be the case if you do some lengthy calculation in your code. Most drawing updates are only placed on a queue, which is processed within gtk_main(). You can force the drawing queue to be processed using something like:

while (g_main_context_iteration(NULL, FALSE));

inside you're function that changes the widget.

What the above snippet does is run all pending events and high priority idle functions, then return immediately (the drawing is done in a high priority idle function)." [http://www.gtk.org/faq/#AEN602\]

I don't see how i can call g_main_context_iteration in ruby. Any idea?

Thanks,
  Patrick

Paul Lutus wrote:

I have not had any success updating progress bars using worker threads and
the Qt GUI library, you may have a different experience with
GTk:ProgressBar.

I can't help with the original GTK question. But in QtRuby you would
use a Qt::Timer that allows you to specify a ruby method as a 'slot' to
be called periodically. In the slot called by Qt::Timer, download a
single file, update the progress bar and return. That way control can
return to Qt's main loop, and events can be handled - otherwise the GUI
will just freeze while you do what might be a lengthy download of lots
of podcasts.

-- Richard

Hi,

···

2006/12/4, Patrick Plattes <patrick@erdbeere.net>:

Paul Lutus schrieb:
> I have not had any success updating progress bars using worker threads and
> the Qt GUI library, you may have a different experience with
> GTk:ProgressBar.
>

"You are probably doing all the changes within a function without
returning control to gtk_main(). This may be the case if you do some
lengthy calculation in your code. Most drawing updates are only placed
on a queue, which is processed within gtk_main(). You can force the
drawing queue to be processed using something like:

while (g_main_context_iteration(NULL, FALSE));

inside you're function that changes the widget.

I don't see how i can call g_main_context_iteration in ruby. Any idea?

  while Gtk.events_pending?
    Gtk.main_iteration
  end

Thanks,
--
kou

Yes, tried that method. Doesn't work for a single file, the original
objective. The reason AFAICS is the timer can't easily preempt the file
download while it is under way, and when it can, it produces now
information that the display routines will use to update the display, but
only after the file download is finished.

Your suggestion works for a task consisting of a series of file downloads,
and a progress bar that indicates the total progress for all the files, and
a timer that initiates each new file download at intervals. Yes, that
works.

···

richard.j.dale@gmail.com wrote:

Paul Lutus wrote:

I have not had any success updating progress bars using worker threads
and the Qt GUI library, you may have a different experience with
GTk:ProgressBar.

I can't help with the original GTK question. But in QtRuby you would
use a Qt::Timer that allows you to specify a ruby method as a 'slot' to
be called periodically. In the slot called by Qt::Timer, download a
single file, update the progress bar and return. That way control can
return to Qt's main loop, and events can be handled - otherwise the GUI
will just freeze while you do what might be a lengthy download of lots
of podcasts.

--
Paul Lutus
http://www.arachnoid.com

Kouhei Sutou schrieb:

while Gtk.events_pending?
   Gtk.main_iteration
end

It works very well, thanks!

Patrick

Paul Lutus wrote:

>
> Paul Lutus wrote:
>
>> I have not had any success updating progress bars using worker threads
>> and the Qt GUI library, you may have a different experience with
>> GTk:ProgressBar.
> I can't help with the original GTK question. But in QtRuby you would
> use a Qt::Timer that allows you to specify a ruby method as a 'slot' to
> be called periodically. In the slot called by Qt::Timer, download a
> single file, update the progress bar and return. That way control can
> return to Qt's main loop, and events can be handled - otherwise the GUI
> will just freeze while you do what might be a lengthy download of lots
> of podcasts.

Yes, tried that method. Doesn't work for a single file, the original
objective. The reason AFAICS is the timer can't easily preempt the file
download while it is under way, and when it can, it produces now
information that the display routines will use to update the display, but
only after the file download is finished.

Your suggestion works for a task consisting of a series of file downloads,
and a progress bar that indicates the total progress for all the files, and
a timer that initiates each new file download at intervals. Yes, that
works.

To do that you would need to create a socket, and then use a
Qt::SocketNotifier of Type Read to monitor it. The SocketNotifier emits
a signal 'activated(int)' when there is something to read on the
socket. So in the slot connected to the activated signal, you would
read from the socket, update the progress bar according to the bytes
read and return.

-- Richard

···

richard.j.dale@gmail.com wrote: