Placing Sets of Ruby/Tk Widgets

D

David Bailey

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=>:eek:range).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
 
H

Hidetoshi NAGAI

From: David Bailey <[email protected]>
Subject: Placing Sets of Ruby/Tk Widgets
Date: Mon, 3 Apr 2006 01:25:46 +0900
Message-ID: said:
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. :)
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=>:eek:range).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
 
D

David Bailey

Hidetoshi said:
Please cool down. :)
Probably, Pack geometry manager is enough for your case.


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. :)>)
 
D

David Bailey

David said:
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!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,692
Latest member
JenniferTi

Latest Threads

Top