1

(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()
CyberTaco
  • 338
  • 1
  • 3
  • 14
  • You can get the screen height and width using the universal `winfo_screenheight()` and `winfo_screenwidth()` methods. Here's some [documentation](http://web.archive.org/web/20190222214221id_/http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html). – martineau Sep 04 '19 at 23:39
  • 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 Sep 05 '19 at 00:50
  • 2
    Try `window.state('zoomed')`. – acw1668 Sep 05 '19 at 02:21
  • Possible duplicate of [Python tk window get x, y, geometry/coordinates without top of window](https://stackoverflow.com/questions/13424598/python-tk-window-get-x-y-geometry-coordinates-without-top-of-window) – stovfl Sep 05 '19 at 09:08
  • @acw1668: Using `window.state('zoomed')` doesn't do anything. – martineau Sep 05 '19 at 18:39
  • Duplicate: Not quite a duplicate of that other question. That question was about getting the x & y of a window without it's decorations, and on top of that, the answer wasn't really spelled out or newbie-friendly, and was missing details. This question is about how to size a window into an exact space on screen, since tkinter's dimensions don't factor in the window decor. I think this question is the next evolutionary step after that question, now that I think about it. – CyberTaco Sep 05 '19 at 20:51

2 Answers2

0

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.

  • Screen size: Oh, no, that part I had - the code in the sample above gets the usable size of the screen (the height of the screen minus what the windows taskbar takes up, and the width of the screen), and that part works fine. What was screwing things up is that no matter what size you set your window height and width to, you'd get a larger window that you specify since the title bar and borders aren't factored in. You can say you want a 500x500 window, and the *inside* of the window will be that, but the whole window will be bigger. – CyberTaco Sep 05 '19 at 20:37
  • As for the optimizations: Whoa. I'm definitely not up to that level yet, but I'll be keeping this in mind when I get better. Thank you! :-) – CyberTaco Sep 05 '19 at 20:38
  • You can rid of the task bar if that's what you want. `window.overrideredirect(True)` will get rid of the task bar. You need to press alt+f4 to exit though. – Adam Rajczakowski Sep 06 '19 at 15:23
  • Well, no, that wasn't what I was looking for, but that's extremely interesting to know on it's own! I think that'll be handy sometime in the future; thank you! :-) – CyberTaco Sep 06 '19 at 17:24
0

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. :-)

CyberTaco
  • 338
  • 1
  • 3
  • 14