Пользователь
0,0
рейтинг
27 ноября 2011 в 13:05

Разработка → Введение в Tkinter из песочницы

image

Всем доброго времени суток!

Tkinter – это кроссплатформенная библиотека для разработки графического интерфейса на языке Python (начиная с Python 3.0 переименована в tkinter). Tkinter расшифровывается как Tk interface, и является интерфейсом к Tcl/Tk.
Tkinter входит в стандартный дистрибутив Python.

Весь код в этой статье написан для Python 2.x.
Чтобы убедиться, что Tkinter установлен и работает, воспользуемся стандартной функцией Tkinter _test():

import Tkinter
Tkinter._test()

После выполнения данного кода должно появиться следующее окно:



Отлично, теперь можно приступать к написанию нескольких простых программ для демонстрации основных принципов Tkinter.

Hello world


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

from Tkinter import *
root = Tk()

Да-да, всего одна строка, это вам не WinAPI (=. Теперь создадим кнопку, при нажатии на которую будет выводиться текст в консоль:

def Hello(event):
    print "Yet another hello world"

btn = Button(root,                  #родительское окно
             text="Click me",       #надпись на кнопке
             width=30,height=5,     #ширина и высота
             bg="white",fg="black") #цвет фона и надписи
btn.bind("<Button-1>", Hello)       #при нажатии ЛКМ на кнопку вызывается функция Hello
btn.pack()                          #расположить кнопку на главном окне
root.mainloop()

Всё просто, не так ли? Создаём экземпляр класса Button, указываем родителя и при желании список параметров. Есть еще немало параметров, таких как шрифт, толщина рамки и т.д.
Затем привязываем к нажатию на кнопку событие (можно привязать несколько разных событий в зависимости, например, от того, какой кнопкой мыши был нажат наш btn.
mainloop() запускает цикл обработки событий; пока мы не вызовем эту функцию, наше окно не будет реагировать на внешние раздражители.

Упаковщики

Функция pack() — это так называемый упаковщик, или менеджер расположения. Он отвечает за то, как виджеты будут располагаться на главном окне. Для каждого виджета нужно вызвать метод упаковщика, иначе он не будет отображён. Всего упаковщиков три:

pack(). Автоматически размещает виджеты в родительском окне. Имеет параметры side, fill, expand. Пример:

from Tkinter import *
root = Tk()
Button(root, text = '1').pack(side = 'left')
Button(root, text = '2').pack(side = 'top')
Button(root, text = '3').pack(side = 'right')
Button(root, text = '4').pack(side = 'bottom')
Button(root, text = '5').pack(fill = 'both')
root.mainloop()



grid(). Размещает виджеты на сетке. Основные параметры: row/column – строка/столбец в сетке, rowspan/columnspan – сколько строк/столбцов занимает виджет. Пример:

from Tkinter import *
root = Tk()
Button(root, text = '1').grid(row = 1, column = 1)
Button(root, text = '2').grid(row = 1, column = 2)
Button(root, text = '__3__').grid(row = 2, column = 1, columnspan = 2)
root.mainloop()



place(). Позволяет размещать виджеты в указанных координатах с указанными размерами.
Основные параметры: x, y, width, height. Пример:

from Tkinter import *
root = Tk()
Button(root, text = '1').place(x = 10, y = 10, width = 30)
Button(root, text = '2').place(x = 45, y = 20, height = 15)
Button(root, text = '__3__').place(x = 20, y = 40)
root.mainloop()



Теперь для демонстрации других возможностей Tkinter, напишем простейший

Текстовый редактор


Без лишних слов приведу код:

from Tkinter import *
import tkFileDialog

def Quit(ev):
    global root
    root.destroy()
    
def LoadFile(ev): 
    fn = tkFileDialog.Open(root, filetypes = [('*.txt files', '.txt')]).show()
    if fn == '':
        return
    textbox.delete('1.0', 'end') 
    textbox.insert('1.0', open(fn, 'rt').read())
    
def SaveFile(ev):
    fn = tkFileDialog.SaveAs(root, filetypes = [('*.txt files', '.txt')]).show()
    if fn == '':
        return
    if not fn.endswith(".txt"):
        fn+=".txt"
    open(fn, 'wt').write(textbox.get('1.0', 'end'))

root = Tk()

panelFrame = Frame(root, height = 60, bg = 'gray')
textFrame = Frame(root, height = 340, width = 600)

panelFrame.pack(side = 'top', fill = 'x')
textFrame.pack(side = 'bottom', fill = 'both', expand = 1)

textbox = Text(textFrame, font='Arial 14', wrap='word')
scrollbar = Scrollbar(textFrame)

scrollbar['command'] = textbox.yview
textbox['yscrollcommand'] = scrollbar.set

textbox.pack(side = 'left', fill = 'both', expand = 1)
scrollbar.pack(side = 'right', fill = 'y')

loadBtn = Button(panelFrame, text = 'Load')
saveBtn = Button(panelFrame, text = 'Save')
quitBtn = Button(panelFrame, text = 'Quit')

loadBtn.bind("<Button-1>", LoadFile)
saveBtn.bind("<Button-1>", SaveFile)
quitBtn.bind("<Button-1>", Quit)

loadBtn.place(x = 10, y = 10, width = 40, height = 40)
saveBtn.place(x = 60, y = 10, width = 40, height = 40)
quitBtn.place(x = 110, y = 10, width = 40, height = 40)

root.mainloop()

Здесь есть несколько новых моментов.

Во-первых, мы подключили модуль tkFileDialog для диалогов открытия/закрытия файла. Использовать их просто: нужно создать объект типа Open или SaveAs, при желании задав параметр filetypes, и вызвать его метод show(). Метод вернёт строку с именем файла или пустую строку, если пользователь просто закрыл диалог.

Во-вторых, мы создали два фрейма. Фрейм предназначен для группировки других виджетов. Один содержит управляющие кнопки, а другой — поле для ввода текста и полосу прокрутки.
Это сделано, чтобы textbox не налезал на кнопки и всегда был максимального размера.

В-третьих, появился виджет Text. Мы его создали с параметром wrap='word', чтобы текст переносился по словам. Основные методы Text: get, insert, delete. Get и delete принимают начальный и конечный индексы. Индекс — это строка вида 'x.y', где x — номер символа в строке, а y — номер строки, причём символы нумеруются с 1, а строки — с 0. То есть на самое начала текста указывает индекс '1.0'. Для обозначения конца текста есть индекс 'end'. Также допустимы конструкции вида '1.end'.

B в-четвёртых, мы создали полосу прокрутки (Scrollbar). После создания её нужно связать с нужным виджетом, в данном случае, с textbox. Связывание двустороннее:
scrollbar['command'] = textbox.yview
textbox['yscrollcommand'] = scrollbar.set

Вот и всё. Tkinter – это, безусловно, мощная и удобная библиотека. Мы осветили не все её возможности, остальные — тема дальнейших статей.

Полезные ссылки:
http://ru.wikiversity.org
http://www.pythonware.com/
Антон @t3ns0r
карма
15,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (44)

  • +3
    Такой вопрос, для такой либы есть какой-нить гуи, чтобы не ручками контролы расставлять?
    • 0
      На сколько я знаю, нет.
      • +1
        *Насколько
    • +3
      посмотрите на Rapyd-Tk
      • 0
        Пользовался для своих нужд. Отлично работает.
    • +1
      Qt + PySide/PyQt. У Qt есть неплохой Designer, в котором как раз можно нарисовать интерфейс из стандартных компонентов. Потом с помощью простых командных утилит файлы дизайнера компилируються в .py файлы который потом легко подключаются к проекту. Презентация о том как это делаться в PyQt. (В PySide все также, только по другому называется консольная команда.)
  • 0
    А как сделать чтобы виджеты поддерживали текущую тему Windows?
    • +2
      Можно использовать стандартный модуль ttk, например, так:

      from Tkinter import *
      import ttk
      
      root = Tk()
      b = ttk.Button(root)
      b.pack()
      root.mainloop()
      


      Тогда виджеты выглядят более естественно.
      • 0
        а в Python 3?
        • 0
          from tkinter import *
          from tkinter.ttk import *
          
          root = Tk()
          b = Button(root)
          b.pack()
          root.mainloop()
          
          • 0
            спасибо
        • +1
          Вот так:

          import tkinter
          from tkinter import ttk
          root = tkinter.Tk()
          button = ttk.Button(root)
          button.pack()
          root.mainloop()
          • 0
            Не успел =)
      • 0
        Не совсем понимаю как можно привязать тему к действующему примеру.

        Вот спрашивал на stackoverflow.com и вообще не ясно stackoverflow.com/questions/28551948/tkinter-look-theme-in-linux/28552061
  • +5
    Действительно, тикль очень древнее и чуть ли не единственное средство для того, чтобы быстренько заскриптовать какой-нибудь простенький и страшненький гуй.

    Но, положа руку на сердце, кто из здесь присутствующих видел/писал/использовал что-либо, написанное при помощи этого?

    За исключением тех, кто ставил SCO Unix и ранние Solaris x86 десятки лет назад :)
    • 0
      Естественно wxPython или PySide более подходят для создания сложных и красивых интерфейсов, но у tk есть один большой плюс, он входит в стандартную библиотеку. А значит лучше всего подходит для несложных GUI при отсутствии сторонних зависимостей
      • 0
        Осмелюсь возразить, вернее — уточнить: в стандартную поставку windows-установщика. А вот в линуксе, например, всё уже не так весело. Поддержка python-tk да и либы от Tcl/Tk по-умолчанию не ставятся…
        • 0
          Зато на маке python поставляется вместе с осью и с необходимыми библиотеками, такие как тикли, easy_install и прочее. Я был удивлен, когда на линуксе мне пришлось доустанавливать тот же easy_install
        • 0
          У вас дистрибутив deb-семейства? Там вроде бы действительно по-умолчанию не ставятся.

          В Gentoo если указан USE-флаг tkinter (вроде так) – будет питон с поддержкой tkinter. Тоесть я хочу сказать, что это вопрос сборки, а в исходниках питон должен иметь поддержку tkinter для Windows, Linux и Mac.

          P.S. Статья интересная. Спасибо!
          • 0
            Угу. Дебиан/Убунту/Минт.

            Никто из них по-умолчанию не ставит не только tkinter, но и libtcl и т.п. Зато, вроде бы, минт ставит Qt/PyQt ;)

            Вопрос: а в генте этот флаг где-нибудь по-умолчанию предполагается? Если нет, то выходит то же самое — ставьте сами :)
            • 0
              Насколько я знаю по-умолчанию он есть. Нашел – называется tk. Поскольку я его всегда явно указывал даже мне стало интересно включен ли он по-умолчанию :)
      • 0
        сторонние зависимости не здесь, так там возникнут, от них сложно деться.
    • +1
      Я писал для лабы гуи тк для машинки тьюринга.
    • 0
      Когда-то пользовался Tkabber
    • –1
      В сочетании с ttk, получается достаточно симпатичный GUI. Использовал в пару популярных относительно популярных проектах под win.
    • 0
      Я тиклем постоянно пользуюсь. И Tk тоже. То, что он по дефолту слегка несовременно выглядит, не делает его ничуть хуже.
    • 0
      Кстати, в этой статье тикля собственно-то и нет. Здесь есть только Tk.
    • –2
      К слову можно создать красивый интерфейс путем использования графических изображений. Нарисовать фон, графические объемные кнопки. Вот тут показано как использовать графическую кнопку www.daniweb.com/software-development/python/code/216852
    • 0
      gitk, git-gui
    • 0
      Не только видел, использовал, писал, но и прямо сейчас пишу. Вообще, эта статья — отличный пример почему гуи (и не только) лучше всё-же писать на Tcl/Tk, а не на Python/Tk (известном как tkinter). (Извините, позволил себе немного избавить код от дублирования и использовать стили ttk, которые в tkinter тоже есть)

      pastebin.com/nz4LJQup

      Но это всё игрушки. Весело было на Tcl (без Tk) многопоточный сервер писать. :3
    • 0
      Вот ответ www.slideshare.net/r1chardj0n3s/tkinter-does-not-suck

      Он прост и умеет достаточно многое.
  • 0
    вот этот ресурс мне весьма помог, когда делал гуи к лабе
  • +1
    Большое спасибо автору, фактически это единственная статья в рунете, которая легким и доступным способом описывает tk. У меня как раз были проблемы с пониманием grid, так как в англоязычных ресурсах как-то более запутано написано.
    • 0
      Пожалуйста, рад, что помог.
  • 0
    На сколько же избыточным выглядит код на Tkinter по сравнению с Tcl/Tk.
    • 0
      Тут, пожалуй не в библиотеке, а в самом языке дело.

      Написал я как-то скриптик на двести строк на Tcl, знакомый фанатик переписал его функционально (не построчно) на Python. Потом спрашиваем у знакомого тоже фанатика, но уже ПЕРЛА, какой из вариантов (Tcl или Python) ему проще читать. Победил Tcl. :)
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Где же вы были около недели назад? :)
    • +2
      Ждал, пока статья пройдёт модерацию (=
      • 0
        Долго как-то. У меня за полтора дня. Правда я её правлю еще. :)
      • 0
        В любом случае спасибо за статью. Нашёл информацию в ней для себя очень полезной.
  • 0
    Да, за статью спасибо, мне, на первый взгляд, библиотека понравилась, на досуге поэксперементирую обязательно.
  • 0
    Я занес эту статью в избранное. Сейчас вернулся к ней. В примере про текстовой редактор есть баг. Если нажать на кнопку Quit, то программа не закрывается, а зависает. Я погуглил. Правильный пример закрытия:
    def quit()
        global root
        root.destroy()
    

    Вот так работает без бага.
    • 0
      Спасибо, исправил.

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