How to set a Tkinter widget to a monospaced, platform independent font?
Question:
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:
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?
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:
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?
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 [Edit: and it’s still true as of today on Python 3.x]
Bottom line is that the code in the question will work perfectly fine if just the parentheses around "TkFixedFont"
were removed.
I’m not as well versed in TkInter intricacies now as I used to be this 4 months ago but a quick look here confirmed my worry you’re talking about tkinter.Button (which can be initialized with font option) and I asked about tkinter.tkk.Button which doesn’t have it. Probably I should’ve made it more clear in the title that the question was about ttk widgets –
z33k
Jul 4, 2018 at 22:20
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:
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?
The Tkdocs.com tutorial quoted above has also a section on Named Fonts and there it says:
the names
Courier
,Times
, andHelvetica
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:
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?
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 [Edit: and it’s still true as of today on Python 3.x]
Bottom line is that the code in the question will work perfectly fine if just the parentheses around "TkFixedFont"
were removed.
I’m not as well versed in TkInter intricacies now as I used to be this 4 months ago but a quick look here confirmed my worry you’re talking about tkinter.Button (which can be initialized with font option) and I asked about tkinter.tkk.Button which doesn’t have it. Probably I should’ve made it more clear in the title that the question was about ttk widgets –
z33k
Jul 4, 2018 at 22:20