2

Consider:

#!/usr/bin/python

from Tkinter import *

root=Tk()
root.withdraw()

top=Toplevel()
top.title("Some long title")
label = Label(top, text ="short", font=('Times', 18))
label.pack()

root.mainloop()

The resulting Toplevel window is large just enough to hold the contents. However, the title cannot be seen. How do I make the window resize itself to show both the contents and the title?

AlwaysLearning
  • 7,257
  • 4
  • 33
  • 68

2 Answers2

0

You can't do what you want. Tkinter has no access to information about the titlebar.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
0

After some digging and testing I think I found something you can use. We need to use the import for tkFont and use actual() to get the font information.

Try the following:

from tkinter import *
import tkinter.font as tkFont

# imports for python 2
# from Tkinter import *
# import tkFont

root=Tk()
root.withdraw()

top=Toplevel()

label_not_settings = Label(top, text ="Some long title")
label_not_settings.grid(row = 0, column = 0, sticky = 'w')

label_arial_12 = Label(top, text ="Some long title", font = ('Arial', 12))
label_arial_12.grid(row = 1, column = 0, sticky = 'w')

label = Label(top, text ="Some long title", font=('Times', 18))
label.grid(row = 2, column = 0, sticky = 'w')


empty_font = tkFont.Font()
label_not_settings_font = tkFont.Font(font = label_not_settings['font'])
label_arial_12_font = tkFont.Font(font = label_arial_12['font'])
toplevel_font = tkFont.Font(top.title("Some long title")) # no error comes from this line thought I don't think its actually working as intended.
label_font = tkFont.Font(font = label['font'])

print('# Results of priting with .actual() "empty_font = tkFont.Font()"')
print(empty_font.actual())
print("")
print("# Results of priting with .actual() on {}".format("label_not_settings_font"))
print(label_not_settings_font.actual())
print("")
print("# Results of priting with .actual() on {}".format("label_arial_12_font"))
print(label_arial_12_font.actual())
print("")
print("# Results of priting with .actual() on {}".format("toplevel_font"))
print(toplevel_font.actual())
print("")
print("# Results of priting with .actual() on {}".format("label_font"))
print (label_font.actual())

root.mainloop()

for me this resulted in:

# Results of priting with .actual() "empty_font = tkFont.Font()"
{'family': 'Arial', 'size': 12, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}

# Results of priting with .actual() on label_not_settings_font
{'family': 'Segoe UI', 'size': 9, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}

# Results of priting with .actual() on label_arial_12_font
{'family': 'Arial', 'size': 12, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}

# Results of priting with .actual() on toplevel_font
{'family': 'Arial', 'size': 12, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}

# Results of priting with .actual() on label_font
{'family': 'Times New Roman', 'size': 18, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}

It does appear to produce the font information you need. Though I am not 100% sure it is working as intended when calling toplevel_font.actual() it produces the same result as calling on an empty variable (I imaging its just stating the default font but I am not sure). Also if I create a label with text but no font configs then it produces a different font.actual() result.

Update:

Also I have looked into the issue of creating your own title bar with the functionality of the title bar. The issues I have run into so far is the window moves over so the top left corner of the title bar is at the mouse point when dragging the window around, the loss of auto resize function when dragging the window to a side of the monitor and not being able to manually resize the window.

I would imaging it is possible to build a fully functional title bar and I will work on it as I am interested to see if I can make one. But for now here is some information to illustrate the basics of creating ones own title bar.

This bit of code comes from this post: Can I change the title bar in Tkinter?

I have made some small changes but it is basically the same.

from tkinter import *

root = Tk()

def move_window(event):
    root.geometry('+{0}+{1}'.format(event.x_root, event.y_root))

root.overrideredirect(True) # turns off title bar, geometry
root.geometry('200x100') # set new geometry

# make a frame for the title bar
title_bar = Frame(root, bg = 'white', relief = FLAT, bd = 2)

# put a close button on the title bar
close_button = Button(title_bar, text = 'X', relief = FLAT, command = root.destroy)

# a canvas for the main area of the window
window = Canvas(root, bg='black')

# pack the widgets
title_bar.pack(expand = 1, fill = X)
close_button.pack(side = RIGHT)
window.pack(expand = 1, fill = BOTH)
# bind title bar motion to the move window function
title_bar.bind('<B1-Motion>', move_window)

root.mainloop()

Edit:

All this being said I would probably just test on each of the major operating systems and deiced on a good root.geometry() or root.minsize() that will show the text in full of the title. This might not be an elegant solution like using code to calculate text size and applying that size to the windows opening size but it should do the trick.

Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • In your first example, there's no guarantee that the font used by a label is the same font used by the system in window titlebars. Also, this code makes no sense: `tkFont.Font(top.title("Some long title"))`. `top.title(...)` just returns an empty string, which causes `tkFont.Font()` to simply return the default font. – Bryan Oakley Jun 14 '17 at 14:32
  • @Bryan Oakley: I was wondering about `top.title(...)` as it did not throw any kind of error. That is why I wrote `Though I am not 100% sure it is working as intended when calling toplevel_font.actual()`. Also I have updated my answer with some different results. – Mike - SMT Jun 14 '17 at 14:38