Change font size without messing with Tkinter button size
Solution 1
The width of the button is defined in units of character width. In your case the button is defined to be 17 characters wide. So changing the character width by (ie changing the font size) changes the width of the button. AFAIK, the only way around that is to put the button into a Frame, because a Frame can define it's size in pixels. Here's a new kind of Button that does exactly that:
import Tkinter as tk
class Warspyking(tk.Frame):
'''A button that has it's width and height set in pixels'''
def __init__(self, master=None, **kwargs):
tk.Frame.__init__(self, master)
self.rowconfigure(0, minsize=kwargs.pop('height', None))
self.columnconfigure(0, minsize=kwargs.pop('width', None))
self.btn = tk.Button(self, **kwargs)
self.btn.grid(row=0, column=0, sticky="nsew")
self.config = self.btn.config
#example usage:
MyWindow = tk.Tk()
MyWindow.geometry("500x550")
from itertools import cycle
fonts = cycle((('Helvetica', '11'),('Helvetica', '15'),('Helvetica', '20')))
def chg():
button.config(font=next(fonts))
button = Warspyking(MyWindow,text="Click me!",width=200,height=100 ,font=next(fonts), command=chg)
button.grid(row=1, column=1)
MyWindow.mainloop()
EDIT: Based on what I learned from Bryan Oakley, here's a much neater implementation:
class Warspyking(tk.Button):
def __init__(self, master=None, **kwargs):
self.img = tk.PhotoImage()
tk.Button.__init__(self, master, image=self.img, compound='center', **kwargs)
I should also add that I very much agree with Bryan: Using this is probably a sign that you are doing something wrong. You should let tkinter handle sizing.
Solution 2
Typically, when you give a button a width, that width is measured in characters (ie: width=1
means the width of one average sized character). However, if the button has an image then the width specifies a size in pixels.
A button can contain both an image and text, so one strategy is to put a 1x1 pixel as an image so that you can specify the button size in pixels. When you do that and you change the font size, the button will not grow since it was given an absolute size.
Here is an example that illustrates the technique. Run the code, then click on "bigger" or "smaller" to see that the text changes size but the button does not.
import Tkinter as tk
import tkFont
def bigger():
size = font.cget("size")
font.configure(size=size+2)
def smaller():
size = font.cget("size")
size = max(2, size-2)
font.configure(size=size)
root = tk.Tk()
font = tkFont.Font(family="Helvetica", size=12)
toolbar = tk.Frame(root)
container = tk.Frame(root)
toolbar.pack(side="top", fill="x")
container.pack(side="top", fill="both", expand=True)
bigger = tk.Button(toolbar, text="Bigger", command=bigger)
smaller = tk.Button(toolbar, text="Smaller", command=smaller)
bigger.pack(side="left")
smaller.pack(side="left")
pixel = tk.PhotoImage(width=1, height=1)
for row in range(3):
container.grid_rowconfigure(row, weight=1)
for column in range(3):
container.grid_columnconfigure(column, weight=1)
button = tk.Button(container, font=font, text="x",
image=pixel, compound="center", width=20, height=20)
button.grid(row=row, column=column)
root.mainloop()
All of that being said, there is almost never a time when this is a good idea. If the user wants a larger font, the whole UI should adapt. Tkinter is really good at making that happen, to the point where it all mostly works by default.
Solution 3
I found solution of this problem. I was trying to solve a similar problem: I want to put image on label. I set the image size equal to label size. When I have been trying to put it with command label.config(image=img)
the label size grow. The image have the size I set to it, so it didn't cover label completely. I was using grid manager. All size were not entered in advanced but calculated by Tkinter. I was using grid_columnconfigure
and grid_rowconfigure
. The solution I found is to put this label with image (or button in Your case) to LabelFrame
and set grid_propagate
to False
.
Code example:
MyWindow = tk.Tk()
MyWindow.geometry("500x550")
#create LabelFrame (200x200)
label = tk.LabelFrame(MyWindow, width=200, height=200)
#grid manager to set label localization
labelk.grid(row=0, column=0)
#label row and column configure: first argument is col or row id
label.grid_rowconfigure(0, weight=1)
label.grid_columnconfigure(0, weight=1)
#cancel propagation
label.grid_propagate(False)
#Create button and set it localization. You can change it font without changing size of button, but if You set too big not whole will be visible
button = t.Button(label, text="Hello!", font=('Helvetica', '20'))
#Use sticky to button took up the whole label area
button.grid(row=0, column=0, sticky='nesw')
MyWindow.mainloop()
Result for font size 40 and 20:
Example for creating button with dynamic size by grid manager:
MyWindow = tk.Tk()
MyWindow.geometry("500x550")
#Divide frame on 3x3 regions
for col in range(3):
MyWindow.grid_columnconfigure(col, weight=1)
for row in range(3):
MyWindow.grid_rowconfigure(row, weight=1)
label = tk.LabelFrame(MyWindow)
#Put label in the middle
label.grid(row=1, column=1, sticky='nesw')
label.grid_propagate(False)
label.grid_rowconfigure(0, weight=1)
label.grid_columnconfigure(0, weight=1)
button = tk.Button(label, text="Hello!", font=('Helvetica', '30'))
button.grid(row=0, column=0, sticky='nesw')
MyWindow.mainloop()
It is late answer, but maybe it will help someone.
warspyking
Hi, I really enjoy programming on the site www.roblox.com although there are many 12- kids on there, it's a great place to develop games. I'm also trying to get used to JavaScript. I know a bit of Batch. I just joined this site in order to get some help, but maybe I'll eventually be good enough to help others too.
Updated on June 04, 2022Comments
-
warspyking almost 2 years
I am having trouble changing the font size of a button in Tkinter, when I attempt to do it the button also expands/contracts based on the size of the text. Is there a way I can alter the text size with the button's size anchored in place?
I ran across this while designing a tic-tac-toe application, however to save you the trouble, here is a very minimal example of the problem in practice:
import Tkinter as tk MyWindow = tk.Tk() MyWindow.geometry("500x550") button = tk.Button(MyWindow,text="Hello!",width=17,height=10,font=('Helvetica', '20')) button.grid(row=1, column=1) MyWindow.mainloop()
The most important part here is
font=('Helvetica', '15')
or more specifically, the number 15. If you change that number and run this again, not only will the text be bigger/smaller, but so will the button! How do I get around this?It's probably a really simple problem. I've just gotten started with Tkinter. Thanks in advance for any help I receive!
-
warspyking about 7 yearsYour class declaration and stuff is scaring me. I'm only starting out in both python and tkinter haha.
-
Novel about 7 yearsGUIs rely heavily on classes, as do many other things in python. Jump in.
-
Xiang over 3 yearsThis is so brilliant and easy to be understood! As a mark, this answer is on
python 2.x
, in order to test onpython 3.x
, please editTkinter
astkinter
in the first line, andimport tkFont
tofrom tkinter import font
in the second line, andtkFont.Font(
tofont.Font(
in the following, then you are all set! -
sodmzs1 about 3 yearsstackoverflow.com/q/67241484/14715170 Can you please help me for this ?