Visualruby: combobox example

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

#!/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

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

Igor P. wrote in post #1078548:

#!/usr/bin/env ruby
require ‘gtk2’

yes thats working, but its not visualruby!

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.

Igor P. 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:

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/SimpleComboBoxEntry.html)

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.

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’.

Igor P. 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

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

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

  1. 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

Eric C. wrote in post #1084015:

  1. 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

Thanks a lot Eric

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

Thanks
Pat

Klaus D. wrote in post #1086961:

Eric C. wrote in post #1084015:

  1. 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 :wink:
I have to manually connect the signal:

@cb.signal_connect “changed” do |w, e|
cb__changed(w,e)
end

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 :wink:

Klaus

Eric C. wrote in post #1084015:

  1. 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. :slight_smile:

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

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