Tkinter – relation between font type and width

Question:

I apologize in advance if my question is a duplicate however I have not found an answer to this question.

I’m learning Tkinter and I’m struggling with understanding the relation between a label’s font type, it’s size and it’s width and the length of the string in it.

Specifically, what my problem is:

  • I have created a widget: a 800×640 canvas on which I want to place other
    widgets.
  • On this canvas I want to place a label with some text which has the following
    attributes: font: Helvetica, font size: 20, text = "main application". I want
    to place this label widget at the very most top left corner of the
    widget(meaning at point 0,0 with respect to the canvas). I want the label to
    be 200 in width meaning it’s background to take almost 1/3 of the canvas’s
    size(after I manage to do this I plan to add 2 more labels as well). I guess
    the height of the label is determined by the font size in this case 20. I
    placed the label at coordinate y=20 and this coordinate seems to be ok.

I did some googling and found out that the width parameter of the label widget is not the actual width but something related to the font and size of the label’s text: something like if I understood correctly: if the width is 6 than the label will be wide enough to contain 6 characters of, in my case verdana size 20. But I was not able to figure out what width and what x coordinate I should give my label so it starts at the x point of the canvas. Here is the code that I wrote:

from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
from tkinter import Menu

# Define the application class where we will implement our widgets
class Application(Frame):
    def __init__(self, master):
        super(Application, self).__init__(master)
        # CANVAS COLOUR DEFAULTS TO THE COLOUR OF THE WORKING WINDOW
        canvas = Canvas(master, width=800, height = 640, bg="gray") # IF YOU DO .PACK() HERE IT WILL RETURN NONE AND THEN YOU WILL HAVE PROBLEMS BECAUSE .PACK() RETURNS A 'NONE' TYPE OBJECT
        canvas.place(relx=0.5, rely=0.5, anchor=CENTER)

        # The 'menu' of the application. The selection labels
        main_application_label = Label(master, text="main_application", font=("Helvetica", 20))
        main_application_window = canvas.create_window(103,20, window=main_application_label)

main_application = Tk()

main_application.title("main_application")

app = Application(main_application)

app_width = 800
app_height = 640

screen_width = main_application.winfo_screenwidth()
screen_height = main_application.winfo_screenheight()

x_coord = (screen_width/2) - (app_width/2)
y_coord = (screen_height/2) - (app_height/2)

main_application.geometry("%dx%d+%d+%d" % (app_width, app_height, x_coord, y_coord))
main_application.mainloop()

I have managed to somehow get the label at around point 0,0(by giving more values till I got it right) but the actual width of the label is not 200 pixels(~1/3 of the canvas). Please help me understand what values to the width parameter I should give so that my label’s background is 1/3 of the canvas’s size and if possible explain the relation between character font and width parameter so I can do that for any widgets regardless of their text’s length. Thank you for reading my post!

Edit: What I wanted to do was to place 3 widgets(labels in this case but it doesn’t matter) on the canvas. I did not understand what the ‘anchor’ option does and that was confusing me because I was expecting the center of the widget to be placed at the given coordinates all times but as I was changing anchor the placement of the center of the widget was changing and that was confusing me. It’s all clear now thanks to @Bryan Oakley. Thanks.

Asked By: Cantaff0rd

||

Answers:

If you want the upper left corner of the text to be at (0,0), you don’t have to adjust the coordinates based on the width. You can use the anchor option when creating the canvas object:

main_application_window = canvas.create_window(0, 0, anchor="nw",
                                               window=main_application_label)

If you really need to compute the actual size of the string, you can create a Font object and then use the measure method to find the actual width of a string in the given font.

from tkinter.font import Font
font = Font(family="Helvetica", size=20)
string_width = font.measure("main_application")
string_height = font.metrics("linespace")

This gives you the size of the rendered string. If you’re using a label widget you’ll also need to take into account the amount of padding and borders that the widget uses.

When you create items on a canvas, you can specify the width and height. For example, this makes the widget 200 pixels wide:

main_application_window = canvas.create_window(0, 0, anchor="nw", width=200,
                                               window=main_application_label, width=400)
Answered By: Bryan Oakley
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.