python 3.6 center tkinter window [дубликат]

Если вы столкнулись с этой проблемой при использовании Maven , вы можете скомпилировать свой код с помощью подключаемого модуля Maven Compiler .

 
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.1
                
                    1.6
                    1.6
                
            
       .....

UPDATE: установите source и target на 1.8, если вы используете JDK 8.

40
задан nbro 4 May 2015 в 02:07
поделиться

7 ответов

Вы можете попробовать использовать методы winfo_screenwidth и winfo_screenheight, которые возвращают соответственно ширину и высоту (в пикселях) вашего экземпляра Tk (окно), а с помощью некоторой базовой математики вы можете центрировать свое окно:

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()

Я вызываю метод update_idletasks, прежде чем извлекать ширину и высоту окна, чтобы гарантировать верность возвращаемых значений.

Tkinter не видит, есть ли два или более монитора расширенного горизонтального или вертикального. Таким образом, вы получите общее разрешение всех экранов вместе, и ваше окно окажется где-то посередине экранов.

PyQt , с другой стороны, также не видит среду с несколькими мониторами, но она получит только разрешение монитора Top-Left (Imagine 4 monitor, 2 up и 2 вниз, делая квадрат). Таким образом, это делает работу, помещая окно в центр этого экрана. Если вы не хотите использовать оба параметра, PyQt и Tkinter , возможно, лучше начать с PyQt с начала.

59
ответ дан Aran-Fey 22 August 2018 в 01:34
поделиться
  • 1
    "не самый мощный" немного субъективен. Он имеет столько же «мощности», как и другие наборы инструментов (в зависимости от вашего определения «мощности»), он просто не делает столько рук. Это разница между строительством дома с предварительно изготовленными стенами (некоторые другие комплекты инструментов) или строительство его из кучи пиломатериалов (Tk). Вы можете в значительной степени сделать что-нибудь в Tkinter, что вы можете сделать в других инструментариях, вам просто нужно немного поработать. – Bryan Oakley 28 July 2010 в 16:48
  • 2
    Кажется, чтобы подтвердить мои подозрения, спасибо! – psicopoo 28 July 2010 в 16:54
  • 3
    @ Брайан - это то, что я имею в виду под властью. Конечно, вы можете обойти Соединенные Штаты в Юго (возможно) и Ferrari, но один из них может доставить вас туда намного быстрее. Конечно, они оба имеют возможность взаимодействовать с пользователем определенными способами, но у Tkinter нет возможности разрешить писать более крупные программы в меньших количествах (и с меньшими усилиями). Конечно, более мелкие программы на самом деле проще в Tkinter, потому что вам не нужно беспокоиться о тех же накладных расходах для виджетов, что и другие инструментальные средства, и это то, что мне нравится Tkinter для написания небольших программ. @pscopoo, добро пожаловать! – Wayne Werner 28 July 2010 в 17:56
  • 4
    В основном работает, но вам нужен вызов update_idletasks (). – Charles Merriam 6 April 2014 в 05:54
  • 5
    Heads up: я отредактировал ваш ответ, чтобы он больше не устанавливал окно в фиксированный размер. Исходный код не позволял изменять размер окна при добавлении / удалении / изменении виджетов. – Aran-Fey 26 July 2018 в 10:02

Я использую функцию frame и expand. Очень просто. Я хочу несколько кнопок в середине экрана. Окно изменения размера и кнопки остаются посередине. Это мое решение.

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)
1
ответ дан easyScript 22 August 2018 в 01:34
поделиться

Общий подход к центрированию окна заключается в вычислении соответствующих координат экрана для верхнего левого пикселя окна:

x = (screen_width / 2) - (window_width / 2)  
y = (screen_height / 2) - (window_height / 2)

Однако это не , достаточное для точно центрирование окна tkinter (по крайней мере, на Windows 7); потому что ширина и высота окна, возвращаемые любым методом , не будут включать самый внешний кадр с кнопками заголовка и min / max / close. Он также не будет включать строку меню (с файлом, редактированием и т. Д.). К счастью, есть способ найти их размеры.

Вот самая основная функция, которая не учитывает вышеупомянутую проблему:

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

Альтернативы: winfo_reqwidth() , winfo_reqheight()

Прежде всего, мы хотим вызвать метод update_idletasks() в окне окна перед тем, как геометрии, чтобы гарантировать, что возвращаемые значения точны.

Важно понимать строки геометрии , используемые с методом geometry() . Первая половина - ширина и высота окна, исключая внешний кадр, а вторая половина - верхние левые координаты x и y.

Существует четыре метода, которые позволят нам определить внешний размеры рамки. winfo_rootx() даст нам координату верхнего левого окна окна, исключая внешний кадр. winfo_x() даст нам верхнюю левую координату x. Их разница - ширина внешнего кадра.

frm_width = win.winfo_rootx() - win.winfo_x()
win_width = win.winfo_width() + (2*frm_width)

Разница между winfo_rooty() и winfo_y() будет нашей высотой заголовка / строки меню.

titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = win.winfo_height() + (titlebar_height + frm_width)

Вот полная функция в рабочем примере:

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()

Один из способов предотвратить просмотр окна по экрану - использовать .attributes('-alpha', 0.0) , чтобы сделать окно полностью прозрачный, а затем установите 1.0 после того, как окно будет центрировано. Использование withdraw() или iconify() позже, а затем deiconify(), похоже, не работает, для этой цели, в Windows 7. Обратите внимание, что я использую deiconify() в качестве трюка для активации окна.

30
ответ дан Honest Abe 22 August 2018 в 01:34
поделиться
  • 1
    Похоже, что функция центра не работает в raw X11 через SSH, в Windows через Xming. Кажется, следует придерживаться стандартного размещения окна Window, начиная с верхнего левого. Выход геометрии выглядит правильно, но возможно ли какое-то взаимодействие с Xming не работает? – Kumba 24 June 2013 в 12:44
  • 2
    трюк -альфа, похоже, не работает в Linux. Не знаю, что еще я могу сделать. – Gabriel Staples 21 August 2016 в 02:18
  • 3
    Ваш код задает размер фиксированного размера. Окно автоматически не изменяет размер, когда добавляются / удаляются / изменяются виджеты. Было бы лучше установить только положение окна и оставить его размер в одиночку. – Aran-Fey 26 July 2018 в 10:04

Я нашел решение для того же вопроса на этом сайте

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()

Конечно, я изменил его соответственно моим целям, он работает.

2
ответ дан Ievgen S. 22 August 2018 в 01:34
поделиться

Tk предоставляет вспомогательную функцию, которая может сделать это как tk::PlaceWindow, но я не верю, что она была выставлена ​​как завернутый метод в Tkinter. Вы бы центрировали виджет, используя следующее:

from tkinter import *

app = Tk()
app.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))
app.mainloop()

Эта функция также должна иметь дело с несколькими дисплеями. Он также имеет опции для центровки над другим виджетами или относительно указателя (используется для размещения всплывающих меню), чтобы они не падали с экрана.

17
ответ дан nbro 22 August 2018 в 01:34
поделиться
  • 1
    К сожалению, он не учитывает внешний фрейм с названием и кнопкой закрытия; поэтому он по-прежнему не полностью центрирован (по крайней мере, на Windows 7). Это короткая альтернатива ответа Уэйна. +1 для этого все же. Возможно, мы сможем его обновить разработчиками Tk. – Honest Abe 30 January 2015 в 03:35
  • 2
    winfo_pathname не работает на Python 3.5.1 (на Win10) с _tkinter.TclError: window id "2885868" doesn't exist in this application. Я не думаю, что когда-либо работал над Python 3, но из вашего импорта в нижний регистр, я полагаю, это сработало для вас? Я смог обновить код, используя вместо этого winfo_toplevel: app.eval('tk::PlaceWindow %s center' % app.winfo_toplevel()) – idbrii 17 January 2017 в 20:11

Использование:

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()
0
ответ дан NightOwl888 22 August 2018 в 01:34
поделиться

Этот ответ лучше для понимания beginner

#
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()
0
ответ дан Sandeep Prasad Kushwaha 22 August 2018 в 01:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: