How to change a widget's font style without knowing the widget's font family/size?
Question:
Is there a way to change a Tkinter widget’s font style without knowing the widget’s font family and font size?
Use case: We create our UI using standard Tkinter widgets (Label, Entry, Text, etc). While our application runs we may want to dynamically change the font style of these widgets to bold and/or italics using the .config()
method. Unfortunately there appears to be no way to specify a font spec without specifying the font’s family and size.
The following are examples of what we’d like to do, but neither of these examples work:
widget.config(font='bold')
or
widget.config(font=( None, None, 'bold' ))
Answers:
If you are using a named font, you can use a couple statements to get what you want:
import tkFont
wfont = tkFont.nametofont(widget['font'])
wfont.config(weight='bold')
Edited to incorporate B. Oakley’s comment.
There’s a much better way than using .config()
to change your application font, especially if your goal is to change the font for a whole group of widgets or all widgets.
One of the really great features of Tk is the notion of "named fonts", which are implemented as objects in tkinter. The beauty of named fonts is, if you update the font, all widgets that use that font will automatically get updated. So, configure your widgets once to use a font object, then you can update all widgets at once simply by changing the configuration of the font object.
Here’s a quick example:
import tkinter as tk
import tkinter.font
class App:
def __init__(self):
root=tk.Tk()
# create a custom font
self.customFont = tkinter.font.Font(family="Helvetica", size=12)
# create a couple widgets that use that font
buttonframe = tk.Frame()
label = tk.Label(root, text="Hello, world", font=self.customFont)
text = tk.Text(root, width=20, height=2, font=self.customFont)
buttonframe.pack(side="top", fill="x")
label.pack(side="top", fill="x")
text.pack(side="top", fill="both", expand=True)
text.insert("end","press +/- buttons to changenfont size")
# create buttons to adjust the font
increase_font = tk.Button(root, text="+", command=self.increase_font)
decrease_font = tk.Button(root, text="-", command=self.decrease_font)
increase_font.pack(in_=buttonframe, side="left")
decrease_font.pack(in_=buttonframe, side="left")
root.mainloop()
def increase_font(self):
'''Make the font 2 points bigger'''
size = self.customFont['size']
self.customFont.configure(size=size+2)
def decrease_font(self):
'''Make the font 2 points smaller'''
size = self.customFont['size']
self.customFont.configure(size=size-2)
app=App()
If you don’t like that approach, or if you want to base your custom font on the default font, or if you’re just changing one or two fonts to denote state, you can use font.actual
to get the actual size of a font for a given widget. For example:
import tkinter as tk
import tkinter.font
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
font = tkinter.font.Font(font=label['font'])
print(font.actual())
When I run the above I get the following output:
{'family': 'Lucida Grande',
'weight': 'normal',
'slant': 'roman',
'overstrike': False,
'underline': False,
'size': 13}
To boil much of the above information down to a single code snippet:
lbl = ttk.Label(blah, blah) # Make a label
font = tkFont(lbl['font']) # Get its font
font.config(weight='bold') # Modify font attributes
lbl['font'] = font # Tell the label to use the modified font
This permits font attributes to be changed independent of the font in use (so long as the font supports that attribute).
You can also do this on the fly, to create truly nauseating font effects.
Even shorter for just one Label:
from Tkinter import *
import Tkinter as tk
root = tk.Tk()
# font="-weight bold" does your thing
example = Label(root, text="This is a bold example.", font="-weight bold")
example.pack()
root.mainloop()
just use the basic attributes of a particular widget, suppose you want to change the font of a label. You can use the following syntax:
mlabel = Label(text="Your text", font=("Name of your font",size))
this code works for python 3.4
Although it’s been quite some time since this Q was asked, I recently had to implement a solution to this, which I thought worth sharing. The function widget_font_config(…) runs on Python 2 and 3.
In essence, the “current value” of the widget’s font is grabbed, modified, and then put back. Named fonts are supported, and the default inplace_f value of True means that named fonts will be preserved and modified in place. But the flag can also be set to False, which will cause a named font to be replaced with a different named font, in case the user does not wish for the changes in the font of the widget to percolate to all other widgets which use the named font.
def widget_font_config(widget, inplace_f=True, **kwargs):
import sys
if sys.version_info[0] == 2:
import tkFont as tk_font
else:
import tkinter.font as tk_font
inplace_f = kwargs.pop('inplace', inplace_f)
font = None
if widget and 'font' in widget.config():
current_font = widget.cget('font') #grabs current value
namedfont_f = False
try:
font = tk_font.nametofont(current_font)
namedfont_f = True
except:
font = current_font
if namedfont_f and inplace_f:
font.config(**kwargs)
else:
font_d = tk_font.Font(font=font).actual()
font_d.update(**kwargs)
font = tk_font.Font(**font_d)
widget.config(font=font)
widget.update_idletasks()
return font
if __name__ == '__main__':
import sys
pyVers = sys.version_info[0] # .major
if pyVers == 2:
import Tkinter as tk, tkFont as tk_font
else:
import tkinter as tk, tkinter.font as tk_font
def go():
print(widget_font_config(root.label, slant='roman', underline=1).actual())
print(widget_font_config(root.button, overstrike=1).actual())
root = tk.Tk()
font_s = 'Courier 20 italic'
font_d = dict(family='Courier', size=10, weight='normal', slant='italic')
font = tk_font.Font(**font_d)
root.label = tk.Label(text='Label {}'.format(font_s), font=font_s)
root.label.pack()
root.button = tk.Button(text='Button {}'.format(font), font=font, command=go)
root.button.pack()
root.mainloop()
To get the default font without touching or having a widget you can use the generic name of the default font.
#!/usr/bin/env python3
import tkinter
import tkinter.font # Python3!
tkinter.Tk()
default_font = tkinter.font.Font(font='TkDefaultFont')
print(default_font.actual())
I know this question is really old, but I am still going to answer for the sake of people from google.
If you just want to make the text a bit bigger, you can do font=15
. Note this seems to always set the font size to 15, no matter what number is entered.
If want an exact size and have not changed the font, you can do font=('TkDefaultFont', 15)
.
('TkDefaultFont'
is the default font for tkinter)
You can use either of these in the parameters of the widget on creation, or later with .config()
.
Works in python 3.6.4
Is there a way to change a Tkinter widget’s font style without knowing the widget’s font family and font size?
Use case: We create our UI using standard Tkinter widgets (Label, Entry, Text, etc). While our application runs we may want to dynamically change the font style of these widgets to bold and/or italics using the .config()
method. Unfortunately there appears to be no way to specify a font spec without specifying the font’s family and size.
The following are examples of what we’d like to do, but neither of these examples work:
widget.config(font='bold')
or
widget.config(font=( None, None, 'bold' ))
If you are using a named font, you can use a couple statements to get what you want:
import tkFont
wfont = tkFont.nametofont(widget['font'])
wfont.config(weight='bold')
Edited to incorporate B. Oakley’s comment.
There’s a much better way than using .config()
to change your application font, especially if your goal is to change the font for a whole group of widgets or all widgets.
One of the really great features of Tk is the notion of "named fonts", which are implemented as objects in tkinter. The beauty of named fonts is, if you update the font, all widgets that use that font will automatically get updated. So, configure your widgets once to use a font object, then you can update all widgets at once simply by changing the configuration of the font object.
Here’s a quick example:
import tkinter as tk
import tkinter.font
class App:
def __init__(self):
root=tk.Tk()
# create a custom font
self.customFont = tkinter.font.Font(family="Helvetica", size=12)
# create a couple widgets that use that font
buttonframe = tk.Frame()
label = tk.Label(root, text="Hello, world", font=self.customFont)
text = tk.Text(root, width=20, height=2, font=self.customFont)
buttonframe.pack(side="top", fill="x")
label.pack(side="top", fill="x")
text.pack(side="top", fill="both", expand=True)
text.insert("end","press +/- buttons to changenfont size")
# create buttons to adjust the font
increase_font = tk.Button(root, text="+", command=self.increase_font)
decrease_font = tk.Button(root, text="-", command=self.decrease_font)
increase_font.pack(in_=buttonframe, side="left")
decrease_font.pack(in_=buttonframe, side="left")
root.mainloop()
def increase_font(self):
'''Make the font 2 points bigger'''
size = self.customFont['size']
self.customFont.configure(size=size+2)
def decrease_font(self):
'''Make the font 2 points smaller'''
size = self.customFont['size']
self.customFont.configure(size=size-2)
app=App()
If you don’t like that approach, or if you want to base your custom font on the default font, or if you’re just changing one or two fonts to denote state, you can use font.actual
to get the actual size of a font for a given widget. For example:
import tkinter as tk
import tkinter.font
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
font = tkinter.font.Font(font=label['font'])
print(font.actual())
When I run the above I get the following output:
{'family': 'Lucida Grande',
'weight': 'normal',
'slant': 'roman',
'overstrike': False,
'underline': False,
'size': 13}
To boil much of the above information down to a single code snippet:
lbl = ttk.Label(blah, blah) # Make a label
font = tkFont(lbl['font']) # Get its font
font.config(weight='bold') # Modify font attributes
lbl['font'] = font # Tell the label to use the modified font
This permits font attributes to be changed independent of the font in use (so long as the font supports that attribute).
You can also do this on the fly, to create truly nauseating font effects.
Even shorter for just one Label:
from Tkinter import *
import Tkinter as tk
root = tk.Tk()
# font="-weight bold" does your thing
example = Label(root, text="This is a bold example.", font="-weight bold")
example.pack()
root.mainloop()
just use the basic attributes of a particular widget, suppose you want to change the font of a label. You can use the following syntax:
mlabel = Label(text="Your text", font=("Name of your font",size))
this code works for python 3.4
Although it’s been quite some time since this Q was asked, I recently had to implement a solution to this, which I thought worth sharing. The function widget_font_config(…) runs on Python 2 and 3.
In essence, the “current value” of the widget’s font is grabbed, modified, and then put back. Named fonts are supported, and the default inplace_f value of True means that named fonts will be preserved and modified in place. But the flag can also be set to False, which will cause a named font to be replaced with a different named font, in case the user does not wish for the changes in the font of the widget to percolate to all other widgets which use the named font.
def widget_font_config(widget, inplace_f=True, **kwargs):
import sys
if sys.version_info[0] == 2:
import tkFont as tk_font
else:
import tkinter.font as tk_font
inplace_f = kwargs.pop('inplace', inplace_f)
font = None
if widget and 'font' in widget.config():
current_font = widget.cget('font') #grabs current value
namedfont_f = False
try:
font = tk_font.nametofont(current_font)
namedfont_f = True
except:
font = current_font
if namedfont_f and inplace_f:
font.config(**kwargs)
else:
font_d = tk_font.Font(font=font).actual()
font_d.update(**kwargs)
font = tk_font.Font(**font_d)
widget.config(font=font)
widget.update_idletasks()
return font
if __name__ == '__main__':
import sys
pyVers = sys.version_info[0] # .major
if pyVers == 2:
import Tkinter as tk, tkFont as tk_font
else:
import tkinter as tk, tkinter.font as tk_font
def go():
print(widget_font_config(root.label, slant='roman', underline=1).actual())
print(widget_font_config(root.button, overstrike=1).actual())
root = tk.Tk()
font_s = 'Courier 20 italic'
font_d = dict(family='Courier', size=10, weight='normal', slant='italic')
font = tk_font.Font(**font_d)
root.label = tk.Label(text='Label {}'.format(font_s), font=font_s)
root.label.pack()
root.button = tk.Button(text='Button {}'.format(font), font=font, command=go)
root.button.pack()
root.mainloop()
To get the default font without touching or having a widget you can use the generic name of the default font.
#!/usr/bin/env python3
import tkinter
import tkinter.font # Python3!
tkinter.Tk()
default_font = tkinter.font.Font(font='TkDefaultFont')
print(default_font.actual())
I know this question is really old, but I am still going to answer for the sake of people from google.
If you just want to make the text a bit bigger, you can do font=15
. Note this seems to always set the font size to 15, no matter what number is entered.
If want an exact size and have not changed the font, you can do font=('TkDefaultFont', 15)
.
('TkDefaultFont'
is the default font for tkinter)
You can use either of these in the parameters of the widget on creation, or later with .config()
.
Works in python 3.6.4