Jak wyśrodkować okno na ekranie w Tkinter?
Próbuję wyśrodkować okno tkinter. Wiem, że mogę programowo uzyskać rozmiar okna i rozmiar ekranu i użyć go do ustawienia geometrii, ale zastanawiam się, czy nie ma prostszego sposobu na wyśrodkowanie okna na ekranie.
7 answers
Możesz spróbować użyć metod winfo_screenwidth
i winfo_screenheight
, które zwracają odpowiednio szerokość i wysokość (w pikselach) instancji Tk
(okna), a przy pomocy podstawowej matematyki możesz wyśrodkować okno:
import tkinter as tk
from PyQt4 import QtGui # or PySide
def center(toplevel):
toplevel.update_idletasks()
# Tkinter way to find the screen resolution
# screen_width = toplevel.winfo_screenwidth()
# screen_height = toplevel.winfo_screenheight()
# PyQt way to find the screen resolution
app = QtGui.QApplication([])
screen_width = app.desktop().screenGeometry().width()
screen_height = app.desktop().screenGeometry().height()
size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
x = screen_width/2 - size[0]/2
y = screen_height/2 - size[1]/2
toplevel.geometry("+%d+%d" % (x, y))
toplevel.title("Centered!")
if __name__ == '__main__':
root = tk.Tk()
root.title("Not centered")
win = tk.Toplevel(root)
center(win)
root.mainloop()
Wywołuję metodę update_idletasks
Przed pobraniem szerokości i wysokości okna, aby upewnić się, że zwracane wartości są dokładne.
Tkinter nie widzi, czy istnieją 2 lub więcej monitorów rozszerzonych poziomo lub pionowo. Więc dostaniesz całość rozdzielczość wszystkich ekranów razem, a twoje okno skończy gdzieś pośrodku ekranów.
PyQt z drugiej strony również nie widzi środowiska multi-monitorów, ale otrzyma tylko rozdzielczość lewego górnego monitora (wyobraź sobie 4 monitory, 2 w górę i 2 w dół tworząc kwadrat). Tak więc wykonuje pracę, umieszczając okno na środku ekranu. Jeśli nie chcesz używać obu, PyQt i Tkinter, może lepiej byłoby wybrać PyQt od początku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-26 10:01:28
[19]} ogólne podejście do centrowania okna polega na obliczeniu odpowiednich współrzędnych ekranu dla lewego górnego piksela okna:
x = (screen_width / 2) - (window_width / 2)
y = (screen_height / 2) - (window_height / 2)
Jest to jednak Nie wystarczające do dokładnego centrowania okna tkinter (przynajmniej w Windows 7); ponieważ szerokość i wysokość okna zwracane przez dowolna metoda nie będzie zawierać zewnętrznej ramki z przyciskami title i min / max / close. Nie będzie również zawierać paska menu (z Plik, Edycja itp.). Na szczęście istnieje sposób na znalezienie ich wymiarów.
Oto najbardziej podstawowa funkcja, która nie bierze pod uwagę powyższego zagadnienia:
def center(win):
win.update_idletasks()
width = win.winfo_width()
height = win.winfo_height()
x = (win.winfo_screenwidth() // 2) - (width // 2)
y = (win.winfo_screenheight() // 2) - (height // 2)
win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
Alternatywy: winfo_reqwidth()
, winfo_reqheight()
Po pierwsze, i przede wszystkim, chcemy wywołać okno update_idletasks()
metoda
bezpośrednio przed pobraniem dowolnej geometrii, aby upewnić się, że zwracane wartości są dokładne.
Ważne jest, aby zrozumieć struny geometrii używane z geometry()
metoda.
Pierwsza połowa to szerokość i wysokość okna z wyłączeniem ramy zewnętrznej,
a druga połowa to współrzędne X i y klatki zewnętrznej.
Istnieją cztery metody, które pozwolą nam określić wymiary zewnętrznej ramki.winfo_rootx()
da nam współrzędną X w lewym górnym rogu okna, z wyłączeniem zewnętrznej ramki.winfo_x()
da nam zewnętrzną ramkę w lewym górnym rogu x koordynować.
Ich różnica polega na szerokości zewnętrznej ramy.
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = win.winfo_width() + (2*frm_width)
Różnica między winfo_rooty()
i winfo_y()
będzie wysokością naszego paska tytułu / paska menu.
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = win.winfo_height() + (titlebar_height + frm_width)
Oto pełna funkcja, w roboczym przykładzie:
import tkinter # Python 3
def center(win):
"""
centers a tkinter window
:param win: the root or Toplevel window to center
"""
win.update_idletasks()
width = win.winfo_width()
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = width + 2 * frm_width
height = win.winfo_height()
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = height + titlebar_height + frm_width
x = win.winfo_screenwidth() // 2 - win_width // 2
y = win.winfo_screenheight() // 2 - win_height // 2
win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
win.deiconify()
if __name__ == '__main__':
root = tkinter.Tk()
root.attributes('-alpha', 0.0)
menubar = tkinter.Menu(root)
filemenu = tkinter.Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=root.destroy)
menubar.add_cascade(label="File", menu=filemenu)
root.config(menu=menubar)
frm = tkinter.Frame(root, bd=4, relief='raised')
frm.pack(fill='x')
lab = tkinter.Label(frm, text='Hello World!', bd=4, relief='sunken')
lab.pack(ipadx=4, padx=4, ipady=4, pady=4, fill='both')
center(root)
root.attributes('-alpha', 1.0)
root.mainloop()
Jednym ze sposobów zapobiegania przesuwaniu się okna po ekranie jest użycie
.attributes('-alpha', 0.0)
Aby okno było całkowicie przezroczyste, a następnie ustawić je na 1.0
po wyśrodkowaniu okna. Używając withdraw()
lub iconify()
, a następnie deiconify()
wydaje się, że nie działa dobrze w tym celu w systemie Windows 7. Zauważ, że używam deiconify()
jako sztuczki, aby aktywować okno.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-27 02:06:19
Tk dostarcza funkcję pomocniczą, która może to zrobić jako tk::PlaceWindow
, ale nie wierzę, że została ona ujawniona jako metoda zawinięta w Tkinter. Wyśrodkowałbyś widżet używając następującego:
from tkinter import *
app = Tk()
app.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))
app.mainloop()
Ta funkcja powinna poprawnie obsługiwać wiele wyświetlaczy. Posiada również opcje wyśrodkowania nad innym widżetem lub względem wskaźnika (używanego do umieszczania wyskakujących menu), aby nie spaść z ekranu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 01:31:00
Znalazłem rozwiązanie tego samego pytania na tej stronie
from tkinter import Tk
from tkinter.ttk import Label
root = Tk()
Label(root, text="Hello world").pack()
# Apparently a common hack to get the window size. Temporarily hide the
# window to avoid update_idletasks() drawing the window in the wrong
# position.
root.withdraw()
root.update_idletasks() # Update "requested size" from geometry manager
x = (root.winfo_screenwidth() - root.winfo_reqwidth()) / 2
y = (root.winfo_screenheight() - root.winfo_reqheight()) / 2
root.geometry("+%d+%d" % (x, y))
# This seems to draw the window frame immediately, so only call deiconify()
# after setting correct window position
root.deiconify()
root.mainloop()
Jasne, zmieniłem go odpowiednio do moich celów, działa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-20 17:29:09
Używam opcji frame i expand. Bardzo proste. Chcę kilka przycisków na środku ekranu. Zmień rozmiar okna i przycisk pozostań w środku. To moje rozwiązanie.
frame = Frame(parent_window)
Button(frame, text='button1', command=command_1).pack(fill=X)
Button(frame, text='button2', command=command_2).pack(fill=X)
Button(frame, text='button3', command=command_3).pack(fill=X)
frame.pack(anchor=CENTER, expand=1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-10 09:01:53
Użycie:
import tkinter as tk
if __name__ == '__main__':
root = tk.Tk()
root.title('Centered!')
w = 800
h = 650
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root.mainloop()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-21 11:01:16
Ta odpowiedź jest lepsza dla zrozumienia początkującego
#import tkinter as tk
win = tk.Tk() # Creating instance of Tk class
win.title("Centering windows")
win.resizable(False, False) # This code helps to disable windows from resizing
window_height = 500
window_width = 900
screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()
x_cordinate = int((screen_width/2) - (window_width/2))
y_cordinate = int((screen_height/2) - (window_height/2))
win.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
win.mainloop()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-30 05:33:19