Tkinter -- how to horizontally center canvas text?

linus72982 picture linus72982 · Feb 26, 2015 · Viewed 9.3k times · Source

I'm working on a function in a UI class that is a config window, it displays the logo of the program and has an updating text at the bottom telling you what it's loading, etc. This is what I have so far:

    self.window = "config"
    self.windowWidth = 340
    self.windowHeight = 270
    infoText = "Configuring Kh..."
    self.root = tk.Tk()
    self.root.geometry("%dx%d+400+400" % (self.windowWidth, self.windowHeight))
    self.root.title("Kh Control v1.1 starting...")
    logo = tk.PhotoImage(file="KhLogo.gif")
    mainPanel = tk.Canvas(self.root, width=self.windowWidth, height=self.windowHeight)
    mainPanel.image = logo
    mainPanel.pack()
    mainPanel.create_image(0, 0, image=logo, anchor="nw")
    mainPanel.create_text(0,200, text=infoText, anchor="nw", fill="yellow")
    return

I'd like the text in infoText to be centered horizontally and offset vertically about 200px down. The vertical offset works fine, but I can't figure out how to center the text horizontally.

I started by trying the age old ((width / 2) - (str length / 2)) but then realized that each letter isn't 1px. And anchor = "center" seems to only put half the text off the left side of the screen.

I'm very new to Python (only a few days now) so if I'm missing something obvious, that's why.

EDIT: and in case it wasn't obvious, this text will change so I can't just make an absolute decision on the offsets, it has to change with the text

Answer

linus72982 picture linus72982 · Feb 27, 2015

I figured it out after scrounging through the canvas reference.

There is a method for a canvas called bbox that returns a tuple containing (x1, y1, x2, y2) of the area an item takes up. I got those coords, drew up a function to find the px length of it, divided it by 2 and subtracted it from the window width. Then I used canvas.move to change the x offset using the number the function returned.

    def findXCenter(self, canvas, item):
      coords = canvas.bbox(item)
      xOffset = (self.windowWidth / 2) - ((coords[2] - coords[0]) / 2)
      return xOffset

The main part is here:

    textID = mainPanel.create_text(0,0, text=infoText, anchor="nw", fill="yellow")
    xOffset = self.findXCenter(mainPanel, textID)
    mainPanel.move(textID, xOffset, 0)

Hopefully my hours of searching for this answer will help someone later on.