Введение в tkinter. Урок 1

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

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

Для языка программирования Python такие виджеты включены в специальную библиотеку — tkinter. Если ее импортировать в программу (скрипт), то можно пользоваться ее компонентами, создавая графический интерфейс.

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

  1. Импорт библиотеки
  2. Создание главного окна
  3. Создание виджет
  4. Установка их свойств
  5. Определение событий
  6. Определение обработчиков событий
  7. Расположение виджет на главном окне
  8. Отображение главного окна

1. Импорт модуля tkinter

Как и любой модуль, tkinter в Python можно импортировать двумя способами: командами import tkinter или from tkinter import *. В дальнейшем мы будем пользоваться только вторым способом, т. к. это позволит не указывать каждый раз имя модуля при обращении к объектам, которые в нем содержатся. Следует обратить внимание, что в версии Python 3 имя модуля пишется со строчной буквы (tkinter), хотя в более ранних версиях использовалась прописная (Tkinter). Итак, первая строчка программы должна выглядеть так:

from tkinter import *

2. Создание главного окна

В современных операционных системах любое пользовательское приложение заключено в окно, которое можно назвать главным, т.к. в нем располагаются все остальные виджеты. Объект окна верхнего уровня создается при обращении к классу Tk модуля tkinter. Переменную связанную с объектом-окном принято называть root (хотя понятно, что можно назвать как угодно, но так уж принято). Вторая строчка кода:

root = Tk()

3. Создание виджет

Допустим в окне будет располагаться всего одна кнопка. Кнопка создается при обращении к классу Button модуля tkinter. Объект кнопка связывается с какой-нибудь переменной. У класса Button (как и всех остальных классов, за исключением Tk) есть обязательный параметр — объект, которому кнопка принадлежит (кнопка не может "быть ничейной"). Пока у нас есть единственное окно (root), оно и будет аргументом, передаваемым в класс при создании объекта-кнопки:

but = Button(root)

4. Установка свойств виджет

У кнопки много свойств: размер, цвет фона и надписи и др. Мы рассмотрим их на следующем уроке. Пока же установим всего одно свойство — текст надписи (text):

but["text"] = "Печать"

5-6. Определение событий и их обработчиков

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

Что же будет делать кнопка и в какой момент она это будет делать? Предположим, что задача кнопки вывести какое-нибудь сообщение в поток вывода, используя функцию print. Делать она это будет при нажатии на нее левой кнопкой мыши.

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

def printer(event):
     print ("Как всегда очередной 'Hello World!'")

Не забывайте, что функцию желательно (почти обязательно) размещать в начале кода. Параметр event – это какое-либо событие.

Событие нажатия левой кнопкой мыши выглядит так: <Button-1>. Требуется связать это событие с обработчиком (функцией printer). Для связи предназначен метод bind. Синтаксис связывания события с обработчиком выглядит так:

but.bind("<Button-1>",printer)

7. Размещение виджет

Если вы заметите, то в любом приложении виджеты не разбросаны по окну как попало, а хорошо организованы, интерфейс продуман до мелочей и обычно подчинен определенным стандартам. До стандартов нам далеко, нужно просто кнопку как-то отобразить в окне. Самый простой способ — это использование метода pack.

but.pack()

Если не вставить эту строчку кода, то кнопка в окне так и не появится, хотя она есть в программе.

8. Отображение главного окна

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

root.mainloop()

Данная строчка кода должна быть всегда в конце скрипта!

В итоге, код программы может выглядеть таким образом:

from tkinter import *
 
def printer(event):
     print ("Как всегда очередной 'Hello World!'")
 
root = Tk()
but = Button(root)
but["text"] = "Печать"
but.bind("<Button-1>",printer)
 
but.pack()
root.mainloop() 

При программировании графического интерфейса пользователя более эффективным оказывается объектно-ориентированный подход. Поэтому многие «вещи» оформляются в виде классов. В нашем примере также можно использовать класс:

from tkinter import *
 
class But_print:
     def __init__(self):
          self.but = Button(root)
          self.but["text"] = "Печать"
          self.but.bind("<Button-1>",self.printer)
          self.but.pack()
     def printer(self,event):
          print ("Как всегда очередной 'Hello World!'")
 
root = Tk()
obj = But_print()
root.mainloop()

Практическая работа

  1. Импортируйте модуль tkinter, создайте объект главного окна, примените к нему метод mainloop. Затем выполните скрипт. Что вы видите?
  2. Добавьте кнопку на главное окно с помощью такой команды:
  3. but = Button(root, text="Печать")
    В данном случае, при создании кнопки, в класс сразу передается и значение свойства text. Это наиболее часто используемый способ установки свойств (по-сравнению с тем, который приводится в уроке: but["text"] = "Печать").

  4. Расположите виджету на главном окне с помощью метода pack. Запустите скрипт. Что вы видите? Нажмите левой кнопкой мыши на кнопку в окне. Что-нибудь происходит?
  5. Создайте какую-нибудь функцию и свяжите ее с событием нажатия кнопки.
  6. Снова запустите скрипт и нажмите кнопку. По идее, должно что-то произойти.

Здравствуйте. Хочу сделать,

Здравствуйте.
Хочу сделать, чтобы при запуске программы на несколько секунд появлялась картинка с логотипом. Подскажите, пожалуйста, как это правильно сделать? Сначала создать окно с картинкой, потом закрыть его, или это все должно содержаться в главном окне? Спасибо!

Здравствуйте. Программирую на

Здравствуйте. Программирую на Qpython3 android. При импорте tkinter пишет ошибку. Скажите пожалуйста почему и как решить проблему.Спасибо.

Скорее всего не установлена

Скорее всего не установлена данная библиотека. Как установить и можно ли вообще не знаю. Попробуйте поискать в маркете.

Что если функция printer

Что если функция printer должна принимать и выводить аргумент? Например,

def printer(word):
     print word

То как в нее передать аргумент при привязке к обработчику кнопки?
Вариант
 but.bind("<Button-1>", printer("Hello")

Не подходит, он вызывает функцию один раз и все

Python 2.6 1.Функция printer

Python 2.6
1.Функция printer будет вызываться не раз, а при каждом событии ''. Сколько раз нажмешь, столько раз функция и вызовится.
2.Чтобы функция приняла аргумент - нужно его указать. Это будет атрибут объекта? тогда, вот такой вариант для примера предлагаю:

# -*- coding: cp1251 -*-  #вот эта строка не помогает 
                          #для надписи на русском на кнопке :(
from Tkinter import *
from random import *  #это для работы генератора случ.чисел - выбора из списка
 
class But_print:
    def __init__(self):
        self.time=['Utro','Deny','Vecher','Noch']#вот наш аттрибут-список, 
                                                 #который будет отражаться 
                                                 #в функции printer
        self.but = Button(root)
        self.but["text"]="print!"
        self.but.bind("<Button-1>",self.printer)
        self.but.pack()
    def printer(self,event):
        print self.time[randint(0,3)]
 
root = Tk()
obj=But_print()
root.mainloop()

Добрый день. Начал изучать

Добрый день.
Начал изучать Python. И создание графического интерфейса. Но столкнулся с проблемой, помогите пожалуйста. Пишу программу в IDLE, выполняется в Python 3.2.3

from tkinter import *
root=Tk()
but=Button(root,text="1")
but.pack()
root.mainloop()

Программа выполняется без ошибок. После закрываю окно, но выполнить программу повторне не получается. Вылазит окно с надписью "The Python Shell window is already executing a command; please wait until it is finished" и в потоке выходит ошибка
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.2/tkinter/__init__.py", line 1402, in __call__
return self.func(*args)
File "/usr/lib/python3.2/idlelib/MultiCall.py", line 166, in handler
r = l[i](event)
File "/usr/lib/python3.2/idlelib/ScriptBinding.py", line 128, in run_module_event
return self._run_module_event(event)
File "/usr/lib/python3.2/idlelib/ScriptBinding.py", line 167, in _run_module_event
interp.runcode(code)
File "/usr/lib/python3.2/idlelib/PyShell.py", line 706, in runcode
self.interp.restart_subprocess()
AttributeError: 'ModifiedInterpreter' object has no attribute 'interp'

Возможно надо просто закрыть

Возможно надо просто закрыть второе окно IDLE, которое появляется при запуске программы.

return

Здравствуйте. Помогите пожалуйста с такой задачей:
функция отображает картинку, ждет ввода текста от пользователя.
введенный текст присваивается переменной "key".
как мне вернуть "key" из функции "showcap"?
чтобы было примерно так: key = showcap()
есть способ обойтись без глобальных переменных?
спасибо.

def showcap():
	def callback(_):
		key = entry.get()
		root.destroy()
 
	root = Tk()
	img = PhotoImage(file = './captcha.gif')
	label = Label(image=img)
	entry = Entry()
	label.pack()
	entry.pack()
	entry.focus()
	root.bind("<Return>", callback)
	root.mainloop()

Ну, а кому принадлежит метод?

Ну, а кому принадлежит метод? вот пусть того класса этот key и будет

class verify()
      self.key
      def showcap()
.......

Может быть нужно использовать

Может быть нужно использовать return в объявлении функции callback?

Наверное можно, но у меня не

Наверное можно, но у меня не получилось. Непонятно, как из callback получить значение.

помогите исправить!

вот моя программка:

from tkinter import*
c = Canvas(width=460,height=100,bg='grey80')
c.pack()
def oval_func(event):
     #c.delete(oval)
     c.create_oval(30,10,100,80,fill="orange",anchor="w")
 
but=Button(c)
but["text"] ="Taster"
but.bind("<Button-1>")
but.pack()
c = Canvas(width=460,height=100,bg='grey80')
c.pack()
oval = c.create_oval(30,10,100,80,fill="black")
 
c.bind(oval,'<Button-1>',oval_func)
 
 
mainloop() 

вкратце расскажу задание, нужно в CUI сделать наподобее лампы с выключателем, то ест с право должен быть круг(черный), а слево должен быть выключатель "кнопка", если на кнопку нажимаешь круг должен стать желтым, т.е лампа должна загореться.Как только с кнопки убираешь , так снова должна потухнуть(круг черным стать)..я только создала круг черный и кнопку, каких распределить правильно и при нажатии кнопки круг должен стать желтым ,как сделать???помогите??пожалуйста??

from tkinter import *   def

from tkinter import *
 
def oval_func(event):
     cv.create_oval(30,10,100,80,fill='orange')
 
def oval_func2(event):
     cv.create_oval(30,10,100,80,fill='black')
 
cv = Canvas(width=150,height=100,bg='grey80')
cv.create_oval(30,10,100,80,fill='black')
cv.pack(side=LEFT)
 
but=Button()
but['text'] ='Taster'
but.pack(side=LEFT)
 
but.bind('<ButtonPress-1>',oval_func)
but.bind('<ButtonRelease-1>',oval_func2)
 
mainloop() 

у меня вторая версия.

у меня вторая версия.

В первой строчке пишите слово

В первой строчке пишите слово tkinter с большой буквы. Вот так:

from Tkinter import *

именно так и писала, результат

именно так и писала, результат - не выводит. Форму выдаёт,а после нажатия кнопки нигде ничего не выводит.

У меня работает. Тыкаешь -

У меня работает. Тыкаешь - желтое, отпускаешь - черное...

from Tkinter import

from Tkinter import *
 
a=1
def oval_func(event):
    global a    
    if a==1:
        cv.create_oval(30,10,100,80,fill='orange')
        a=-1
    else:
        cv.create_oval(30,10,100,80,fill='black')    
        a=1
cv = Canvas(width=150,height=100,bg='grey80')
cv.create_oval(30,10,100,80,fill='black')
cv.pack(side=LEFT)
 
but=Button()
but['text'] ='Taster'
but.pack(side=LEFT)
 
but.bind('<Button-1>',oval_func)
mainloop()

Посмотрите два последних

Посмотрите два последних комментария на этой странице (от 13 июля). Возможно "проблема" именно в этом.

ничего не выводит!!!и

ничего не выводит!!!и никуда!!!В чем косяк?!

У вас версия Python какая?

У вас версия Python какая? 2-я или 3-я?

tkinter? Может быть Tkinter?

tkinter? Может быть Tkinter?

tkinter

Для версий 2.х - Tkinter. А для версий 3.x - tkinter.

Вопросик..? А точно программа работает в первой уроке?

def printer(event):
     print ("Как всегда очередной 'Hello World!'")
 
     # Может так?  but['text']= "Как всегда очередной 'Hello World!'"

Что-то я немного не понял.. Кнопка в вашей версии программы не срабатывает.Или я что-то не могу понять?
Если не понимаю объясните пожалуйста в чем дело.

Функция print осуществляет

Функция print осуществляет вывод в основной поток вывода. Она ничего не выводит на графический интерфейс.

Если у вас Linux, то строка-аргумент функции print отобразится в консоли, откуда был запущен Python, или в IDLE (если используется эта среда программирования).
В Windows - в IDLE.

Можно и так, как предложили вы:

def printer(event):
     but['text']= "Как всегда очередной 'Hello World!'"

В результате чего изменится текст на кнопке.

python

в 2.7 не работает русский текст.
но IDLE стоит с 3.0, поэтому все работает.
еще проблемма: при передвижении окон сильно виснет(не так каак при скомпилировнных приложениях)
и вопрос-есть ли компилятор для python(не интерпретатор, а компилятор)

Есть py2exe, с помощью

Есть py2exe, с помощью которого можно получить exe-файл. Насколько понимаю, для Linux не актуально.

В 2.7 надо указывать кодировку. Попробуйте перед строкой с русскими символами писать английскую u:
variable = u'Привет'

То что виснет, странно. Я такое наблюдала, когда была ошибка в коде.

Есть еще JIT-компиляция

Есть еще JIT-компиляция