1
votes

I want to create a window with two text boxes one on top of another with first occupying 25% of height and next occupying 75% of height.

I tried to calculate relative height/width of toplevel win and pass into text command but didn't work (I am guessing because the units of dimension returned by wm geometry is not the same as when passed to text command)

Following is my code:

toplevel .t
wm geometry .t 1500x800+10+10
update
proc topAspect {args} {
    regexp {(\d+)} $args -> relAspect
    regexp {([^\d|%]+)} $args -> aspect
    regexp {(.*)x(.*)[+-](.*)[+-](.*)} [wm geometry .t] -> width height x y
    puts "width->$width height->$height x->$x y->$y"
    switch -regexp [string tolower $aspect] {
        x {
            return [expr $x + $relAspect]
        }
        y {
            return [expr $y + $relAspect]
        }
        w {
            return [expr $width * $relAspect / 100]
        }
        h {
            return [expr $height * $relAspect / 100]
        }
        default {
            log::log error "Unsupported relative aspect $aspect cannot be determined for top level window"
        }
    }
}

text  .t.text1 -height [topAspect -width 25%] -width [topAspect -width 99%]
grid .t.text1 -sticky news
text  .t.text2 -height [topAspect -width 75%] -width [topAspect -width 99%]
grid .t.text2 -sticky news

When I tried following - it did give me some decent GUI:

text  .t.text1 -height 20 -width [topAspect -width 99%]
grid .t.text1 -sticky news
text  .t.text2 -height 20 -width [topAspect -width 99%]
grid .t.text2 -sticky news

But i want to use the relative options. How to make it work?

3

3 Answers

2
votes

The easiest way to solve this is to use the grid geometry manager with weights in the right ratio and a uniform group. It will even work fine when you resize the window; Tk knows the policy itself and maintains it for you. (Internally, grid is a fairly sophisticated constraint solver; you can do some really complicated stuff with it.)

toplevel .t
grid [text .t.text1 -bg red]   -sticky news
grid [text .t.text2 -bg green] -sticky news

# The group name is just an arbitrary non-empty string.
# So long as it is the same on the two rows it will work as desired.
# The weights give a ratio of 1:3, i.e., 25% to one and 75% to the other.

grid rowconfigure .t .t.text1 -weight 1 -uniform group1
grid rowconfigure .t .t.text2 -weight 3 -uniform group1

(If you're using Tk 8.5, you'll need to specify the rows to rowconfigure by number instead of the often-more-convenient name of a widget in the row.)

1
votes

Yes, the -height and -width options for the text widget are given in character units, not screen units. You can fix that by further dividing by font width and height (I set them to constant values below). Remember that this is integer division!

Oooh, all those regexes… I’ve cleaned up a bit, you can take it or leave it.

proc topAspect {aspect relAspect} {
    set relAspect [string trimright $relAspect %]
    scan [wm geometry .t] "%dx%d%d%d" width height x y
    set fontWidth 15
    set fontHeight 15
    switch -regexp [string tolower $aspect] {
        x {
            return [expr {$x + $relAspect}]
        }
        y {
            return [expr {$y + $relAspect}]
        }
        w {
            return [expr {($width * $relAspect / 100) / $fontWidth}]
        }
        h {
            return [expr {($height * $relAspect / 100) / $fontHeight}]
        }
        default {
            log::log error "Unsupported relative aspect $aspect cannot be determined for top level window"
        }
    }
}

Also, you used -width as an argument to topAspect for both -height and -width: I presume that was a mistake.

text  .t.text1 -height [topAspect -height 25%] -width [topAspect -width 99%]
grid .t.text1 -sticky news
text  .t.text2 -height [topAspect -height 75%] -width [topAspect -width 99%]
grid .t.text2 -sticky news

Otherwise, I recommend Donal Fellows’s solution.

Documentation: * (operator), + (operator), / (operator), expr, for, grid, proc, return, scan, set, string, switch, text (widget), wm, Syntax of Tcl regular expressions

0
votes

Place worked best in this case - even on resizing the following held out the proportions well:

place .t.text1  -in .t -relheight .25 -relwidth .98 -relx .003 -rely .003
place .t.text2 -in .t -relheight .75 -relwidth .98 -relx .003 -rely .254

Is there any pitfall that anyone sees in this approach as compared to grid.

Thank you