Перейти к содержимому

Tkinter как сделать окно по центру

  • автор:

Как в Tkinter отцентровать окно внутри другого окна?

У меня есть некое окно с кнопками. Одна из кнопок открывает еще одно окно. Как можно сделать так, чтобы второе окно, которое открывается по кнопке, открывалось по центру первого окна? Или хотя бы не выходило за его пределы.
В гугле не нашел ничего похожего кроме того как в целом можно отцентровать окно, но как связать окна между собой не ясно. Буквально вчера начал изучать python по этому пока не могу даже наводящими поисковыми запросами вырулить в нужное направление.

  • Вопрос задан 01 июн. 2023
  • 151 просмотр

1 комментарий

Простой 1 комментарий

TosterModerator

Модератор @TosterModerator

Не надо ставить как можно больше тэгов. Лучше оставить один, но конкретный, с которым проблема.
См.п.3.1 Регламента.
Если нет кода python, не ставьте тэг python . Если есть тэг более конкретный, чем python (т.е. Tkinter ) не ставьте тэг python .

Решения вопроса 0
Ответы на вопрос 2

Nicelogin

Nicelogin @Nicelogin Автор вопроса

Решил вот таким способом, отцентровав окна по отдельности. В целом удовлетворительно, так как окна открываются не абы где а примерно по центру. Так как первое окно больше, а второе меньше создается ощущение что они связаны и второе открывается внутри первого. Но это не совсем решение так как если изменить настройки открытия первого второе не потянется за ним и не будет открываться внутри.

w = root.winfo_screenwidth() h = root.winfo_screenheight() w = w//2 # середина экрана h = h//2 w = w - 200 # смещение от середины h = h - 200 root.geometry('400x400+<>+<>'.format(w, h))

Отобразить форму по центру экрана по его высоте — Tkinter — Ответ 15410586

Ципихович Эндрю, да, но у —geometry говорю же оч кривой формат, помниться там наличие двойных кавычек давало результат (не в питоне а в debian-twm) так, что здесь нужно побольше кофе.

root.minsize(width=200, height=100)
сорь, но по специфичной либе винды ни чем не помогу ((

Добавлено через 2 минуты
так же можно попробовать через root.eval(special ttk command), но даже не знаю имеется ли там возможность изменять размер окна.

Меню пользователя @ user-ganz

Окна

По умолчанию приложение Tkinter имеет одно главное окно, которое представляет класс tkinter.Tk . Запуск приложение приводит к запуску главного окно, в рамках которого помещаются все виджеты. Закрытие главного окна приводит к завершению работы приложения. Однако в рамках главного окна также можно запускать вторичные, неглавные окна. Например, октроем новое окно по нажатию на кнопку:

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") def click(): window = Tk() window.title("Новое окно") window.geometry("250x200") button = ttk.Button(text="Создать окно", command=click) button.pack(anchor=CENTER, expand=1) root.mainloop()

Здесь по нажатию на кнопку создается новый объект window, у него устанавливается заголовок и размеры.

Создание окон в Tkinter и Python

Стоит отметить, что приложение завершит работу, когда будут закрыты все его окна.

Как и главное окно, вторичные окна могут иметь виджеты. Например, определим на новом окне метку:

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") def click(): window = Tk() window.title("Новое окно") window.geometry("250x200") label=ttk.Label(window, text="Принципиально новое окно") label.pack(anchor=CENTER, expand=1) button = ttk.Button(text="Создать окно", command=click) button.pack(anchor=CENTER, expand=1) root.mainloop()

Единственное не надо забывать у добавляемых виджетов устанавливать окно в качестве родительского контейнера

Создание окон Tk в Tkinter и Python

Удаление окна

Для удаления окна применяется меnод destroy()

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") def click(): window = Tk() window.title("Новое окно") window.geometry("250x200") close_button = ttk.Button(window, text="Закрыть окно", command=lambda: window.destroy()) close_button.pack(anchor="center", expand=1) open_button = ttk.Button(text="Создать окно", command=click) open_button.pack(anchor="center", expand=1) root.mainloop()

В данном случае в новом окне по нажатию на кнопку close_button срабатывает метод window.destroy() , который закрывает окно и по сути аналогичен нажатию на крестик в верхнем правом углу окна.

Определение окна в объектно-ориентированном стиле

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

from tkinter import * from tkinter import ttk class Window(Tk): def __init__(self): super().__init__() # конфигурация окна self.title("Новое окно") self.geometry("250x200") # определение кнопки self.button = ttk.Button(self, text="закрыть") self.button["command"] = self.button_clicked self.button.pack(anchor="center", expand=1) def button_clicked(self): self.destroy() root = Tk() root.title("METANIT.COM") root.geometry("250x200") def click(): window = Window() open_button = ttk.Button(text="Создать окно", command=click) open_button.pack(anchor="center", expand=1) root.mainloop()

Здесь определение окна вынесено в отдельный класс Window, который наследуется от класса tkinter.Tk. Благодаря этому мы можем вынести весь код определения окна в отдельную структурную единицу — класс, что позволит упростить управление кодом.

Окно поверх других окон

Для создания диалогового окна, которое располагается поверх главного окна, применяется класс Toplevel :

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") def dismiss(window): window.grab_release() window.destroy() def click(): window = Toplevel() window.title("Новое окно") window.geometry("250x200") window.protocol("WM_DELETE_WINDOW", lambda: dismiss(window)) # перехватываем нажатие на крестик close_button = ttk.Button(window, text="Закрыть окно", command=lambda: dismiss(window)) close_button.pack(anchor="center", expand=1) window.grab_set() # захватываем пользовательский ввод open_button = ttk.Button(text="Создать окно", command=click) open_button.pack(anchor="center", expand=1) root.mainloop()

Toplevel по сути то же самое окно Tk, которое располагается поверх других окон. В примере выше оно также имеет кнопку. Но кроме того, чтобы пользователь не мог перейти обратно к главному окну пока не закроет это диалоговое окно, применяется ряд методов. Прежде всего захватываем весь пользовательский ввод с помощью метода grab_set() :

window.grab_set()

В функции dismiss() , которая закрывает окно, освобождаем ввод с помощью метода grab_release()

window.grab_release()

Tkinter как сделать окно по центру

Для позиционирования виджетов в контейнере применяются различные способы. Один из них представляет вызов у виджета метода pack() . Этот метод принимает следующие параметры:

  • expand : если равно True, то виджет заполняет все пространство контейнера.
  • fill : определяет, будет ли виджет растягиваться, чтобы заполнить свободное пространство вокруг. Этот параметр может принимать следующие значения: NONE (по умолчанию, элемент не растягивается), X (элемент растягивается только по горизонтали), Y (элемент растягивается только по вертикали) и BOTH (элемент растягивается по вертикали и горизонтали).
  • anchor : помещает виджет в определенной части контейнера. Может принимать значения n, e, s, w, ne, nw, se, sw, c, которые являются сокращениями от Noth(север — вверх), South (юг — низ), East (восток — правая сторона), West (запад — левая сторона) и Center (по центру). Например, значение nw указывает на верхний левый угол
  • side : выравнивает виджет по одной из сторон контейнера. Может принимать значения: TOP (по умолчанию, выравнивается по верхней стороне контейнера), BOTTOM (выравнивание по нижней стороне), LEFT (выравнивание по левой стороне), RIGHT (выравнивание по правой стороне).
  • ipadx : устанавливает отступ содержимого виджета от его границы по горизонтали.
  • ipady : устанавливают отступ содержимого виджета от его границы по вертикали.
  • padx : устанавливает отступ виджета от границ контейнера по горизонтали.
  • pady : устанавливает отступ виджета от границ контейнера по вертикали.

Растяжение виджета

Для растяжения виджета применяется параметру expand передается значение True (или соответствующее число). Причем при отсутствии других параметров позиционирования значение expand=True позволяет поместить виджет по центру:

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") btn = ttk.Button(text="Click me") btn.pack(expand=True) root.mainloop()

позиционирование виджета по центру в tkinter и python

Anchor

Параметр anchor помещает виджет в определенной части контейнера. Может принимать следующие значения:

  • n : положение вверху по центру
  • e : положение в правой части контейнера по центру
  • s : положение внизу по центру
  • w : положение в левой части контейнера по центру
  • nw : положение в верхнем левом углу
  • ne : положение в верхнем правом углу
  • se : положение в нижнем правом углу
  • sw : положение в нижнем левом углу
  • center : положение центру

Схематически это выглядит следующим образом:

позиционирование виджета в tkinter и python

Стоит отметить, что значение в кавычках для параметра anchor передается в нижнем регистре, без кавычек — в верхнем регистре

btn.pack(anchor="nw") btn.pack(anchor=NW)

Также стоит отметить, что для некоторых сценариев (например, помещение в нижней части контейнера) может потребоваться указать для параметра expand значение True. Например, поместим кнопку в верхнем левом углу:

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") btn = ttk.Button(text="Click me") btn.pack(anchor="nw") root.mainloop()

позиционирование виджета в контейнере в tkinter и python

Заполнение контейнера

Параметр fill позволяет заполнить пространство контейнер по горизонтали (значение X), по вертикали (значение Y) или по обеим сторонам (значение BOTH). По умолчанию значение NONE, при котором заполнение контейнера отсутствует. Например, заполним все пространство контейнера по горизонтали

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") btn = ttk.Button(text="Click me") btn.pack(fill=X) root.mainloop()

Метод pack и fill в tkinter Python

Для заполнения контейнера по всем сторонам также требуется установить параметр expand = True

btn.pack(fill=BOTH, expand=True)

Отступы

Параметры padx и pady позволяют указать отступы виджета от границ контейнера:

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") btn = ttk.Button(text="Click me") btn.pack(anchor="nw", padx=20, pady=30) root.mainloop()

Здесь кнопка смещена относительно верхнего левого угла на 20 единиц вправо и на 30 единиц вниз

Метод pack и внешние отступы виджета в tkinter Python

Выше устанавливался общий отступ от левой и правой стороны и общий отступ от верхней и нижней кромки контейнера. Поскольку кнопка позиционировалась в верхнем левом углу и имеела небольшие размеры, отступ от нижней и правой кромки контейнера нас не особо интересовали. Однако при желании мы можем задать отдельно два отступа от правой и левой границы и отдельно два отступа от верхней и нижней границ:

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") btn = ttk.Button(text="Click me") btn.pack(fill=X, padx=[20, 60], pady=30) root.mainloop()

В данном случае отступ слева — 20 единиц, а справа — 60 единиц

 внешние отступы виджета в tkinter Python

Параметры ipadx и ipady позволяют указать отступы содержимого виджета от границ виджета по горизонтали и вертикали соответственно:

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") btn = ttk.Button(text="Click me") btn.pack(expand=True, ipadx=10, ipady=10) root.mainloop()

 внутренние отступы виджета в tkinter Python

Позиционирование по стороне

Используем параметр side :

from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") btn1 = ttk.Button(text="BOTTOM") btn1.pack(side=BOTTOM) btn2 = ttk.Button(text="RIGHT") btn2.pack(side=RIGHT) btn3 = ttk.Button(text="LEFT") btn3.pack(side=LEFT) btn4 = ttk.Button(text="TOP") btn4.pack(side=TOP) root.mainloop()

Параметр side в методе pack в Python

Комбинируя параметры side и fill, можно растянуть элемент по вертикали:

btn1 = ttk.Button(text="CLICK ME") btn1.pack(side=LEFT, fill=Y)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *