Как сделать окно активным в tkinter

Добавил пользователь Skiper
Обновлено: 05.10.2024

Это третья часть нашей многосерийной серии по разработке графических интерфейсов на Python с использованием Tkinter. Проверьте ссылки ниже для других частей этой серии:

  • Разработка графического интерфейса Python с помощью Tkinter
  • Разработка графического интерфейса Python с помощью Tkinter: Часть 2
  • Разработка графического интерфейса Python с помощью Tkinter: Часть 3

Вступление

Tkinter – это де-факто стандартный пакет для построения графических интерфейсов в Python. В Stackabuse first и second части учебника Tkinter мы узнали, как использовать основные строительные блоки GUI для создания простых интерфейсов.

В последней части нашего урока мы рассмотрим несколько ярлыков, которые предлагает Tkinter, чтобы мы могли легко предлагать сложные и очень полезные функции. Мы также узнаем о Python MegaWidgets – инструментарии, основанном на Tkinter, который еще быстрее ускоряет создание сложных интерфейсов.

Диалоговое окно файла

Предоставление пользователю возможности выбрать файл на своем компьютере, очевидно, является очень распространенной особенностью графических интерфейсов. Диалоговые окна файлов обычно довольно сложны – они объединяют по крайней мере несколько кнопок (например, Open , Cancel или Create New Folder ) и фрейм, который отображает структуру каталогов нашей среды. Основываясь на наших предыдущих уроках, вы можете предположить, что с помощью Tkinter очень трудно создать такую сложную функцию. Однако на самом деле это не так. Взгляните на следующий пример:

Приведенный выше код-это все, что вам нужно для отображения приятного, полезного диалога File Dialog . В строке 2 мы импортируем содержимое класса filedialog . Затем, после создания нашего окна root в строке 4, мы определяем новую функцию в строке 6 (которая должна выполняться кнопкой, созданной в строке 17 и упакованной в строку 18).

Давайте взглянем на определение функции print_path () . В строке 7 мы выполняем функцию askopenfilename , которая принимает несколько аргументов. Первым аргументом, конечно, является родительский виджет диалогового окна (который в данном случае является нашим корневым окном). Затем в аргументе initialdir мы указываем местоположение, которое будет отображаться в нашем диалоговом окне файла сразу после его открытия. title управляет содержимым строки заголовка диалогового окна.

И тогда у нас есть аргумент file types , благодаря которому мы можем указать, какие файлы будут видны пользователю в диалоговом окне file. Сужение типов файлов может значительно ускорить поиск нужного файла, а также дать пользователю знать, какие типы файлов принимаются.

Аргумент для типов файлов представляет собой список 2-элементных кортежей. В каждом кортеже первым элементом является строка, представляющая собой любое описание, которое мы хотим задать для каждого из типов файлов. Второй элемент – это то, где мы указываем или перечисляем расширения файлов, связанные с каждым типом файла (если есть только одно расширение, это строка, в противном случае это кортеж). Как вы можете видеть на скриншоте вывода выше, пользователь может выбрать отображаемый тип файла из выпадающего списка в правом нижнем углу диалогового окна.

Метод askopenfilename() возвращает строку, которая является путем к файлу, выбранному пользователем. Если пользователь решает нажать Cancel , возвращается пустая строка. В строке 7 мы возвращаем путь к переменной f , а затем в строке 15 (которая выполняется только после закрытия диалогового окна файла) путь печатается в консоли.

Отображение Изображений С Помощью Tkinter

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

Давайте посмотрим, что изменилось внутри функции, выполняемой нашей кнопкой, теперь переименованной в display_image . Мы выводим диалоговое окно файла, используем те же критерии выбора файла, что и раньше, и снова сохраняем возвращенный путь в переменной f . Однако после получения пути к файлу мы не печатаем его в консоли. Мы создаем окно верхнего уровня в строке 14. Затем в строке 16 мы создаем экземпляр объекта класса PhotoImage , заставляя его читать файл .jpg , выбранный пользователем. Затем объект сохраняется в переменной image , которую мы можем передать в качестве аргумента для построения виджета Label в строке 17. В строке 18 мы обязательно сохраняем ссылку на объект image , чтобы он не был очищен сборщиком мусора Python . Затем в строке 19 мы упаковываем нашу метку (на этот раз отображающую изображение, а не текст) внутри new_window .

Выбор Цвета

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

В строке 2 примера, показанного выше, мы импортируем класс с именем color chooser . Мы используем его метод askcolor() в строке 7. Этот метод, как и askopenfilename() , отвечает за открытие красивого, сложного диалога (в данном случае выбор цвета) и возвращает данные, зависящие от выбора пользователя. В этом случае после того, как пользователь выбирает цвет из палитры и принимает свой выбор, объект, возвращаемый переменной color , представляет собой кортеж, содержащий два элемента. Первый элемент-это кортеж, который хранит значения для красного, зеленого и синего каналов выбранного цвета. Второй элемент кортежа имеет тот же цвет, что и в формате hexadecimal . Мы можем видеть содержимое кортежей в нашей консоли, благодаря print() в строке 8.

После того как мы сохраним кортеж , возвращенный askcolor в переменной color , мы затем используем эту переменную в строке 9 для настройки кнопки b1 . Как вы уже знаете, аргумент bg отвечает за управление цветом фона кнопки. Передаем ему первый элемент кортежа color (представление цвета в шестнадцатеричном формате). В результате, после нажатия кнопки b1 пользователь может изменить свой цвет фона, используя хороший выбор цвета.

Как я уже говорил, строки 11-21 содержат код, отвечающий за отображение диалогов для получения решения пользователя. askokcancel (строка 11) возвращает True если пользователь нажимает OK и False если он нажимает Cancel . askyesno (строка 14) возвращает True если пользователь нажимает Yes и False если пользователь нажимает No . askretrycancel (строка 17) возвращает True если пользователь нажимает Retry и False если пользователь нажимает Cancel . askquestion очень похож на askyesno , но возвращает 'yes' если пользователь нажимает Yes и 'no' если пользователь нажимает No .

Индикатор выполнения

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

В приведенном выше примере показана реализация Progress bar . Он является частью модуля tkinter.ttk , который обеспечивает доступ к набору тематических виджетов Tk, представленному в Tk 8.5 . Вот почему нам нужно дополнительно импортировать модуль ttk в строке 3.

Состояние нашего индикатора прогресса будет контролироваться временем – индикатор будет прогрессировать в десять шагов, выполняемых с интервалом в одну секунду. Для этого мы импортируем модуль time в строку 2.

Мы определяем наш Индикатор выполнения в строке 20. Мы определяем его родительский виджет ( root ), даем ему “горизонтальную” ориентацию и длину 200 пикселей. Затем мы определяем значение maximum , которое является значением переменной, назначенной индикатору выполнения с помощью аргумента var (в нашем случае переменной progress_var ), что означает, что индикатор выполнения заполнен полностью. Мы устанавливаем mode на “determinate”, что означает, что наш код будет перемещать длину индикатора в точно определенные точки на основе значения progress_var .

Целочисленная переменная progress_var , которая будет управлять прогрессом бара, определена в строке 18. В строке 26, используя задание типа словаря, мы устанавливаем начальное значение индикатора выполнения равным 0.

В строке 15 мы создаем кнопку , которая должна запустить часы, контролирующие ход нашего бара, выполнив функцию start () , определенную между строками 7 и 13. Там у нас есть простой цикл for , который будет перебирать значения от 1 до 10. С каждой итерацией значение progress_var обновляется и увеличивается на 1. Чтобы иметь возможность четко наблюдать за ходом выполнения, мы ждем одну секунду во время каждой итерации (строка 12). Затем мы используем метод корневого окна update_idletasks() в строке 13, чтобы позволить программе обновить внешний вид индикатора выполнения, даже если мы все еще выполняем цикл for (таким образом, технически мы все еще находимся в одной итерации mainloop () ).

Python Mega Widgets

Если вы широко используете Tkinter в своих проектах, я думаю, что это хорошая идея, чтобы рассмотреть возможность включения Python Mega Widgets в ваш код. Python MegaWidgets-это инструментарий, основанный на Tkinter, который предлагает набор megawidgets : сложных, функциональных и относительно эстетически приятных виджетов, сделанных из более простых виджетов Tkinter. Что замечательно в этом пакете, который вы можете скачать здесь , так это то, что общая философия определения и ориентации виджетов такая же, как и в случае с Tkinter, и вы можете смешивать обе библиотеки в своем коде. Давайте закончим наш урок, поцарапав поверхность этого мощного инструментария.

Виджет EntryField

Одним из наиболее полезных виджетов пакета Pmw является Поле ввода . Давайте проанализируем следующий пример, чтобы увидеть, на что он способен:

На этот раз мы должны не только импортировать tkinter , но и наш недавно установленный Pmw пакет (строка 2). Как всегда, мы используем класс Tk для инициализации нашего корневого окна.

В строках 10-14 и 16-20 мы определяем два Pmw.EntryField виджеты. Поле ввода представляет собой функциональную смесь Tkinter Label и Entry с некоторым добавлением полезных функций. Первым аргументом для инициализации виджета является, конечно же, родительский виджет. label_text , entry_bg и entry_width управляют некоторыми самоочевидными аспектами внешнего вида виджета. Наиболее интересным аргументом в нашем примере, вероятно, является аргумент validate . Здесь мы можем решить, какие данные пользователь может поместить в поле.

В поле entry_color мы ожидаем строку букв, поэтому устанавливаем validate в “алфавитный”. В виджете entry_number мы ожидаем целое число, и именно на него мы устанавливаем значение аргумента validate . Таким образом, если мы попытаемся поместить число внутри первого и букву внутри второго, символы просто не появятся в виджетах, и будет воспроизводиться системный звук, сообщающий нам, что мы пытаемся сделать что-то не так. Кроме того, если виджет ожидает определенного типа данных и его содержимое находится в конфликте с этим условием в момент инициализации, поле EntryField будет выделено красным цветом.

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

Кнопка, определенная в строке 26, выполняет команду color_entry_label () , определенную между строками 6 и 8. Цель функции-нарисовать фон метки виджета entry_number в соответствии с содержимым виджета entry_color . В строке 7 метод get() используется для извлечения содержимого поля entry_color | Entry . Затем, естественно, метод configure() используется для изменения внешнего вида виджета entry_number . Обратите внимание, что для изменения характеристик виджетов Pmw, состоящих из нескольких более простых виджетов, мы должны указать, какой суб-виджет мы хотим настроить (в нашем случае это метка - именно поэтому мы настраиваем label_bg , а не, скажем, entryfield_bg ).

Виджет EntryField может быть визуально не очень впечатляющим, но даже этот простой пример иллюстрирует потенциал мега-виджетов – создание такого рода самоподтверждающейся части интерфейса более высокой сложности потребовало бы гораздо больше кода, если бы мы попытались достичь того же эффекта с помощью простого Tkinter. Я призываю вас изучить другие мощные мега-виджеты, описанные в документации инструментария .

Вывод

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

Графический интерфейс – необходимый компонент любого современного приложения. Он значительно облегчает использование программы, управление ее настройками и выполнение любых других действий. Существует несколько библиотек, позволяющих на практике реализовывать работу графического интерфейса в Python. Но самой простой, безусловно, является Tkinter. Она позволяет создавать окна и добавлять на них привычные каждому графические элементы: надписи, кнопки. Поскольку Tkinter – свободное ПО, то эта библиотека регулярно обновляется и дополняется. Это позволяет ее использовать по максимуму. Сегодня мы более подробно поговорим об окне в этой оболочке. В том числе, о том, как осуществлять его настройку и обработку событий.

Как обрабатывать события с мыши и клавиатуры?

Любое приложение с графическим интерфейсом может реагировать на события. Без этого никуда. Именно от него зависит возможность вообще взаимодействовать с окном приложения.

Что такое событие? Это функция, которая выполняется каждый раз, когда выполняется определенное действие или появляется определенное условие, связанное с графическим интерфейсом.

С событиями сталкивался каждый пользователь, когда нажимал клавиши на клавиатуре или выполнял клик мышью по элементам. Например, параметр command – это типичный обработчик событий виджета Button. После того, как кнопка будет нажата, выполняется функция, которая прописывается в том параметре.

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

Как проверить, привязано ли конкретное событие к элементу окна? Для этого необходимо использовать функцию bind . Приведем пример, который демонстрирует, как осуществляется привязка событий мыши к Frame .

import tkinter as tk

class App(tk.Tk):

def __init__(self):

super().__init__()

height=100, width=100)

frame.pack(padx=50, pady=50)

def print_event(self, event):

app = App()

app.mainloop()

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

Приведем еще один пример. Он продемонстрирует, как работает программа с одним полем ввода и несколькими привязками. Первая из них активируется, на текстовое поле переходит фокус, а второе – если нажимается кнопка.

import tkinter as tk

class App(tk.Tk):

def __init__(self):

super().__init__()

entry = tk.Entry(self)

entry.pack(padx=20, pady=20)

def print_type(self, event):

print(event.type)

def print_key(self, event):

app = App()

app.mainloop()

Сначала в приложении активируется событие FocusIn , которое срабатывает на появление фокуса в поле ввода.

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

Отслеживание событий: принцип работы

Метод bind , который используется для отслеживания событий, используется с тремя аргументами:

  1. Событие, которое должно отслеживаться.
  2. Функция, которая выполняется при активации события.
  3. Строка Add , использование которой – необязательно.

Первый аргумент должен содержать событие формата .

Модификаторы также использовать необязательно. С их помощью можно задать дополнительные особенности события типа нажатия вспомогательных кнопок, двойного, тройного осуществления события и так далее.

Приведем их подробный перечень.

  • Shift – при нажатии клавиши Shift вместе с событием, которое происходит.
  • Alt – задает срабатывание события при условии, что одновременно с ним нажата клавиша Alt.
  • Control – если нажимается кнопка Control на клавиатуре.
  • Lock – при нажатии клавиши Lock на клавиатуре.
  • Shift – если в момент активации события одновременно нажимается кнопка Shift.
  • Double – двойная активация события.
  • Triple – тройная активация события

События могут быть следующих типов:

  • ButtonPress или Button – это те события, активация которых осуществляется, когда человек нажимает кнопку мыши.
  • ButtonRelease – аналогичное, на первый взгляд, предыдущему событие за тем лишь исключением, что его обработка осуществляется не в момент нажатия кнопки, а в момент, когда пользователь отпускает кнопку мыши. Разницу между ними можно заметить, лишь если понаблюдать за каждым из вариантов. Если используется только один из этих обработчиков, то разницу можно будет и не заметить.
  • Enter – событие, которое активируется при перемещении курсора мыши на виджет.
  • Leave – событие, обратное предыдущему. Активируется, если мышь покидает границы элемента.
  • FocusIn – событие, активация которого происходит при попадании фокуса ввода в текстовое поле.
  • FocusOut – аналогично предыдущим, это обратное по значению событие. Оно активируется, когда фокус исчезает из поля ввода.
  • KeyPress или Key – событие для нажатия кнопки.
  • KeyRelease – событие для отпущенной кнопки.
  • Motion – событие при перемещении мыши.

Еще параметр – это detail . Его использование необязательно. С его помощью можно конкретизировать событие. Допустим, человек кликнул левой кнопкой мыши, и получил результат. И щелкнул правой кнопкой. И также получил результат. А что, если нам надо сделать так, чтобы обработчик события вызывался исключительно при нажатии правой кнопки мыши? В этом случае необходимо передать этому параметру значение 3.

Кстати, можно также настроить отдельные обработчики событий для левой и средней кнопок. Для этого необходимо использовать значения 1 и 2 соответственно.

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

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

Также можно поставить координаты относительно верхнего левого угла экрана. Для этого используются x_root и y_root . Если же необходимо получить номер кнопки мыши, которая была нажата, используется атрибут num . Числа указаны выше.
Хорошо, а как нам получить параметры события, связанного с клавиатурой. Для этого используются такие атрибуты:

  • char . Это та клавиша, которая была нажата, которая передается в строчном формате.
  • keysym . Это нажатая пользователем клавиша, которая передается в виде символа, изображенном на самой клавише.
  • keycode . Это код, соответствующий клавише, которая была нажата.

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

Если используется функция callback, то рекомендуется всегда определять для нее метод. Дело в том, что ссылка на объект будет всегда, и через нее очень легко будет получить доступ к необходимому атрибуту элемента.

Кроме приведенных выше типов событий есть и другие. Но они заслуживают отдельного рассмотрения. Приведем пару примеров для наглядности:

  1. . Это событие означает уничтожение элемента.
  2. . А это используется, если надо изменить размер или положение определенного элемента.

Чтобы ознакомиться с полным перечнем событий, необходимо изучить документацию Tcl/Tk .

Как настроить иконки, названия и размер основного окна

Основное отличие Tk от всех остальных виджетов в том, как осуществляется его настройка. Например, можно настроить иконку, используя метод iconbitmap() , в качестве аргумента которого использовать ссылку на .ico файл. Он должен располагаться в той же папке, что и скрипт.

Кроме замены иконок, можно также осуществлять настройку названия окна. Для этого используется метод title() , в качестве аргумента которого указывается сам заголовок, оформленный в виде строки.

Ну и, наконец, третий метод, с помощью которого мы можем задать размеры окна, является одновременно самым сложным из всех перечисленных выше. Называется он geometry() и принимает один аргумент в виде строки. Но чтобы метод работал, он должен соответствовать шаблону x++ .

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

А чтобы перевести программу в полноэкранный режим, вместо метода geometry() используется state(“zoomed”). Обратите внимание, что состояние должно быть указано именно, как zoomed .

Многие программы на сегодняшний день используют графический интерфейс, который более интуитивен и удобен для пользователя, чем консоль. И с помощью языка программирования Python также можно создавать графические программы. Для этого в Python по умолчанию применяется специальный toolkit - набор компонентов, который называется tkinter .

Библиотека tkinter доступна в виде отдельного встроенного модуля, который содержит все необходимые графические компоненты - кнопки, текстовые поля и т.п.

Базовым моментом в построении графических программ является создание окна. Затем в окно добавляются все остальные компоненты графического интерфейса. Поэтому создадим вначале простейшее окно. Для этого определим следующий скрипт:

Для создания графического окна применяется конструктор Tk() , который определен в модуле tkinter . Создаваемое окно присваивается переменной root , и через эту переменную мы можем управлять атрибутами окна. Вместо комментария '''any code''' добавляются все необходимые компоненты окна.

Для отображения окна надо вызвать у него метод mainloop() , который запускает цикл обработки событий окна для взаимодействия с пользователем.

В результате при запуске скрипта мы увидим такое пустое окошко:

C помощью метода title() можно установить заголовок окна.

По умолчанию окно позиционируется в верхний левый угол экрана. Но мы можем изменить его положение, передав нужные значения в метод geometry() :

Создайте 4 окна с заголовками окон: "Top", "Bottom", "Right", "Left". Разместить окна по сторонам рабочего стола:

  • вверх по центру,
  • низ по центру,
  • право по центру,
  • лево по центру.

Создайте 4 окна с заголовками окон: "Top-right", "Top-left", "Bottom-right", "Bottom-left". Разместить 4 окна по углам рабочего стола.

Создайте окно, появляющееся в центре экрана, с заголовком "Center".

Текстовые и другие редакторы в заголовках программы указывают имя "активного файла - название программы".

  • Создайте окно с заголовком в виде f-строки, в котором указывается имя разработчика, название и версия программы;
  • Имя и версия программы хранятся в отдельных переменных;
  • Пример вывода заголовка: "Bob's programm - Empty v.01"

Иконки окон не отображаются в системах MacOS, задача только для Windows: Найдите в интернете, как в tkinter сменить иконку, отображаемую в левом верхнем углу окна. И замените её, на любую другую иконку, которую можно скопировать из интернета или создать самому. Картинка для иконки обязательно должна иметь расширение .ico .

Нужно чтобы открывалось первое окно, в нем вводишь уровень игры, нажимаем 'ok', окно закрывается. Открывается второе окно и там есть значение из первого окна. Такое есть во многих программах, например, выбор языка перед запуском программы. Как это сделать на Tkinter?


Вызов нового окна из другого окна
Хочу реализовать следующее. При нажатии на кнопку "Добавить профиль в БД" вызыв второго окна.


Два окна
Есть 2 окна. Одно, главное, вызывает второе. Делаю я это так if listbox1.Items.Count<>0 then.

Два окна
Здравствуйте! Подскажите плиз, как создать в двух окнах от одного класса разные курсоры? . int.

Два параллельных окна
Абстрактно говоря, задача состоит в следующем: есть окно1, в которое юзер вводит некоторый текст.

Читайте также: