Updated 2016-04-27 17:04:32 by bll

User Interface Design: Sizing of Elements  edit

bll 2015-10-21

This page will primarily discuss the sizing of various elements (widgets) in a modern environment and how to create a user interface that works in an international environment and for various different resolutions.

Localization affects the user interface display as the text widths can vary wildly with compact languages such as Japanese and not so compact languages such as Spanish and Portuguese.

With the advent of 4k displays and huge range of resolutions from 24 inch 2k desktops to 1k laptops to 1k phones to 4k laptops, sizing elements based on pixels has become something that should be avoided at all costs.

With font scaling, font measure, full unicode support, localization support, and dynamic GUI sizing, Tk is well positioned to provide localized graphical user interfaces that work on all sizes and resolutions of monitors.

[NickR] 2016-4-27

Thank you for your many nice suggestions above. I am currently working on upgrading an old Tk program to work better on high resolution displays.

At the moment, I am not sure how applicable these suggestions are. I guess the gist is that one should work with points and not pixels. But I am not sure how to apply this technique. For example, I am not concerned about frame sizing, but I am with toplevel sizing. But various wm commands only work with sizes in pixels. And tk scaling is set up already after I load Tk and it gives me the right scaling factor so how am I to apply it again?

I guess what would be useful is to have a function that maps a size in pixels to an approximately the same size in points or characters.

Do you have an idea of what such a function would look like?

bll 2016-4-27: You would use a similar setup as the frame section below, but the configuration line changes. Just set your toplevel width based on the width of the '0' character.
  toplevel .mytoplevel
  set wid [expr {25*[font measure TkDefaultFont 0]}]
  .mytoplevel configure -width $wid

Make sure that tk scaling is set at the first step in your program before any widgets or fonts are created.

Fonts  edit

Often fonts get sized as a height in pixels. Fortunately, Tk defaults to a size in points so this is less of a problem than in some other GUI environments (e.g. web pages).

Whether the font is sized in pixels or points, imagine what happens when your program is moved from a 24 inch 2k monitor to a 14 inch 4k laptop screen. It will get very small indeed.

If the font is sized in pixels, nothing can be done other than to resize the font. However, if the font size is specified in points, setting the tk scaling appropriately as the first step in setting up a program will automatically size the fonts appropriately and give a nice default font size. The tk scaling wiki page has a couple of example setup scripts.

User configurable font sizes may seem like extra work, but every user has different vision capabilities and may need or want a different size font for their needs and their computer setup. It's very easy to implement user configurable font sizing. This can be done at program startup or in a completely dynamic fashion. Most of the widgets can be styled once, and the other widgets can be configured when instantiated.

Setting a font to a bold weight may not work for some languages that have complex characters (e.g. Chinese). The bold weight simply makes the character lines bleed into each other and the font becomes unreadable.
  font configure mydefault -size $mydefaultsize

  font configure mysmallerdefault -size [expr {$mydefaultsize-2}]

  ttk::style configure My.TLabel -font mydefault

  ttk::style configure MySmall.TLabel -font mysmallerdefault

  ttk::combobox .mycombo -font mydefault

(a) Always set tk scaling for each computer and monitor.

(b) Always specify font sizes in points.

(c) Allow the user to change the font size.

(d) Be careful using bold fonts with complex international characters.

(Note: font sizes on the mac seem to include the line spacing (try measuring a 72 point font on the mac, windows and linux). I ended up multiplying font sizes on the mac by 1.3 to get approximately the correct size.)

Buttons  edit

Buttons are set with a minimum width of 11 characters. My guess this was done so that buttons would generally be about the same size for most usage cases and would make the user interface look proper with similar sized buttons.

Unfortunately, 11 characters is a fairly large width in many cases and the automatic reaction of the programmer is to change the width to some smaller size. This does not work well when the button text must be localized.

The button's width is also dependent upon the current theme's styling. The following code will adjust the button width to a smaller default width.
  set wid [ttk::style lookup My.TButton -width]
  if { $wid < -8 } {
    ttk::style configure My.TButton -width -8
  }

Another common use of the width option for a button is to get buttons of equal width. Again this doesn't work out when the button text must be localized. The following example shows how to create equal width buttons on a single line (from They aren't wide enough).
  frame .f0
  frame .f1

  button .f0.b01 -text Simple
  button .f0.b02 -text Complicated
  button .f0.b03 -text Done

  button .f1.b01 -text Simple -width 10
  button .f1.b02 -text Complicated -width 10
  button .f1.b03 -text Done -width 10

  pack .f0 .f1
  grid columnconfigure .f0 {0 1 2} -weight 1 -uniform f0
  grid .f0.b01 .f0.b02 .f0.b03 -sticky ew
  grid .f1.b01 .f1.b02 .f1.b03

For the simplistic approach, it would be better to specify -width -10 to get a minimum width rather than specifying a maximum width.

It is also easy to get a column of buttons to be the same width using the -sticky ew option with grid or using -fill x with pack.
  # try using a no default width for buttons that get
  # gridded with -sticky or packed with -fill x
  ttk::style configure MyBasic.TButton -width {}

(e) Never set the button width to a fixed maximum value.

(f) Use the grid options -sticky and -uniform to adjust the widths of multiple buttons to match each other.

Comboboxes  edit

Unfortunately, comboboxes have a preset default width. This does not work when trying to localize the combobox text. With compact languages, there's too much extra space or too little space with less compact languages.

See Combobox Enhancements for a method to reset the width of the combobox.

For localization purposes, Tk comboboxes have a fatal flaw in that they return the display value and there's no way to assign values to return for the selection. The Combobox Enhancements page also outlines a method to handle this issue.

(g) Set the width of comboboxes dynamically to adjust to the localized text.

Frames and Spacing  edit

Frame sizes are measured in pixels. Often a minimum frame size is wanted so that the user interface will have space to utilize. However, setting a minimum frame size in pixels will not work when transferring the program to a high resolution 4k laptop screen.

The solution is to count in characters. For example if a 250px frame width is wanted, set the frame width as:
  set wid [expr {25*[font measure mydefault 0]}]
  ttk::frame .myframe -width $wid

This will be sized appropriately for all resolutions and will work with the user's selected font size.

Similarly any spacing between elements should be counted in characters and font measure may be used to get an appropriate sized spacing value.

(h) Set frame widths and spacing using characters with font measure rather than in pixels.

Labels  edit

Label text may be any width depending on localized text. If the text is long and may get wrapped, the wraplength should be measured in characters using font measure.

If the display text is quite long, it is easier to use a text widget to display the text and handle the wrapping of the display.

(i) Never set the label width.

Padding / Borders  edit

Padding sizes and border widths are normally specified in pixels. As always, on a 4k display this can be problematic as a 1 pixel pad is very small with high resolution displays.

dzach 2015-12-09: Another way would to specify absolute sizes would be by using the following units, all allowed by Tk:
 c
    The number specifies a distance in centimeters on the screen.
 i
    The number specifies a distance in inches on the screen.
 m
    The number specifies a distance in millimeters on the screen.
 p
    The number specifies a distance in printer's points (1/72 inch) on the screen.

(from the Tk manual).

bll 2015-12-11: Excellent, I had forgotten about that. Simply substituting points instead of pixels seems to work out quite well (e.g. -padx 1p)

(j) Use points or mm to specify the padding and borderwidth sizes.

General User Interface Sizing  edit

Personally, I (bll) have never understood the desire to make every element a certain size. I know some of this desire is due to trying to make the user interface look absolutely identical on different platforms. Again this just doesn't work out well when localizing the text.

With Tk, what I found works well is to let the display size itself the first time, then save the size as reported by wm geometry. Then this size can be restored when the program is run again. This also preserves any user changes to the window size.

See also:

When size matters A well written complaint about localization of text.

Tk internationalization A version of tk_optionMenu that works with localization.

Notes:

This page does not attempt to address right-to-left languages.