Placing Sets of Ruby/Tk Widgets

After a whole day of frustrating “experimentation” with no good results,
I was ready to give up and ask this question:

How do I place two vertical sets of widgets (inside of a left and right
frame), two horizontal set of widgets (inside of a top and bottom frame)
and one set of rectanges in a square grid (inside of a middle center
canvas in a middle center frame) to control the location of my “sets”?

But then I got angry (both with myself and Ruby/Tk) and became
determined to figure it out without asking.

It took me hours and hours, but I fainally “nailed” it! The source of
my frustration was not realizing that the (:x,:y) coordinates were
relative to the parent widgets’ origin (in my example these are TkRoot
and TkFrames).

If you want to take a look (where I’ve use :background, :borderwidth and
:relief options to make the frames and canvas stand out), here is the
Ruby code:

require “tk”
root=TkRoot.new(:title=>'Ruby/Tk Geometry, Frame, Canvas, ’ +
‘and Widget Meanderings’, :geometry=>‘705x700’)

packer1 = { :fill=>:none }

Note: These (x,y) coordinates are relative to the parent widget’s

(TkRoot’s or TkFrame’s) origin

placer1 = { :x=>0, :y=>0 }; placer2 = { :x=>0, :y=>600 }
placer3 = { :x=>0, :y=>40 }; placer4 = { :x=>100, :y=>100 };
placer5 = { :x=>600, :y=>100 }; placer6 = { :x=>0, :y=>100 }

topFrame = TkFrame.new(root, :width=>705, :height=>100,
:borderwidth=>5, :relief=>:groove, :background=>:pink).place(placer1)
topFrameButton1 = TkButton.new(topFrame, :text=>‘TFButton 1’).
place(placer1)

middleLeftFrame = TkFrame.new(root, :width=>100, :height=>500,
:borderwidth=>5, :relief=>:groove, :background=>:cyan).place(placer6)
middleLeftFrameButton1 = TkButton.new(middleLeftFrame, :text=>
‘MLFButton 1’).place(placer1)
middleLeftFrameButton2 = TkButton.new(middleLeftFrame, :text=>
‘MLFButton 2’).place(placer3)

middleCenterFrame = TkFrame.new(root, :width=>500, :height=>500,
:borderwidth=>5, :relief=>:groove, :background=>:blue).place(placer4)
middleCenterCanvas = TkCanvas.new(middleCenterFrame, :width=>477,
:height=>477, :borderwidth=>5, :relief=>:groove,
:background=>:yellow).
pack(packer1)
middleCenterCanvasButton1 = TkButton.new(middleCenterCanvas, :text=>
‘MCCButton 1’).place(placer1)

middleRightFrame = TkFrame.new(root, :width=>105, :height=>500,
:borderwidth=>5, :relief=>:groove, :background=>:green).place(placer5)
middleRightFrameButton1 = TkButton.new(middleRightFrame, :text=>
‘MRFButton 1’).place(placer1)

bottomFrame = TkFrame.new(root, :width=>705, :height=>100,
:borderwidth=>5, :relief=>:groove,
:background=>:orange).place(placer2)
bottomFrameButton1 = TkButton.new(bottomFrame, :text=>‘BFButton 1’).
place(placer1)

ev_quit = TkVirtualEvent.new(‘Control-c’, ‘Control-q’, ‘q’)
Tk.root.bind(ev_quit, proc{Tk.exit}).focus
Tk.mainloop

From: David B. [email protected]
Subject: Placing Sets of Ruby/Tk Widgets
Date: Mon, 3 Apr 2006 01:25:46 +0900
Message-ID: [email protected]

But then I got angry (both with myself and Ruby/Tk) and became
determined to figure it out without asking.

It took me hours and hours, but I fainally “nailed” it! The source of
my frustration was not realizing that the (:x,:y) coordinates were
relative to the parent widgets’ origin (in my example these are TkRoot
and TkFrames).

Please cool down. :slight_smile:
Probably, Pack geometry manager is enough for your case.

In many cases, Pack geometry manager is good choice.
In many cases of others (e.g. layout a widget with both of a horizontal
and a vertical scrollbar), Grid geometry manager is suitable.
And in extremely rase case, Place geometry manager (or layout on the
canvas widget) is necessary.

I think that it is not difficult to study Pack geometry manager.
Its strategy of layout is simple but working very well.
The following is rewrite-version of your example with Pack.
Please see that there is no coordinate except putting a widget on
a canvas widget and there are minimum controls to fix the widget size.

require ‘tk’

root=TkRoot.new(:title=>'Ruby/Tk Geometry, Frame, Canvas, ’ +
‘and Widget Meanderings’, :geometry=>‘705x700’)

#-----------------------------------
topFrame = TkFrame.new(root, :height=>100, :borderwidth=>5,
:relief=>:groove,
:background=>:pink).pack(:fill=>:x,
:expand=>false)
topFrame.pack_propagate(false) # if you must keep the height of the
frame.

topFrameButton1 = TkButton.new(topFrame, :text=>‘TFButton 1’)
topFrameButton1.pack(:side=>:left, :anchor=>:nw)

#-----------------------------------
middleFrame = TkFrame.new(root).pack(:fill=>:both, :expand=>true)

#-----------------------------------
middleLeftFrame = TkFrame.new(middleFrame, :width=>100, :borderwidth=>5,
:relief=>:groove, :background=>:cyan)
middleLeftFrame.pack(:side=>:left, :fill=>:y, :expand=>false)

middleLeftFrameButton1 = TkButton.new(middleLeftFrame, :text=>‘MLFButton
1’)
middleLeftFrameButton1.pack(:fill=>:x, :expand=>false)

middleLeftFrameButton2 = TkButton.new(middleLeftFrame, :text=>‘MLFButton
2’)
middleLeftFrameButton2.pack(:fill=>:x, :expand=>false)

#-----------------------------------
middleCenterFrame = TkFrame.new(middleFrame, :borderwidth=>5,
:relief=>:groove, :background=>:blue)
middleCenterFrame.pack(:side=>:left, :fill=>:both, :expand=>true)

middleCenterCanvas = TkCanvas.new(middleCenterFrame, :borderwidth=>5,
:relief=>:groove,
:background=>:yellow)
middleCenterCanvas.pack(:fill=>:both, :expand=>true, :padx=>5, :pady=>5)

middleCenterCanvasButton1 = TkButton.new(middleCenterCanvas,
:text=>‘MCCButton 1’)

??? Do you want to put the button “ON” the canvas?

middleCenterCanvasButton1.place(:x=>0,:y=>0)

canvasButton1Win = TkcWindow.new(middleCenterCanvas, [0, 0],
:anchor=>:nw,
:window=>middleCenterCanvasButton1)

#-----------------------------------
middleRightFrame = TkFrame.new(middleFrame, :width=>105,
:borderwidth=>5,
:relief=>:groove, :background=>:green)
middleRightFrame.pack(:side=>:left, :fill=>:y, :expand=>false)

middleRightFrameButton1 = TkButton.new(middleRightFrame,
:text=>‘MRFButton 1’)
middleRightFrameButton1.pack(:fill=>:x, :expand=>false)

#-----------------------------------
bottomFrame = TkFrame.new(root, :height=>100,
:borderwidth=>5, :relief=>:groove,
:background=>:orange).pack(:fill=>:x,
:expand=>false)
bottomFrame.pack_propagate(false) # if you must keep the height of the
frame.

bottomFrameButton1 = TkButton.new(bottomFrame, :text=>‘BFButton 1’,
:command=>proc{p root.geometry}
)
bottomFrameButton1.pack(:side=>:left, :anchor=>:nw)

#-----------------------------------
ev_quit = TkVirtualEvent.new(‘Control-c’, ‘Control-q’, ‘q’)
Tk.root.bind(ev_quit, proc{Tk.exit}).focus
Tk.mainloop

Hidetoshi NAGAI wrote:

Please cool down. :slight_smile:
Probably, Pack geometry manager is enough for your case.


bottomFrameButton1 = TkButton.new(bottomFrame, :text=>‘BFButton 1’,
:command=>proc{p root.geometry}
)

Wow! Once again, brute force must bow to finesse!

I did not notice the pack_propagate() method, before. That was key.

Also, what does the bottomFrameButton1’s “{:command=>{p root.geometry}”
do? And why did you NOT use it in the topFrameButton1?

Thanks.

P.S. Yes, I will cool down. (:>)

David B. wrote:

Also, what does the bottomFrameButton1’s “{:command=>{p root.geometry}”
do? And why did you NOT use it in the topFrameButton1?

Oh, you’re just printing out the geometry when the button is clicked.
Bingo!

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs