1
votes

(Environment: Windows, Python 3)

My problem is that using .geometry to set a height & width sets the height & width of the space inside the window - the title bar and window border make it larger. Below is my code so far. As you'll see, even though I have it create a window that's the exact size of the available screen area, the window ends up being too big because the title bar and borders aren't accounted for when setting the size.

See that "what needs to change here" part? What do those two statements need to be changed to or replaced with, that's simple? (If you have it right, the window should fit exactly in the available space on your desktop, with title bar and borders clearly visible.)

Please keep it simple - I'm still new to all of this. :-)

#Important variables:
#screenAvailableWidth, screenAvailableHeight: Height & width of
#                                              screen without
#                                              taskbar
#windowWidth, windowHeight: Height & width of new window to create
#window: Object of class Tk() from tkinter.

#Get screen height and width WITHOUT including the taskbar.
#This part works fine - I've tested the result and it's good.
from win32api import GetMonitorInfo, MonitorFromPoint
monitorInfo = GetMonitorInfo(MonitorFromPoint((0,0)))
workArea = monitorInfo.get("Work")
screenAvailableWidth = workArea[2]
screenAvailableHeight = workArea[3]

#Create a tkinter window
from tkinter import Tk 
window = Tk()

#Set new window height & width
#--------------------------------------------
#----- HERE. What needs to change here? -----
#--------------------------------------------
windowWidth = screenAvailableWidth
windowHeight = screenAvailableHeight
#--------------------------------------------

#Show debug info
print("")
print("screenAvailableWidth:",screenAvailableWidth,
      " screenAvailableHeight:",screenAvailableHeight)
print("windowWidth:\t",windowWidth," windowHeight:\t",windowHeight)

#Set the new window to upper left corner and height &
# width of screen
window.geometry("{}x{}+0+0".format(windowWidth,windowHeight))

#Show the window
window.mainloop()
2
You can get the screen height and width using the universal winfo_screenheight() and winfo_screenwidth() methods. Here's some documentation. - martineau
Those, I have, that isn't a problem. The problem is that if I set a window size to that, the actual size I get is that plus the size of the title bar and border. (AKA - the window is too big.) - CyberTaco
Try window.state('zoomed'). - acw1668
@acw1668: Using window.state('zoomed') doesn't do anything. - martineau

2 Answers

0
votes

I GOT IT! The trick is that as long as the window's visible (even if it's somewhere offscreen), you can do this:

titlebarHeight = window.winfo_rooty() - window.winfo_y()
borderSize= window.winfo_rootx() - window.winfo_x()

And once you have those, you can adjust your desired window width and height to correct for the title bar and borders like this:

WindowWidth = WindowWidth - (borderSize * 2)
WindowHeight = (WindowHeight - titlebarHeight) - borderSize

So, the code that ended up working in the end is this (which is complete - copy and paste this into your editor of choice and it should run as-is):

#Get screen height and width WITHOUT including the taskbar.
#This part works fine - I've tested the result and it's good.
from win32api import GetMonitorInfo, MonitorFromPoint
monitorInfo = GetMonitorInfo(MonitorFromPoint((0,0)))
workArea = monitorInfo.get("Work")
screenAvailableWidth = workArea[2]
screenAvailableHeight = workArea[3]

#Create a tkinter window
from tkinter import Tk 
window = Tk()

#Set new window height & width
#--------------------------------------------
#-----   HERE. This is what changed:    -----
#--------------------------------------------
#Make window visible so we can get some geometry
window.update_idletasks()
#Calculate title bar and border size
titlebarHeight = window.winfo_rooty() - window.winfo_y()
borderSize= window.winfo_rootx() - window.winfo_x()

#Start with full available screen
windowWidth = screenAvailableWidth
windowHeight = screenAvailableHeight

#Adjust for title bar and borders
windowWidth = windowWidth - (borderSize * 2 )
windowHeight = (windowHeight - titlebarHeight) - borderSize
#--------------------------------------------

#Show debug info
print("")
print("screenAvailableWidth:",screenAvailableWidth,
      " screenAvailableHeight:",screenAvailableHeight)
print("windowWidth:\t",windowWidth," windowHeight:\t",windowHeight)

#Set the new window to upper left corner and height &
# width of screen (after adjustment)
window.geometry("{}x{}+0+0".format(windowWidth,windowHeight))

#Show the window
window.mainloop()

(The breakthrough was examining all the properties mentioned in the suspected duplicate question (and it's comments and replies) here: tkinter window get x, y, geometry/coordinates without top of window That question didn't really put the pieces together in a newbie-friendly way, nor did it have any usable sample code, so hopefully this will be of use to someone else in the future.)

To everyone who commented and offered solutions for me, thank you! I really appreciate you taking the time to do so. :-)

0
votes

Instead of using monitorInfo you can use winfo_screedwidth() and winfo_screenheight().

This is how to do it:

windowWidth = window.winfo_screenwidth
windowHeight = window.winfo_screenheight

window.geometry("%sx%s" %(screenWidth, screenHeight)

You can use window.overrideredirect(True) to get rid of the task bar. It will also get rid of the bar at the top, so you will have to use alt+f4 to exit out of the window.

Also, these options are optional but will certainly make your code more clear and efficient by getting rid of possible errors which may occur when doing certain tasks with the code.

--You can stop reading if you want to--

Instead of from tkinter import Tk use import tkinter as tk. This means you can write tk.widget and not having to write out every widget you use. Also, if you use from tkinter import * you can use import tkinter as tk instead as it groups all attributes into tk. It will certainly clean up the attributes, and you will not having them together with all of the built in attributes

Also, get all of your widgets into a class. You can do this like so:

class Name(tk.Frame):

Inside it you need to write the __init__ function:

def __init__(self, master, **kwargs): #Feel free to add any extra parameters

Inside the __init__ function you write:

super().__init__(master, **kwargs)

The class makes your code neat and tidy while the __init__ and super() are needed for whenever you make a function.

Also, you can use the __name__ == "__main__" if condition to stop the code from running when importing it to another script.

This is how to do this:

def func_name():
    root = tk.Tk()
    #Add any root titles, geometry or any other configurations here
    app = Window(root) #Instead of Window, replace it with your class name
    app.pack(fill=tk.BOTH, expand=True)
    #Add any app configurations here
    root.mainloop()

if __name__ == "__main__":
    func_name()

All these features, you can include to make your code neater.