I'm fairly new to Python and am just discovering GUI programming with Tkinter.
My goal is to have a window (root) be resizable only in height and not in width. I looked it up on SO and google and found this: root.resizable(width=False, height=True)
It works fine on its own, even when I add widgets to the root, but as soon as I add a menu to the root, the root window becomes resizable in width, even if I reconfigure it with root.resizable(width=False, height=True)
after adding the menu.
Edit 1: I should mention that setting both parameters to False
makes the window non-resizable, as it should be. So it partially works.
Here's a sample code to help you test the problem (simply maximize the Tk window to see how both behave):
This code works as intended:
from Tkinter import Tk, Menu
root = Tk()
root.resizable(width=False, height=True)
root.mainloop()
This code doesn't:
from Tkinter import Tk, Menu
root = Tk()
root.resizable(width=False, height=True) # moving this just before the mainloop() call doesn't change a thing
menubar=Menu(root)
root.config(menu=menubar)
root.mainloop()
I kept the examples as simple as possible but the behavior of the first code doesn't change if I add widgets to root. The behavior of the second code doesn't change either if I add items to the menu, and/or widgets to root.
I'm running Python 2.7 on IDLE, on Windows Vista 32bit. I'm using Tkinter version 8.5
Edit 2: Thanks to the help of Lafexlos and Marcin, it has been made fairly obvious that Vista is somewhat responsible for the problem (or, at least, the way Tkinter operates with Vista). I have therefore reformulated the question and added a Vista tag to help future SO users.
Thanks for any help in understanding why the second piece of code doesn't work and what I should do to make it work.
PS: let me know if I can provide any more info to help you help me ;-)
It took some work, but I finally found a solution (though the cause itself and the reason it only seems to happen on Vista are still unknown factors).
Basically once all my widgets have been gridded or packed or placed, I query the widow's current width (don't forget to call update_idletasks()
beforehand) and save it for later (this will be my max_width as I don't want the window to be larger or thinner than my largest row of widgets). Then by setting the window's state to 'zoomed', I can query the max_height of the window (i.e. the window's height now that it is maximized). Then I force the window to remain within these limits by calling wm_minsize
and wm_maxsize
, passing the saved max_width and max_height as parameters (you should set a lower value for the min_height in order to have a little bit of freedom when the window is in 'normal' state). You could finish by resetting the window's state to normal before calling mainloop()
if you don't want to open your window maximized.
The window should now only be resizable in height, whether by expanding it's top or bottom side or by clicking on the maximize button. Hope this helps other Vista users.
from Tkinter import Tk, Menu, Frame
class MyTkWindow(Tk):
def __init__(self):
Tk.__init__(self)
# replace these three lines to create your own menu
self.menubar = Menu(self)
self.menubar.add_command(label='Hello')
self.config(menu=self.menubar)
# replace these two lines to embed your own widgets in the window
self.frame = Frame(self, width=500)
self.frame.grid(sticky='news')
# this block makes the window not resizable in width,
# only in height (and within a certain range only)
self.update_idletasks()
self.max_w = self.winfo_width()
self.state('zoomed')
self.update_idletasks()
self.max_h = self.winfo_height()
self.wm_minsize(width=self.max_w, height=self.max_h-100)
self.wm_maxsize(width=self.max_w, height=self.max_h)
t = MyTkWindow()
t.mainloop()