Search code examples
rubyprogress-bargtk3

Use GTK3 progress bars in Ruby


This is my code:

require "gtk3"
builder_file = "#{File.expand_path(File.dirname(__FILE__))}/example.ui"
builder = Gtk::Builder.new(:file => builder_file)
window = builder.get_object("window")
window.signal_connect("destroy") { Gtk.main_quit }
progressbar=builder.get_object("progressbar1")
progressbar.set_fraction(0.5)
button = builder.get_object("button1")
button.signal_connect("clicked") {
  for i in(0..4)
    sleep(1)
    puts "query " + (i+1).to_s + " done"
    a=(i+1)/5.to_f
    puts a
    progressbar.set_fraction(a)
  end
  }
Gtk.main

sleep is just a placeholder for a web query that takes about 1 second. When I execute this code on my machine, the console output is fine, but the progress bar stays empty until it jumps to full after five seconds, which is not what I want. How can I make use of the progress bar?


Solution

  • The integration of the event loop of the GUI tool (Gtk, Tk, etc) and Ruby annoys beginners including me. I know two ways.

    1.add thread

    require 'gtk3'
    
    win = Gtk::Window.new('Sample')
    win.signal_connect('destroy') { Gtk.main_quit }
    
    box = Gtk::Box.new(:vertical)
    
    pb = Gtk::ProgressBar.new
    pb.set_fraction(0.5)
    
    b = Gtk::Button.new(label: 'Button')
    b.signal_connect('clicked') do
      Thread.new do
        5.times do |i|
          sleep 1
          pb.fraction = (i + 1) / 5.0
        end
      end
    end
    
    win.add box
    box.pack_start pb
    box.pack_start b
    
    win.show_all
    
    Gtk.main
    

    2.use GLib::Timeout

    b.signal_connect('clicked') do
        i = 0.0
        GLib::Timeout.add(1000) do |a|
               i += 0.2
               pb.fraction = i
               i < 1.0 # return false and stop when i >= 1.0
        end
    end