Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a Tkinter widget to a monospaced, platform independent font?

It's said here in the section Standard Fonts:

Particularly for more-or-less standard user interface elements, each platform defines specific fonts that should be used. Tk encapsulates many of these into a standard set of fonts that are always available, and of course the standard widgets use these fonts. This helps abstract away platform differences.

And then in the predefined fonts list there is:

TkFixedFont A standard fixed-width font.

This also corresponds with what I could find here on the standard ways of choosing a monospaced, platform independent font in Tkinter like for example stated in this answer.

Alas, when I try to do this on my own, like with the simple code below:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
frame = ttk.Frame(root)
style = ttk.Style()
style.configure("Fixed.TButton", font=("TkFixedFont", 16))

button = ttk.Button(text="Some monospaced text, hopefully", style="Fixed.TButton")
frame.grid()
button.grid(sticky="news")
button.configure(text="I don't quite like this font.")

what I get is this:

TkFixedFont, size 16

That doesn't look like monospaced to me, so I check what exactly Tkinter translates TkFixedFont into on my platform with:

from tkinter import font
font.nametofont("TkFixedFont").actual()

and the answer is:

{'family': 'DejaVu Sans Mono', 'size': 9, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}

So how does DejaVu Sans Mono look like?

DejaVu Sans Mono, size 16

The Tkdocs.com tutorial quoted above has also a section on Named Fonts and there it says:

the names Courier, Times, and Helvetica are guaranteed to be supported (and mapped to an appropriate monospaced, serif, or sans-serif font)

So I try with:

style.configure("Courier.TButton", font=("Courier", 16))
button.configure(style="Courier.TButton")

and now finally I get a monospaced result:

enter image description here

Admittedly, it's Courier New and not DejaVu Sans Mono that my platform chooses as the standard monospaced font, but that's at least something, right? But shouldn't TkFixedFont just work?

like image 535
z33k Avatar asked Feb 11 '18 13:02

z33k


1 Answers

Standard fonts (including TkFixedFont) can only be given as a plain string, not as a tuple. I.e. font='TkFixedFont' works, while font=('TkFixedFont',) (note the parentheses and comma) will not.

This seems to be the general case. I tried it with both Tkinter.Button and ttk.Style.

For styles that means:

import Tkinter
import ttk

# will use the default (non-monospaced) font
broken = ttk.Style()
broken.configure('Broken.TButton', font=('TkFixedFont', 16))

# will work but use Courier or something resembling it
courier = ttk.Style()
courier.configure('Courier.TButton', font=('Courier', 16))

# will work nicely and use the system default monospace font
fixed = ttk.Style()
fixed.configure('Fixed.TButton', font='TkFixedFont')

Tested to work with Python 2.7 on both Linux and Windows.

Bottom line is that the code in the question will work perfectly fine if just the parentheses around "TkFixedFont" were removed.

like image 140
Friedrich Avatar answered Sep 30 '22 01:09

Friedrich