Modify the default font in Python Tkinter
Solution 1
Tkinter has several built-in fonts -- TkDefaultFont
, TkTextFont
, TkFixedFont
, etc. These are all what are called "named fonts". They are remarkably powerful -- change one of these and all widgets that use them will change as well.
To change one of these fonts, get a handle to it and then use the configure
method to change. For example, to change the size of TkDefaultFont
to 48 you would do this:
default_font = tkFont.nametofont("TkDefaultFont")
default_font.configure(size=48)
That's it. You don't have to do anything else -- everything that uses TkDefaultFont
will instantly notice the change.
In your question you imply you want TkDefaultFont
font to be used by everything. To do that you can use option_add
as you've shown:
root.option_add("*Font", default_font)
Note, however, that option_add
only affects widgets created after you've called option_add
, so you need to do it before creating any other widgets.
Also note that you can give the font name to option_add
if you don't want to bother with getting the font instance first (ie: root.option_add("*Font", "TkDefaultFont")
).
Solution 2
Caveat: although the question involves Py2.7, my answer is for Py3. The concepts are exactly the same. But instead of tkinter.font
, one would use tkFont
for Py2, etc.
If you want to change a default font, or any named font, you have to access the font object via nametofont()
:
def_font = tkinter.font.nametofont("TkDefaultFont")
and then config the returned object, like
def_font.config(size=24)
When you call
myfont = tkinter.font.Font(font="TkDefaultFont")
you're actually creating a new named font that has the same attributes. To help show this:
str(def_font)
gives "TkDefaultFont", and
str(myfont)
gives "font1"
Oops.. Forgot to mention... You asked what you were doing wrong. One of the things is in your second line, you create and then config a new named font, but you don't capture it into a variable. If you captured it, you could use that named font. But that still would not modify the default named fonts. You would have to use nametofont()
as explained above to accomplish that.
ericc
Updated on February 11, 2020Comments
-
ericc almost 4 years
I'm working on a GUI in Python2.7, with Tkinter, and I have an annoying problem.
I would like to define the default font used by all the widgets, if possible in one line. This line modify only the font used in Entry, or ComboBox:
root.option_add("*Font", "courier 10")
but not the label of checkbox by example.
I found that a predefined font exist "TkDefaultFont" but I'm unable to change its configuration:
print tkFont.Font(font='TkDefaultFont').configure() tkFont.Font(font='TkDefaultFont').config(family='Helvetica', size=20) tk.TkDefaultFont = tkFont.Font(family="Helvetica",size=36,weight="bold") print tkFont.Font(font='TkDefaultFont').configure()
return :
{'family': 'DejaVu Sans', 'weight': 'normal', 'slant': 'roman', 'overstrike': 0, 'underline': 0, 'size': -12} {'family': 'DejaVu Sans', 'weight': 'normal', 'slant': 'roman', 'overstrike': 0, 'underline': 0, 'size': -12}
(no errors, but nothing change !!)
What I'm doing wrong ?
-
ArtOfWarfare over 7 yearsNever knew about the
nametofont
method before - thanks for mentioning it! I feel like the primary issue with Tkinter isn't so much an issue with the library (although it certainly has its quirks) so much as how much of it seems to be entirely undocumented. There's a passing mention thattkFont
exists in the docs, but then it never says anything about what it contains or how it works. -
JDM over 6 years@BryanOakley, I'm using the
root.option_add
method and it's working perfectly in my app but with one exception: the font option doesn't seem to carry through to aTreeview
widget I'm using one of the windows. My guess is this is because it's attk
widget rather thanTkinter
. -
Gary02127 almost 4 yearsAlso, as a side note, you need to have a Tk() or Toplevel() window open before Tkinter will let you do much with fonts...
-
user171780 almost 3 yearsIt would be nice to add
import tkinter.font as tkFont
in the first block code of this answer. -
peter.murray.rust over 2 yearsWhen I run your code I get ``` Traceback (most recent call last): File "/Users/pm286/projects/openDiagram/physchem/python/pysimpleg.py", line 434, in <module> test9() File "/Users/pm286/projects/openDiagram/physchem/python/pysimpleg.py", line 326, in test9 def_font = tkinter.font.nametofont("TkDefaultFont") File "/opt/anaconda3/lib/python3.8/tkinter/font.py", line 22, in nametofont] ... if self.name not in tk.splitlist(tk.call("font", "names")): AttributeError: 'NoneType' object has no attribute 'splitlist' ```
-
martineau over 1 year@user171780: That would not be correct for a question tagged "python-2.7".
-
martineau over 1 year@peter.murray.rust: When I use
tkinter.font.nametofont("TkDefaultFont")
in Python 3.8.10 it works fine — sounds like your installation oftkinter
may be messed-up. -
Billy over 1 year@BryanOakley I have a different scenario. I want to modify and use the
TkFixedFont
, but I don't want it to change all the widgets created after modification, instead only some specific widgets. How can I modify theTkFixedFont
without affecting all newly created widgets? -
Russell Smith over 1 year@Billy: you'll need those other widgets to use a different font object. It can have the same properties but it needs to be a different font object.
-
Billy over 1 year@BryanOakley Thanks for pointing out. For testing purposes, I tried creating a font using
nametofont
and then tried to inspect it. Turns out theTkFixedFont
isCourier New 10
. Now creating a new Font object with this data will solve the issue. -
Russell Smith over 1 year@Billy: the comment section isn't for extended discussions. It's quite possible to use the "Courier New" font as long as you do it properly.