How to make a window fullscreen in a secondary display with tkinter?
Asked Answered
D

7

21

I know how to make a window fullscreen in the "main" display, but even when moving my app's window to a secondary display connected to my PC, when I call:

self.master.attributes('-fullscreen', True)

to fullscreen that window, it does so in the "main" display and not in the secondary one (the app's window disappears from the secondary display and instantly appears in the "main" one, in fullscreen).

How can I make it fullscreen in the secondary display?

Denver answered 9/10, 2014 at 19:40 Comment(4)
Windows? or something else?Idaho
Just Windows... Tk() or Toplevel()Denver
Well, i guess my response was a bit unclear @TerryJanReedy. I want to fullscreen Tk() or Toplevel() windows, in Windows SO.Denver
Sorry, I don't have an answer.Idaho
S
7

This works on Windows 7: If the second screen width and height are the same as the first one, you can use win1 or win2 geometry in the following code depending on its relative position (leftof or rightof) to have a fullscreen window on a secondary display:

from tkinter import *

def create_win():
    def close():
        win1.destroy()
        win2.destroy()

    win1 = Toplevel()
    win1.geometry('%dx%d%+d+%d'%(sw, sh, -sw, 0))
    Button(win1, text="Exit1", command=close).pack()

    win2 = Toplevel()
    win2.geometry('%dx%d%+d+%d'%(sw, sh, sw, 0))
    Button(win2, text="Exit2", command=close).pack()

root = Tk()
sw, sh = root.winfo_screenwidth(), root.winfo_screenheight()
print(f"screen1:\nscreenwidth: {sw}\nscreenheight: {sh}")

w, h = 800, 600
a, b = (sw-w)/2, (sh-h)/2

Button(root, text="Exit", command=lambda r=root:r.destroy()).pack()
Button(root, text="Create win2", command=create_win).pack()

root.geometry('%sx%s+%s+%s'%(w, h, a, b))
root.mainloop()

Salad answered 24/8, 2015 at 22:50 Comment(3)
I've got a workaround but you deserve an "accepted" and a upvote for this, since it may be useful for someone. Thanks!Denver
And what is your workaround?Scratches
@Scratches Presumably something like root.overrideredirect(True); root.geometry("+0+-900"); root.state("zoomed") which works for me.Passim
S
3

Try:

from Tkinter import *

rot = Tk()


wth,hgh = rot.winfo_screenwidth(),rot.winfo_screenheight()
#take desktop width and hight (pixel)
_w,_h = 800,600 #root width and hight
a,b = (wth-_w)/2,(hgh-_h)/2 #Put root to center of display(Margin_left,Margin_top)



def spann():
    def _exit():
        da.destroy()

    da = Toplevel()
    da.geometry('%dx%d+%d+%d' % (wth, hgh,0, 0))

    Button(da,text="Exit",command=_exit).pack()
    da.overrideredirect(1)
    da.focus_set()#Restricted access main menu




Button(rot,text="Exit",command=lambda rot=rot : rot.destroy()).pack()


but = Button(rot,text="Show SUB",command=spann)
but.pack()


rot.geometry('%sx%s+%s+%s'%(_w,_h,a,b))
rot.mainloop()
""" Geometry pattern 'WxH+a+b'
        W = Width
        H = Height
        a = Margin_left+Margin_Top"""
Sufflate answered 22/8, 2015 at 13:31 Comment(0)
H
3

Super simple method working in 2021

This works even if both displays are different resolutions. Use geometry to offset the second display by the width of the first display. The format of the geometry string is <width>x<height>+xoffset+yoffset:

root = tkinter.Tk()

# specify resolutions of both windows
w0, h0 = 3840, 2160
w1, h1 = 1920, 1080

# set up a window for first display, if wanted  
win0 = tkinter.Toplevel()
win0.geometry(f"{w0}x{h0}+0+0")

# set up window for second display with fullscreen 
win1 = tkinter.Toplevel()
win1.geometry(f"{w1}x{h1}+{w0}+0") # <- this is the key, offset to the right by w0
win1.attributes("-fullscreen", True)

As long as you know the width of the first display, this will work fine. The X system TK runs on puts the second monitor to the right of the first one by default.

Hypercritical answered 8/4, 2021 at 18:37 Comment(2)
Forcing it over to the other window works, but setting the fullscreen attribute makes it full screen on the main monitor again.Dunkirk
Make sure you have offset it by the proper amount. I found that when I was off by even a few pixels, it would put it on the main display, but if the offset is just right it will work.Hypercritical
L
2

Windows, Python 3.8

In this solution, pressing F11 will make the window fullscreen on the current screen.

Note that self.root.state("zoomed") is Windows specific according to doc.

self.root.overrideredirect(True) is weird in Windows and may have unwanted side effects. For instance I've had issues related to changing screen configuration with this option active.

#!/usr/bin/env python3
import tkinter as tk


class Gui:
    fullScreen = False

    def __init__(self):
        self.root = tk.Tk()
        self.root.bind("<F11>", self.toggleFullScreen)
        self.root.bind("<Alt-Return>", self.toggleFullScreen)
        self.root.bind("<Control-w>", self.quit)
        self.root.mainloop()

    def toggleFullScreen(self, event):
        if self.fullScreen:
            self.deactivateFullscreen()
        else:
            self.activateFullscreen()

    def activateFullscreen(self):
        self.fullScreen = True

        # Store geometry for reset
        self.geometry = self.root.geometry()

        # Hides borders and make truly fullscreen
        self.root.overrideredirect(True)

        # Maximize window (Windows only). Optionally set screen geometry if you have it
        self.root.state("zoomed")

    def deactivateFullscreen(self):
        self.fullScreen = False
        self.root.state("normal")
        self.root.geometry(self.geometry)
        self.root.overrideredirect(False)

    def quit(self, event=None):
        print("quiting...", event)
        self.root.quit()


if __name__ == '__main__':
    Gui()
Lists answered 26/7, 2020 at 16:42 Comment(1)
This does not seem to work. The window gets the decorations removed and get the size of the screen, but it is not centered. The position of the fullscreen window will be the same as the starting smaller window (the left top will stay at the same coordinate).Fleetwood
T
0

I searched for a long time to achieve fullscreen on the subscreen, and finally found that overrideredirect(1)+ root.geometry to the location of the secondary screen can be achieved.(If this can not be achieved I will go to use PyQt5. :(

And even if the window is moved by root.geometry, the fullscreen of the root.wm_attributes('-fullscreen',True) method is still on the main screen。

from tkinter import *
import ctypes.wintypes
def get_monitors_info():
    """Obtain all monitors information and return information for the second monitor"""
    """Windows only - using user32 eliminates the need to install the pywin32 software package"""
    user32 = ctypes.windll.user32
    def _get_monitors_resolution():
        monitors = []
        monitor_enum_proc = ctypes.WINFUNCTYPE(
            ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(ctypes.wintypes.RECT), ctypes.c_double)
        # Callback function,to obtain information for each display
        def callback(hMonitor, hdcMonitor, lprcMonitor, dwData):
            monitors.append((lprcMonitor.contents.left, lprcMonitor.contents.top,
                             lprcMonitor.contents.right - lprcMonitor.contents.left,
                             lprcMonitor.contents.bottom - lprcMonitor.contents.top))
            return 1
        # Enumerate all Monitors
        user32.EnumDisplayMonitors(None, None, monitor_enum_proc(callback), 0)
        return monitors
    # All monitors information
    monitors = _get_monitors_resolution()
    return monitors

import tkinter as tk
from PIL import Image, ImageTk
import tkinter.font as tkFont
class MyApp:
    def __init__(self, master):
        self.master = master
        master.title("My App")
        monitors = get_monitors_info()
        if len(monitors) >= 2:
            x1=monitors[1][0]
            y1=monitors[1][1]
            w1=monitors[1][2]
            h1=monitors[1][3]
            print("%dx%d+%d+%d" % (w1, h1, x1, y1))
            "Can move the window via root.geometry, but it cannot be moved to full screen on the secondary monitor via root.wm_attributes('-fullscreen',True) either"
            "The fullscreen top-level window created with overrideredirect(1) can be fullscreen on the secondary screen after moving the position。"
            root.geometry("%dx%d+%d+%d" % (w1, h1, x1, y1))
            # root.wm_attributes('-fullscreen', True)
            root.overrideredirect(1)
            # root.attributes("-topmost", True)
        else:
            w1=monitors[0][2]
            h1 = monitors[0][3]
            root.geometry("%dx%d+%d+%d" % (w1, h1, 0, 0))
            root.overrideredirect(1)
        master.bind('<Double-Button-1>', self.toggle_fullscreen)
        master.bind("<F11>", self.toggle_fullscreen)
        master.bind('<Escape>', self.close)
    def toggle_fullscreen(self, event=None):
        overrideredirect_value = root.overrideredirect()
        if(overrideredirect_value):
            root.overrideredirect(0)
        else:
            root.overrideredirect(1)
    def close(self, event=None):
        # set the running flag to False to stop updating the image
        self.running = False
        # close the window
        self.master.destroy()
root = tk.Tk()
app = MyApp(root)
root.mainloop()

How do I get monitor resolution in Python?

Create a fullscreen app in the secondary screen using tkinter and python 3.7.2

Tinsley answered 26/4, 2023 at 20:28 Comment(0)
D
0

Ad gentletato answer:

Initially another window, covering the whole second display, appeared and I didn't know, that yet another "big one" was underneath the the first big one (after a while I got, that there supposed to be three: root, win1, win2).

After a while I got a version of the code working properly, with both of my displays.

Changes:

  1. root window moved to "the first display", (w, h, 100, 100), i.e. left upper corner,
  2. width for both "the big windows" was divided by 2 (resolution of either of my displays was 2560x1140),
  3. The location of the big windows was changed: the first one to 0, 0, the second one to sw/2, 0,
  4. Minor changes, .format method was used.

The code:

from tkinter import *


def create_win():
    
    def close():
        win1.destroy()
        win2.destroy()

win1 = Toplevel()
win1.title("win1")
# perhaps the formatting is an overkill,
# ('{}x{}+{}+{}'.format(sw//2, sh, 0, 0) should suffice):
win1_geometry = '{}x{}+{}+{}'.format(*[int(x) for x in (sw/2, sh, 0, 0)])
win1.geometry(win1_geometry)
Button(win1, text="Exit1", command=close).pack()

win2 = Toplevel()
win2.title("win2")
win2Geometry = '{}x{}+{}+{}'.format(*[int(x) for x in (sw/2, sh, sw/2, 0)])
print(f"{win2Geometry = }")
win2.geometry(win2Geometry)
Button(win2, text="Exit2", command=close).pack()


root = Tk()
sw, sh = root.winfo_screenwidth(), root.winfo_screenheight()
print(f"screen1:\nscreenwidth: {sw}\nscreenheight: {sh}")

w, h = 800, 600
a, b = (sw-w)/2, (sh-h)/2

Button(root, text="Exit", command=lambda r=root:r.destroy()).pack()
Button(root, text="Create win2", command=create_win).pack()

root.geometry('{}x{}+{}+{}'.format(*[int(x) for x in (w, h, 100, 100)]))
root.mainloop()
Dosh answered 27/11, 2023 at 18:19 Comment(0)
P
0

This works for me with an external display above my main display. You can use Alt+F4 to close the Tk window in Windows:

import tkinter
root = tkinter.Tk()
root.overrideredirect(True)  # Remove window borders.
root.geometry("+0+-900")  # Move window to other display, adjust if needed.
root.state("zoomed")  # Maximize borderless window.
root.mainloop()  # Render Tk window.
Passim answered 23/3 at 23:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.