Для Python существует множество библиотек для создания графического интерфейса пользователя (GUI). Здесь будет рассмотрена только одна -- Tkinter. Это привязка Python к Tcl/Tk. Она поставляется вместе с Python. Для построения графических интерфейсов частенько используют построители (Builders), но мы рассмотрим "ручной" вариант GUI-программирования: он поможет лучше уяснить принципы работы графических приложений.
Почти все современные графические интерфейсы общего назначения строятся по модели WIMP - Window, Icon, Menu, Pointer (окно, иконка, меню, курсор [обычно мыши]). Внутри окон рисуются элементы графического интерфейса, именуемые "виджетами" (widget - штучка).
Вот лишь некоторые виджеты из Tcl/Tk:
ToplevelButtonCanvasCheckbuttonEntryFrameLabelListboxMenuMenubuttonMessageLabel, но позволяет заворачивать длинные строки и легко меняет свой размер RadiobuttonScaleScrollbarTextПримеры виджетов (порождены этой программой)

Рассмотрим подробнее следующую программу:
from Tkinter import *
import math
def Square(radius):
return math.pi * radius**2
def calculate_square():
radius = float(radius_entry.get())
try:
square = "%11.3f" % Square(radius)
except:
square = "?"
square_label.configure(text=square)
root = Tk()
root.title("Площадь круга")
frame = Frame(root)
frame.pack()
radius_entry = Entry(frame, width=10)
radius_entry.grid(row=0, column=0)
square_label = Label(frame, text="?")
square_label.grid(row=0, column=1)
eval_button = Button(frame, text="Calculate", width=10,
command=calculate_square)
eval_button.grid(row=1, column=0)
exit_button = Button(frame, text="Exit", width=10,
command=root.destroy)
exit_button.grid(row=1, column=1)
root.mainloop()
Результаты работы этой программы:

Заметьте в примере выше способ вызова функции для обработки
собятия нажатие на кнопку: он задается именованным
аргументом command. Аналогично кнопка
exit_button выполняет закрытие окна (и всего приложения),
так как ей задан метод destroy объекта root.
Окно графического приложения состоит из вложенных друг в друга виджетов. Для примера выше дерево виджетов выглядит так:

Расположением виджетов управляют менеджеры расположения. В Tkinter их три разновидности:
packgridplaceВ основном GUI-приложения состоят из двух фаз: (I) фазы генерации интерфейса и (II) фазы цикла обработки событий. На фазе генерации интерфейса каждый виджет создается (при этом возможно задание некоторых аргументов); прикрепляется одним из указанных трех методов к своему хозяину. Виджеты появляются на экране только в результате прикрепления к уже прикрепленным виджетам. Для запуска фазы II используется метод mainloop() Toplevel-виджета. На второй фазе изменение свойств виджетов производится с помощью метода configure().
Каждый виджет может обрабатывать возникающие в нем события: движения курсора мыши, ввод с клавиатуры и т.п. Основные события в Tkinter:
KeyPressKeyReleaseButtonPressButtonReleaseMotionEnterLeaveMouseWheelVisibilityFocusInFocusOutReparentDestroyActivateDeactivateОписание события задается строкой (часть элементов может быть опущена):
<модификаторы-тип-детализация>
Например,
Пример программы, в которой текстовое поле перехватывает движения мыши и пишет атрибуты события (event):
from Tkinter import *
tk = Tk()
txt = Text(tk)
txt.pack()
def give_info(event):
# event.widget - виджет, в котором произошло событие
txt.delete("1.0", END)
items = event.__dict__.items()
items.sort()
for k, v in items:
txt.insert(END, "%s: %s\n" % (k, v))
txt.bind("<Motion>", give_info)
tk.mainloop()
Результат:

Конечно, кажды виджет имеет большое количество всевозможных
параметров, которые можно задавать и затем изменять.
(Например, так мы изменяли текст в этикетке:
Для удобства связи между виджетами применяются специальные
переменные (они бывают четырех типов:
BooleanVar,
StringVar,
FloatVar,
IntegerVar -- по представляемым ими типам.
Особенность этих переменных в том, что использующие их виджеты могут изменять свое состояние в зависимости от этих переменных и, наоборот, переменные могут изменять состояние в зависимости от изменения состояния виджетов под действием пользователя графического интерфейса.
Следующая программа dclock.py иллюстрирует работу переменной, в результате чего мы получаем "электронные часы":

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