Need help Dynamically resizing my text to fit in the tkinter canvas

Viewed 775

I was working on a small python script lately when I came across this problem. I tried to create a canvas in a strip shape and write text into it expecting that the text would auto adjust itself to the boundaries of canvas(similar to how a text box works in word processing software). But the text is apparently going out of boundaries.

ScreenShot Display of text going out of canvas boundary

Code

from tkinter import *
top = Tk()  
top.geometry("130x370")
c = Canvas(top,bg = "pink",height = "370")
c.create_text(30,30,fill="darkblue",font="Times 20 italic bold",text="Hey There!")
c.pack()
top.mainloop() 
1 Answers

Firstly, the .create_text() method of the Canvas has a width option which sets the maximum width of the text beyond which it is wrapped. To get a dynamical effect when resizing the window, this width option can be changed in a function bound to the <Configure> event (the resize() function in the example below).

Secondly, to check that the text fits vertically in the canvas, I use the .bbox(item_id) method of the Canvas to get the coordinates of the bounding box of the text. Then, I decrement the fontsize as long as the bottom of the text is lower than the bottom of the canvas.

Here is the example:

import tkinter as tk
top = tk.Tk()
top.geometry("130x370")

def resize(event):
    font = "Times %i italic bold"
    fontsize = 20
    x0 = c.bbox(text_id)[0] # x-coordinate of the left side of the text
    c.itemconfigure(text_id, width=c.winfo_width() - x0, font=font % fontsize)
    # shrink to fit
    height = c.winfo_height() # canvas height
    y1 = c.bbox(text_id)[3] # y-coordinate of the bottom of the text
    while y1 > height and fontsize > 1:
        fontsize -= 1
        c.itemconfigure(text_id, font=font % fontsize)
        y1 = c.bbox(text_id)[3]

c = tk.Canvas(top, bg="pink", height="370")
text_id = c.create_text(30, 30, anchor="nw", fill="darkblue", font="Times 20 italic bold", text="Hey There!")
c.pack(fill="both", expand=True)
c.bind("<Configure>", resize)

top.mainloop()

Also note that I set the anchor of the text to north west in .create_text() so that (30, 30) are the coordinates of the top-left corner of the text and not of the center to ensure that the start of the text is visible.

Related