Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better way to append child to a vbox #1180

Closed
arjunmenon opened this issue May 16, 2018 · 4 comments
Closed

Better way to append child to a vbox #1180

arjunmenon opened this issue May 16, 2018 · 4 comments

Comments

@arjunmenon
Copy link
Contributor

Hey

I am trying to append children to a vbox after it has been created. That vbox is actually a child of a scrolled_window.
Basically after a search box receives the enter key signal, I want to add the results to the scrolled_window.

The way I have done, It works but I wonder if there is a better way?

require 'gtk2'

# a dummy array of data we will search from
@t = [{"id"=>"819827", "city"=>"Razvilka", "countryCode"=>"RU"}, 
				{"id"=>"524901", "city"=>"Moscow", "countryCode"=>"RU"}, 
				{"id"=>"1271881", "city"=>"Firozpur Jhirka", "countryCode"=>"IN"}, 
				{"id"=>"1283240", "city"=>"Kathmandu", "countryCode"=>"NP"}]

# create a modal window
def button_clicked (parent)
        # this modal window as three tabs.
        # the first tab has a search box and a scrolled window to show the results
	dialog = Gtk::Dialog.new(
        "Configure",
        parent,
        Gtk::Dialog::MODAL,
        [ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK ]
  	)

  	nb = Gtk::Notebook.new
	label1 = Gtk::Label.new("  Location  ") # no easy way to define padding here, so we just add spaces
	label2 = Gtk::Label.new("  Preferences  ")
	label3 = Gtk::Label.new("  About  ")
	button = Gtk::Button.new("Gumbek")

	# we create a big vbox. Then add search bar and a scrolled window to display the results.

	location_box = Gtk::VBox.new(false,5)
	search = Gtk::Entry.new
	search.set_inner_border(Gtk::Border.new(10, 10, 10, 10))
	location_box.pack_start(search, false,false, 0)

	search.signal_connect("activate") do |widget, event|
		# we want to display radio boxes, but they require a group id to work proeprly, so we get the first element and set a instance variable, then we itierate through the rest and add the variable as the group

		if widget.text.length >= 3
			@result_box.each{|child| @result_box.remove child }
			@t.map.with_index do |name, index|
				if index == 0 # using index to define a radio group
					@radio1 = Gtk::RadioButton.new("#{name["city"]}, #{name["countryCode"]}")
					halign = Gtk::Alignment.new 0, 0, 0, 0 # left align everythin in result_box
					halign.add @radio1

                                        ####### 
                                        # IS THERE A BETTER WAY TO ADD RESULTS TO A VBOX
					@result_box.pack_start(halign, false,false, 0)
					@radio1.show
					halign.show
				else
					puts "#{name["city"]}, #{name["countryCode"]}"
					radio = Gtk::RadioButton.new(@radio1, "#{name["city"]}, #{name["countryCode"]}")
					halign = Gtk::Alignment.new 0, 0, 0, 0 # left align everythin in result_box
					halign.add radio

                                        # IS THERE A BETTER WAY TO ADD RESULTS TO A VBOX
					@result_box.pack_start(halign, false,false, 0)
					radio.show
					halign.show
				end
		    end									    
		end
	end

	@info_label = Gtk::Label.new("Type your city (atleast 3 letters) and press enter")
	location_box.pack_start(@info_label, false, false, 0)

	scrolled_win = Gtk::ScrolledWindow.new
	scrolled_win.border_width = 5

	# we define a vbox under scrolled window to give its children a structure
	@result_box = Gtk::VBox.new(false,0)
	halign = Gtk::Alignment.new 0, 0, 0, 0 # left align everythin in result_box
	halign.add @result_box

	scrolled_win.add_with_viewport(halign)
	scrolled_win.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC)
	scrolled_win.modify_bg(Gtk::STATE_NORMAL, Gdk::Color.parse("red")) # doesn't work

	event_box = Gtk::EventBox.new.add(scrolled_win)
	event_box.modify_bg(Gtk::STATE_NORMAL, Gdk::Color.parse("red"))
	location_box.pack_start(event_box, true,true, 0) # even this doesn't work


	location_halign = Gtk::Alignment.new 0, 0, 1, 1 # allows us to add padding to location_box. Can't find anything else in docs
	location_halign.add location_box
	location_halign.set_padding(5,5,5,5)

	# define the next tab	
	preference_vbox = Gtk::VBox.new(true, 5)
	heading1 = Gtk::Label.new
	heading1.set_markup("<big><b>Interface</b></big>")
	preference_vbox.pack_start(heading1, false, false, 5)

	preference_halign = Gtk::Alignment.new 0, 0, 0, 0 # allows us to add padding to location_box. Can't find anything else in docs
	preference_halign.add preference_vbox
	preference_halign.set_padding(5,5,5,5)

	# both tabs defined, now add them to the notebook
	nb.append_page(location_halign, label1)
	nb.append_page(preference_halign, label2)
	nb.append_page(button,  label3)
	nb.show_border=true # can't see the border?

	#everythin finished, close the dialog settings
	dialog.vbox.add(nb)
	dialog.set_size_request(400,350)
	dialog.resizable = false
	dialog.decorated = true
	dialog.show_all
	dialog.run
	dialog.destroy
end

@window = Gtk::Window.new("type = Gtk::WindowType::TOPLEVEL")
@window.resizable = false
@window.border_width = 10
@window.signal_connect('destroy') { Gtk.main_quit }
@window.set_size_request(350, 500)
# @window.modify_bg(Gtk::STATE_NORMAL, Gdk::Color.parse("red"))

@container = Gtk::VBox.new(false, 0)


image = Gtk::Image.new(Gtk::Stock::GO_FORWARD,'dialog')
image.set_tooltip_text("Set Location")

event_box = Gtk::EventBox.new.add(image)
event_box.signal_connect("button_press_event") do
	button_clicked(@window)
  	puts "Clicked."
end

halign = Gtk::Alignment.new 1, 0, 0, 0
halign.add event_box

@container.pack_start(halign, false, false, 0)

@window.add(@container)

@window.show_all
Gtk.main

Is their a better way?

EDIT - using gtk2

@kou
Copy link
Member

kou commented May 19, 2018

We can simplify it like the following?

      radio = nil
      @t.each do |name|
        label = "#{name["city"]}, #{name["countryCode"]}"
        if radio.nil?
          radio = Gtk::RadioButton.new(label)
        else
          radio = Gtk::RadioButton.new(radio, label)
        end
        halign = Gtk::Alignment.new 0, 0, 0, 0 # left align everythin in result_box
        halign.add radio

        #######
        # IS THERE A BETTER WAY TO ADD RESULTS TO A VBOX
        @result_box.add halign
        radio.show
        halign.show
      end

But what do you want to avoid?

@arjunmenon
Copy link
Contributor Author

This was more of a Gtk framework question, to see if there is a better way to add child to a parent. Since vbox was already created, I wanted to know if it is inefficient to modify boxes after they have been created.
Some of the other containers has specific methods which allows you to append child, like the textbuffers. I couldn't find anything for boxes.

Also, did you try doing ctrl+c to close the app? It introduces a segmentation fault. At first I thought it was because of vbox, but later found the problem to be because of Notebook.

Apparently adding notebook to dialogs introduces some low-level error, You can see that if you do ctrl+c in the terminal.

@kou
Copy link
Member

kou commented Jun 30, 2018

Ctrl+C didn't cause a segumentation fault on my environment:

% ruby /tmp/br.b
tk-Message: 21:33:46.653: Failed to load module "canberra-gtk-module"
^CTraceback (most recent call last):
	1: from /tmp/b.rb:141:in `<main>'
/tmp/b.rb:141:in `main': Interrupt

%

@kou
Copy link
Member

kou commented Dec 8, 2022

No response.

@kou kou closed this as not planned Won't fix, can't repro, duplicate, stale Dec 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants