Forum: Ruby-Gnome 2 visualruby: combobox example

15451874210a5b7a7ae12ce9d9cf4ae4?d=identicon&s=25 Patrik K. (patrik_k)
on 2012-09-30 20:34
Hi

I'm on my first steps with visualruby, in glade gui editor I created a
combobox1.

Can someone help me to predefine the values by using combArray =
["plane", "ship", "car"]

and how to read out the selected value from within the calling class?

BR
Pat
46a8ebdfabc2485407f89a2db5bdafb7?d=identicon&s=25 Igor Pirnovar (rooby)
on 2012-10-03 21:49
#!/usr/bin/env ruby
require 'gtk2'

combArray = ["plane", "ship", "car"]
store = Gtk::ListStore.new(String)
combArray.each_with_index do |e|
  iter = store.append
  iter[0]   = e
end

cb = Gtk::ComboBox.new(true)
cb.model = store

window = Gtk::Window.new("Load Array Into ComboBox")
window.resizable = true
window.border_width = 10
window.signal_connect('destroy') { Gtk.main_quit }
window.set_size_request(300, -1)
window.add(cb)
window.show_all
Gtk.main
46a8ebdfabc2485407f89a2db5bdafb7?d=identicon&s=25 Igor Pirnovar (rooby)
on 2012-10-03 21:53
Of course you will have to do something like:

combArray = ["plane", "ship", "car"]
store = Gtk::ListStore.new(String)
combArray.each do |e|
  iter = store.append
  iter[0]   = e
end

cb = # Gget combo box from visual ruby
cb.model = store
15451874210a5b7a7ae12ce9d9cf4ae4?d=identicon&s=25 Patrik K. (patrik_k)
on 2012-10-03 23:26
Igor Pirnovar wrote in post #1078548:
> #!/usr/bin/env ruby
> require 'gtk2'

yes thats working, but its not visualruby!
15451874210a5b7a7ae12ce9d9cf4ae4?d=identicon&s=25 Patrik K. (patrik_k)
on 2012-10-03 23:31
Igor Pirnovar wrote in post #1078549:
> cb = # Get combo box from visual ruby
> cb.model = store


The real trick is to get the combo box, but how?

So I found this one:
http://stackoverflow.com/questions/1194659/how-to-...
combo = VR::SimpleComboBoxEntry("Selected", "Option1", "option2",
"Option3")
@builder["combobox1"].add(combo)

looks very simple but fails with:
undefined method SimpleComboBoxEntry for VR module

(http://ruby-doc.org/gems/docs/v/vrlib-0.0.32/VR/Si...)
46a8ebdfabc2485407f89a2db5bdafb7?d=identicon&s=25 Igor Pirnovar (rooby)
on 2012-10-04 19:58
If VisualRuby was working as expected, you should be able to initialiye
your 'MyClass' with the following code:

def initialize
  combArray = ["plane", "ship", "car"]
  store = Gtk::ListStore.new(String)
  combArray.each do |e|
    iter = store.append
    iter[0]   = e
  end
  cb = @builder["combobox1"]
  cb.model = store
end

However, there seems to be a problem in VR, namely, it '@builder'
variable contains nil! Because of this the initialization of 'MyClass'
fails.
46a8ebdfabc2485407f89a2db5bdafb7?d=identicon&s=25 Igor Pirnovar (rooby)
on 2012-10-04 21:05
Sorry, I missed one thing before {{ load_glade(__FILE__) }}.

def initialize
  load_glade(__FILE__)
  combArray = ["plane", "ship", "car"]
  store = Gtk::ListStore.new(String)
  combArray.each do |e|
    iter = store.append
    iter[0]   = e
  end
  cb = @builder["combobox1"]
  cb.model = store
end

This now works. However, it does not load the model. You may also have
to define the model in Glade?!

I do not know enough about VB, but you should do something along the
following:

   combobox1 -> General tab -> ComboBox model -> \
      [...] (click the ellipsis) -> New -> liststore1

But I still think, that you should be able to write your own code in
ruby (as we did in the initialize method above for 'MyClass'), rather
than messing up with Glade.
46a8ebdfabc2485407f89a2db5bdafb7?d=identicon&s=25 Igor Pirnovar (rooby)
on 2012-10-05 20:38
Hi,

VR doesn't initialize the Gtk::ComboBox correctly. It looks as if VR's
combobox constructor is always called with the argument false. Anyhow,
it seems not only is the run-time assignment of different data model to
a VR combo-box not working, initialization of VR's combo-box too, looks
like a generic VR/Glade problem!?

Both, GTK+ and Ruby-GTK allow to dynamically change the models for any
combo-box.

I have tested Gtk::ComboBox in VR with both, (1) the model created in
Glade, (2) and the one generated manually in initialize method. It
turned out that VR's ComboBox object is aware of both and can even
combine them, i.e. you can append programmatically items to the Glade
generated model, if you so desire. However, VR fails to display either
of them regardless of how you set up the respective model values (rows).

You can tinker with the following code in VR's "MyClass", and see for
yourself that all items are available to 'cb' (combobox) object in VR:

----------------------------------------------------------------------
class MyClass #(change name)

  include GladeGUI

  def initialize
    load_glade(__FILE__)
    combArray = ["plane", "ship", "car"]
    store = Gtk::ListStore.new(String)
#   store = @builder["liststore1"]
    combArray.each do |e|
      iter = store.append
      iter[0]   = e
    end
    puts "DEBUG: @builder.class=#{@builder.class} " +
         "store.class=#{store.class}"

    cb = @builder["combobox1"]
    cb.set_model(store)
    cb.active = 3
    puts "DEBUG: active_text=#{cb.active_text}"
  end

  def show()
    load_glade(__FILE__)  #loads glade/MyClass.glade into @builder
    @label1 = "Hello World"
    set_glade_all() #populates glade controls with instance variables
    show_window()
  end
end
----------------------------------------------------------------------

If you correctly initialize the 'liststore1' in Glade, and also set a
few columns, say ("horse", "bicycle", "rollers"), values in it, you can
combine the model rows ("plane", "ship", "car") defined programmatically
in MyClass's 'initialize' with the model rows ("horse", "bicycle",
"rollers") defined in Glade into a single VR's "cb" list ("horse",
"bicycle", "rollers", "plane", "ship", "car"), by uncommenting // store
= @builder["liststore1"] // line in the above listing. To confirm that
VR's combobox contains both lists you can first set //cb.active = 0//,
and in the next test run to '4' (//cb.active = 4//). The two VR test
runs will in //puts "DEBUG: active_text=#{cb.active_text}"// correctly
print 'horse' and 'ship' respectively.

For this test to work for both programmatically set model and the one
set in Glade, you have to assign 'liststore1' 'to tour combobox1' in
Glade. Also in Glade under "Add and remove columns" you have to set up
liststore1's "Column type" to "gchararray" data type. And lastly, under
"Add and remove rows" add for example the rows as suggested above
("horse", "bicycle", "rollers") to the 'liststore1'.
15451874210a5b7a7ae12ce9d9cf4ae4?d=identicon&s=25 Patrik K. (patrik_k)
on 2012-10-09 00:05
Igor Pirnovar wrote in post #1078751:

> VR doesn't initialize the Gtk::ComboBox correctly.

Hi Ivan

I gave it a quick try today, but the box remained empty.
Yes, I set the fields in Glade. The ComboBox model I set to liststore1.
Columntype and Column name to gchararray. And added Data rows with
"horse", "bicycle", "rollers"

The debugger shows:
C:/Ruby193/lib/ruby/gems/1.9.1/gems/vrlib-0.0.32/lib/GladeGUI.rb: line
127
   GLib-GObject-CRITICAL **:g_value_unset: assertion `G_IS_VALUE
(value)' failed
DEBUG: @builder.class=Gtk::Builder store.class=Gtk::ListStore
DEBUG: active_text=

BR
Patrik
46a8ebdfabc2485407f89a2db5bdafb7?d=identicon&s=25 Igor Pirnovar (rooby)
on 2012-10-09 18:19
Patrick,

I can not reproduce your {{ GLib-GObject-CRITICAL **:g_value_unset }}
error. It looks that you are running Windows, I am on Linux. Perhaps the
two implementations differ, since the line 127 in GladeGUI.rb, on Linux
would not spit out your {{ GLib-GObject-CRITICAL **:g_value_unset }}
error. Nevertheless, your debug output line {{ DEBUG: active_text= }}
indicates that the two models did not merge. Try changing the {{
cb.active }} from 3 to 0, and comment out the line {{ store =
@builder["liststore1"] }} in your MyClass::initialize. And re-run this
test in VR. You should get {{ DEBUG: active_text=plane }}, providing
your {{ initialize }} method in MyClass looks like the following:

  def initialize
    load_glade(__FILE__)
    combArray = ["plane", "ship", "car"]
    store = Gtk::ListStore.new(String)
#   store = @builder["liststore1"]
    combArray.each do |e|
      iter = store.append
      iter[0]   = e
    end
    puts "DEBUG: @builder.class=#{@builder.class} " +
         "store.class=#{store.class}"

    cb = @builder["combobox1"]
    cb.set_model(store)
    cb.active = 0
    puts "DEBUG: active_text=#{cb.active_text}"
  end

I can show you the code that works in pure Ruby GTK, to prove that it is
possible to dynamically switch models for Gtk::ComboBox.

Regards, igor
0d130f179f85401f248e6ebc2ef8292f?d=identicon&s=25 Eric C. (eric_c)
on 2012-11-12 03:25
Sorry for the late response.

I would suggest that you never place a combobox in your glade form using
the glade software for 2 reasons:

1)  The glade program has a bug in it so you can't create a simple
combobox.  There are two types of comboboxes, and it always uses the
complicated type that requires a liststore object.  If you want a simple
combobox that has one column of choices, use the VR::SimpleComboBoxEntry
class.  (See below)

2)  I beleive it is a bad idea to try to populate your combobox using a
liststore object in glade because you'll always want to dynamically
populate the list at runtime using ruby code later anyway.  So, do all
work with the data in code.

This is how you use comboboxes in visualruby:

1)  In your glade form, place a vbox object where you want your combobox
to appear.  For this example, the name if the vBox will be "vbox1." (we
will insert a combobox inside it using code)

2)  In your show() method, create a VR::SimpleComboBoxEntry:

def show()
  load_glade(__FILE__)
  @cb = VR::SimpleComboBoxEntry.new("plane", "ship", "car")
  @builder["vbox1"].add(@cb)
  show_window()
end

3)  Later, you can retrieve the selected text like this:

  def buttonSave__clicked
    @var = @cb.active_text
    destroy_window()
  end

The reason I wrote a class to make a simple combobox is because its
impossible to create with glade alone.

Good luck,
Eric
15451874210a5b7a7ae12ce9d9cf4ae4?d=identicon&s=25 Patrik K. (patrik_k)
on 2012-11-18 20:35
Thanks a lot Eric

With this I think I now have what I need.
GUI's without comboboxes would be very boring.

Thanks
Pat
00c2ec5c197b2de8e55997e594ba4c0a?d=identicon&s=25 Klaus D. (kdiddy)
on 2012-11-28 22:20
Eric C. wrote in post #1084015:
>
> 2)  In your show() method, create a VR::SimpleComboBoxEntry:
>
> def show()
>   load_glade(__FILE__)
>   @cb = VR::SimpleComboBoxEntry.new("plane", "ship", "car")
>   @builder["vbox1"].add(@cb)
>   show_window()
> end
>

How could I then react on the change signal from this combobox ??

Greetings

Klaus
00c2ec5c197b2de8e55997e594ba4c0a?d=identicon&s=25 Klaus D. (kdiddy)
on 2012-11-29 00:15
Klaus D. wrote in post #1086961:
> Eric C. wrote in post #1084015:
>>
>> 2)  In your show() method, create a VR::SimpleComboBoxEntry:
>>
>> def show()
>>   load_glade(__FILE__)
>>   @cb = VR::SimpleComboBoxEntry.new("plane", "ship", "car")
>>   @builder["vbox1"].add(@cb)
>>   show_window()
>> end
>>
>
> How could I then react on the change signal from this combobox ??
>
> Greetings
>
> Klaus

Ok, I found it ;-)
I have to manually connect the signal:

  @cb.signal_connect "changed" do |w, e|
    cb__changed(w,e)
  end
0d130f179f85401f248e6ebc2ef8292f?d=identicon&s=25 Eric C. (eric_c)
on 2012-11-29 00:58
Hi Klaus:

Actually, one of the nice things about visualruby is that you don't need
to use the signal_connect method.  Instead, you just give your method a
name using the naming convention:  "widget__signal" or
"instancevariable__signal" or "self__signal" and vr will automatically
connect the signal for you:

def cb__changed(w,e)
  VR::msg("the combobox just changed!")
end

This method will execute when the widget in the @cb variable emits the
"changed" signal.

Good luck,
Eric
00c2ec5c197b2de8e55997e594ba4c0a?d=identicon&s=25 Klaus D. (kdiddy)
on 2012-11-29 22:26
Eric C. wrote in post #1086973:
> Hi Klaus:
>
> Actually, one of the nice things about visualruby is that you don't need
> to use the signal_connect method.  Instead, you just give your method a
> name using the naming convention:  "widget__signal" or
> "instancevariable__signal" or "self__signal" and vr will automatically
> connect the signal for you:
>
> def cb__changed(w,e)
>   VR::msg("the combobox just changed!")
> end
>
> This method will execute when the widget in the @cb variable emits the
> "changed" signal.
>
> Good luck,
> Eric

Hi Eric,

didn't know about the "instancevariable__signal" part ;-(
and learned that I have to declare the instancevariable before calling
load_glade ;-)

Klaus
E040c3341f4ccc3aa85ae171fec6e296?d=identicon&s=25 Kacper M. (kacper_m)
on 2013-05-26 16:47
Eric C. wrote in post #1084015:
> 3)  Later, you can retrieve the selected text like this:
>
>   def buttonSave__clicked
>     @var = @cb.active_text
>     destroy_window()
>   end

And how do I access a combobox value in a listview? I'm trying to check
value of another cell in a row in a validation block but fail to. It
seems that I can access only ComboCol and it doesn't have a
"active_text" method.
I'm lost. :)

Here's my code:

self.renderer(:get_formats).validate_block = Proc.new { | value, row |
  if row[:formats].active_text == ""
    @yt.get_formats(row)
    row[:formats] = VR::ComboCol.new("Choose",
*@yt.videos[row.to_s.to_i].formats)
  end
}

It returns with error:
undefined method `active_text' for #<VR::ComboCol:0x00000002eac7c8>

Cheers,
k
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.