Tkinter, оптимизация разрешения окна
Писал олимпиадную задачу, и вот возникла проблема. Если запускать программу на разных операционных системах (или мониторах) интерфейс часто ломается. Возможно, есть какие-то путь оптимизации окна? Можно ли задать значения параметров width и height в процентах от расширения монитора, или что-то вроде этого?
Отслеживать
49.3k 17 17 золотых знаков 57 57 серебряных знаков 101 101 бронзовый знак
задан 6 мар 2020 в 0:56
Werflame Xij Werflame Xij
81 1 1 золотой знак 3 3 серебряных знака 10 10 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
По сути, подобной возможности нет. Но можно узнать расширение монитора пользователя и указать какой либо процент от него. Например, окно с расширением в 80% от монитора:
import tkinter root = tkinter.Tk() x = root.winfo_screenwidth() # размер по горизонтали y = root.winfo_screenheight() # размер по вертикали root.geometry('<>x<>'.format(int(x*0.8), int(y*0.8))) # обязательно должно быть целое число tkinter.mainloop()
Отслеживать
ответ дан 24 мар 2020 в 13:23
red TARDIS red TARDIS
117 5 5 бронзовых знаков
Окна в tkinter
В этом уроке рассмотрим основные настройки окон, в которых располагаются виджеты. Обычные окна в Tkinter порождаются не только от класса Tk , но и Toplevel . От Tk принято создавать главное окно. Если создается многооконное приложение, то остальные окна создаются от Toplevel. Методы обоих классов схожи.
Размер и положение окна
По умолчанию окно приложения появляется в верхнем левом углу экрана. Его размер (ширина и высота) определяется совокупностью размеров расположенных в нем виджетов. В случае если окно пустое, то tkinter устанавливает его размер в 200 на 200 пикселей.
С помощью метода geometry можно изменить как размер окна, так и его положение. Метод принимает строку определенного формата.
from tkinter import * root = Tk() root.geometry('600x400+200+100') root.mainloop()
Первые два числа в строке-аргументе geometry задают ширину и высоту окна. Вторая пара чисел обозначает смещение на экране по осям x и y . В примере окно размерностью 600 на 400 будет смещено от верхней левой точки экрана на 200 пикселей вправо и на 100 пикселей вниз.
Если перед обоими смещениями вместо плюса указывается минус, то расчет происходит от нижних правых углов экрана и окна. Так выражение root.geometry(‘600×400-0-0’) заставит окно появиться в нижнем правом углу.
В аргументе метода geometry можно не указывать либо размер, либо смещение. Например, чтобы сместить окно, но не менять его размер, следует написать root.geometry(‘+200+100’) .
Бывает удобно, чтобы окно появлялось в центре экрана. Методы winfo_screenwidth и winfo_screenheight возвращают количество пикселей экрана, на котором появляется окно. Рассмотрим, как поместить окно в центр, если размер окна известен:
from tkinter import * root = Tk() w = root.winfo_screenwidth() h = root.winfo_screenheight() w = w // 2 # середина экрана h = h // 2 w = w - 200 # смещение от середины h = h - 200 root.geometry(f'400x400++') root.mainloop()
Здесь мы вычитаем половину ширины и высоты окна (по 200 пикселей). Иначе в центре экрана окажется верхний левый угол окна, а не его середина.
Если размер окна неизвестен, то его можно получить с помощью того же метода geometry , но без аргументов. В этом случае метод возвращает строку, содержащую сведения о размерах и смещении, из которой можно извлечь ширину и высоту окна.
from tkinter import * root = Tk() Button(text="Button", width=20).pack() Label(text="Label", width=20, height=3).pack() Button(text="Button", width=20).pack() root.update_idletasks() s = root.geometry() s = s.split('+') s = s[0].split('x') width_root = int(s[0]) height_root = int(s[1]) w = root.winfo_screenwidth() h = root.winfo_screenheight() w = w // 2 h = h // 2 w = w - width_root // 2 h = h - height_root // 2 root.geometry('+<>+<>'.format(w, h)) root.mainloop()
Метод update_idletasks позволяет перезагрузить данные об окне после размещения на нем виджетов. Иначе geometry вернет строку, где ширина и высота равняются по одному пикселю. Видимо таковы параметры на момент запуска приложения.
По умолчанию пользователь может разворачивать окно на весь экран, а также изменять его размер, раздвигая границы. Эти возможности можно отключить с помощью метода resizable . Так root.resizable(False, False) запретит изменение размеров главного окна как по горизонтали, так и вертикали. Развернуть на весь экран его также будет невозможно, при этом соответствующая кнопка разворота исчезает.
Заголовок окна
По умолчанию в заголовке окна находится надпись «tk». Для установки собственного названия используется метод title .
… root.title("Главное окно") …
Если необходимо, заголовок окна можно вообще убрать. В программе ниже второе окно ( Toplevel ) открывается при клике на кнопку, оно не имеет заголовка, так как к нему был применен метод overrideredirect с аргументом True . Через пять секунд данное окно закрывается методом destroy .
from tkinter import * def about(): a = Toplevel() a.geometry('200x150') a['bg'] = 'grey' a.overrideredirect(True) Label(a, text="About this").pack(expand=1) a.after(5000, lambda: a.destroy()) root = Tk() root.title("Главное окно") Button(text="Button", width=20).pack() Label(text="Label", width=20, height=3).pack() Button(text="About", width=20, command=about).pack() root.mainloop()
Практическая работа
Напишите программу, в которой на главном окне находятся холст и кнопка «Добавить фигуру». Кнопка открывает второе окно, включающее четыре поля для ввода координат и две радиокнопки для выбора, рисовать ли на холсте прямоугольник или овал. Здесь же находится кнопка «Нарисовать», при клике на которую соответствующая фигура добавляется на холст, а второе окно закрывается. Проверку корректности ввода в поля можно опустить.
Курс с примерами решений практических работ: pdf-версия
X Скрыть Наверх
Tkinter. Программирование GUI на Python
Окна в tkinter
В этом уроке рассмотрим основные настройки окон, в которых располагаются виджеты. Обычные окна в Tkinter порождаются не только от класса Tk , но и Toplevel . От Tk принято создавать главное окно. Если создается многооконное приложение, то остальные окна создаются от Toplevel. Методы обоих классов схожи.
Размер и положение окна
По умолчанию окно приложения появляется в верхнем левом углу экрана. Его размер (ширина и высота) определяется совокупностью размеров расположенных в нем виджетов. В случае если окно пустое, то tkinter устанавливает его размер в 200 на 200 пикселей.
С помощью метода geometry можно изменить как размер окна, так и его положение. Метод принимает строку определенного формата.
from tkinter import * root = Tk() root.geometry('600x400+200+100') root.mainloop()
Первые два числа в строке-аргументе geometry задают ширину и высоту окна. Вторая пара чисел обозначает смещение на экране по осям x и y . В примере окно размерностью 600 на 400 будет смещено от верхней левой точки экрана на 200 пикселей вправо и на 100 пикселей вниз.
Если перед обоими смещениями вместо плюса указывается минус, то расчет происходит от нижних правых углов экрана и окна. Так выражение root.geometry(‘600×400-0-0’) заставит окно появиться в нижнем правом углу.
В аргументе метода geometry можно не указывать либо размер, либо смещение. Например, чтобы сместить окно, но не менять его размер, следует написать root.geometry(‘+200+100’) .
Бывает удобно, чтобы окно появлялось в центре экрана. Методы winfo_screenwidth и winfo_screenheight возвращают количество пикселей экрана, на котором появляется окно. Рассмотрим, как поместить окно в центр, если размер окна известен:
from tkinter import * root = Tk() w = root.winfo_screenwidth() h = root.winfo_screenheight() w = w // 2 # середина экрана h = h // 2 w = w - 200 # смещение от середины h = h - 200 root.geometry(f'400x400++') root.mainloop()
Здесь мы вычитаем половину ширины и высоты окна (по 200 пикселей). Иначе в центре экрана окажется верхний левый угол окна, а не его середина.
Если размер окна неизвестен, то его можно получить с помощью того же метода geometry , но без аргументов. В этом случае метод возвращает строку, содержащую сведения о размерах и смещении, из которой можно извлечь ширину и высоту окна.
from tkinter import * root = Tk() Button(text="Button", width=20).pack() Label(text="Label", width=20, height=3).pack() Button(text="Button", width=20).pack() root.update_idletasks() s = root.geometry() s = s.split('+') s = s[0].split('x') width_root = int(s[0]) height_root = int(s[1]) w = root.winfo_screenwidth() h = root.winfo_screenheight() w = w // 2 h = h // 2 w = w - width_root // 2 h = h - height_root // 2 root.geometry('+<>+<>'.format(w, h)) root.mainloop()
Метод update_idletasks позволяет перезагрузить данные об окне после размещения на нем виджетов. Иначе geometry вернет строку, где ширина и высота равняются по одному пикселю. Видимо таковы параметры на момент запуска приложения.
По умолчанию пользователь может разворачивать окно на весь экран, а также изменять его размер, раздвигая границы. Эти возможности можно отключить с помощью метода resizable . Так root.resizable(False, False) запретит изменение размеров главного окна как по горизонтали, так и вертикали. Развернуть на весь экран его также будет невозможно, при этом соответствующая кнопка разворота исчезает.
Заголовок окна
По умолчанию в заголовке окна находится надпись «tk». Для установки собственного названия используется метод title .
… root.title("Главное окно") …
Если необходимо, заголовок окна можно вообще убрать. В программе ниже второе окно ( Toplevel ) открывается при клике на кнопку, оно не имеет заголовка, так как к нему был применен метод overrideredirect с аргументом True . Через пять секунд данное окно закрывается методом destroy .
from tkinter import * def about(): a = Toplevel() a.geometry('200x150') a['bg'] = 'grey' a.overrideredirect(True) Label(a, text="About this").pack(expand=1) a.after(5000, lambda: a.destroy()) root = Tk() root.title("Главное окно") Button(text="Button", width=20).pack() Label(text="Label", width=20, height=3).pack() Button(text="About", width=20, command=about).pack() root.mainloop()
Практическая работа
Напишите программу, в которой на главном окне находятся холст и кнопка «Добавить фигуру». Кнопка открывает второе окно, включающее четыре поля для ввода координат и две радиокнопки для выбора, рисовать ли на холсте прямоугольник или овал. Здесь же находится кнопка «Нарисовать», при клике на которую соответствующая фигура добавляется на холст, а второе окно закрывается. Проверку корректности ввода в поля можно опустить.
Курс с примерами решений практических работ: pdf-версия
X Скрыть Наверх
Tkinter. Программирование GUI на Python
Обработка событий и настройка окна / tkinter 4
Возможность реагировать на события — одна из базовых, но важных тем в приложениях с графическим интерфейсом. Именно она определяет, как пользователи смогут взаимодействовать с программой.
Нажимание клавиш на клавиатуре и клики по элементам мышью — базовые примеры событий, все из которых автоматически обрабатываются в некоторых классах Tkinter. Например, это поведение уже реализовано в параметре command класса виджета Button , который вызывает определенную функцию.
Некоторые события можно вызвать и без участия пользователя. Например, фокус ввода можно сместить с одного виджета на другой.
Выполнить привязку события к виджету можно с помощью метода bind . Следующий пример привязывает некоторые события мыши к экземпляру Frame :
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
frame = tk.Frame(self, bg="green",
height=100, width=100)
frame.bind("", self.print_event)
frame.bind("", self.print_event)
frame.bind("", self.print_event)
frame.bind("", self.print_event)
frame.bind("", self.print_event)
frame.bind("", self.print_event)
frame.pack(padx=50, pady=50)
def print_event(self, event):
position = "(x=<>, y=<>)".format(event.x, event.y)
print(event.type, "event", position)
if __name__ == "__main__":
app = App()
app.mainloop()Все события обрабатываются методом класса print_event() , который выводит тип события и положение мыши в консоли. Можете поэкспериментировать, нажимая на зеленую рамку мышью и двигая ею, пока она будет выводить сообщения события.
Следующий пример содержит виджет поля ввода и несколько привязок. Одна из них срабатывает в тот момент, когда фокус оказывается в виджете, а вторая — при нажатии кнопки:
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
entry = tk.Entry(self)
entry.bind("", self.print_type)
entry.bind("", self.print_key)
entry.pack(padx=20, pady=20)
def print_type(self, event):
print(event.type)
def print_key(self, event):
args = event.keysym, event.keycode, event.char
print("Знак: <>, Код: <>, Символ: <>".format(*args))
if __name__ == "__main__":
app = App()
app.mainloop()В первую очередь программа выведет сообщение события FocusIn . Это произойдет в тот момент, когда фокус окажется в виджете Entry. Можно убедиться также в том, что события срабатывают и в случае с непечатаемыми символами, такими как клавиши стрелок или Backspace.
Как работает отслеживание событий
Метод bind определен в классе widget и принимает три аргумента: событие sequence , функцию callback и опциональную строку add :
widget.bind(sequence, callback, add='')Строка sequence использует синтаксис .
Модификаторы являются опциональными и позволяют задать дополнительные комбинации для общего типа события:
- Shift – когда пользователь нажимает клавишу Shift.
- Alt – когда пользователь нажимает клавишу Alt.
- Control – когда пользователь нажимает клавишу Control.
- Lock – когда пользователь нажимает клавишу Lock.
- Shift – когда пользователь нажимает клавишу Shift.
- Shift – когда пользователь нажимает клавишу Shift lock.
- Double – когда событие происходит дважды подряд.
- Triple – когда событие происходит трижды подряд.
Типы события определяют общий тип события:
- ButtonPress или Button – события, которые генерируются при нажатии кнопки мыши.
- ButtonRelease – событие, когда кнопка мыши отпускается.
- Enter – событие при перемещении мыши на виджет.
- Leave – событие, когда мышь покидает область виджета.
- FocusIn – событие, когда фокус ввода попадает в виджет.
- FocusOut – событие, когда виджет теряет фокус ввода.
- KeyPress или Key – событие для нажатия кнопки.
- KeyRelease – событие для отпущенной кнопки.
- Motion – событие при перемещении мыши.
detail – также опциональный параметр, который отвечает за определение конкретной клавиши или кнопки:
- Для событий мыши 1 — это левая кнопка, 2 — средняя, а 3 — правая
- Для событий клавиатуры используются сами клавиши. Если это специальные клавиши, то используется специальный символ: enter, Tab, Esc, up, down, right, left, Backspace и функциональные клавиши (от F1 до F12).
Функция callback принимает параметр события. Для событий мыши это следующие атрибуты:
- x и y – текущее положение мыши в пикселях
- x_root и y_root — то же, что и x или y, но относительно верхнего левого угла экрана
- num – номер кнопки мыши
Для клавиш клавиатуры это следующие атрибуты:
- char – нажатая клавиша в виде строки
- keysym – символ нажатой клавиши
- keycode – код нажатой клавиши
В обоих случаях у события есть атрибут widget , ссылающийся на экземпляр, который сгенерировал событие и type , определяющий тип события.
Рекомендуется определять метод для функции callback , поскольку всегда будет иметься ссылка на экземпляр класса, и таким образом можно будет легко получить доступ к атрибутам widget .
Наконец, параметр add может быть пустым ( "" ) для замены функции callback , если до этого была привязка или + для добавления функции обратного вызова и сохранения старых.
Помимо описанных типов событий есть и другие, которые оказываются полезными в определенных сценариях: например, генерируется при уничтожении виджета, а — при изменении размера или положения.
Полный список событий доступен в документации Tcl/Tk.
Настройка иконки, названия и размера основного окна
Экземпляр Tk отличается от обычных виджетов тем, как он настраивается. Рассмотрим основные методы, которые позволяют настраивать внешний вид.
Этот кусок кода создает основное окно с заданными названием и иконкой. Его ширина — 400 пикселей, а высота — 200. Плюс, есть разделение в 10px по каждой оси к левому верхнему углу экрана.