Введение в pygtk/gtkbuilder: пишем калькулятор

    Разберем создание интерфейса на pygtk на примере самого примитивного калькулятора. Много картинок, немного кода.
    gtkbuilder наиболее прогрессивный формат описания gtk интерфейса в xml,
    если вы ранее использовали libglade, вы можете сконфертировать .glade файл в новый формат командой libglade-convert

    Всё это может работать под windows, вам нужно установить pygtk и все нужные библиотеки; в дальнейшем, вы сможете упаковывать всё с помощью py2exe.
    Запускаем glade-3

    Создаем окно, помещаем в него таблицу

    В верхнюю левую ячейку вставляем Entry, в packing выставляем right
    attachment-4, чтобы растянуть её на 4 колонки
    В general выставляем Editable: No


    Для window1 в signals вводим в key-press-event «key_press»;
    в destroy — «quit»(чтобы при закрытии окна, мы выходили из программы)
    key_press и quit это название методов в нашем коде, которые будут
    вызываться при совершении определенных действий, в данном случае — нажатию кнопки и закрытии окна.

    Добавляем кнопочки

    Остальные мы сгенерируем в коде.
    Для всех кнопок, кроме "=" и сброса выставляем signals/clicked «put_text»
    Для "=" — «calculate», для сброса — «reset»

    Выставляем common/accelerators для кнопочек, чтобы clicked у нас вызывался
    при нажатии соотв. клавиш, для "=" это будет "=" и Return, для сброса не
    выставляем ничего(мы хотим Escape и сделаем это в коде)

    Сохраняем в файл demo.ui
    Пишем код

    Если возникают вопросы — запускаем «devhelp» и читаем документацию


    Обратите внимание на EntryDescriptor — это питоновский дескриптор, который
    позволяет нам гораздо удобнее работать со значениями в gtk.Entry

    Остальное должно быть понятно из комментариев

    Примечание: калькулятор работает с целыми числами и целочисленным делением,
    т.е. 5/2 = 2:) Это статья про создание интерфейса, всё остальное я сделал
    максимально просто, чтобы не отвлекало.

    #!/usr/bin/env python
    # coding: utf-8
    # vim: ai ts=4 sts=4 et sw=4
    
    import gtk
    import os
    
    class EntryDescriptor(object):
        def __init__(self, object_name):
            self.object_name = object_name
        def __get__(self, obj, cls):
            return obj.get_object(self.object_name).get_text()
        def __set__(self, obj, value):
            obj.get_object(self.object_name).set_text(value)
    
    
    class Calculator(gtk.Builder):
        def __init__(self):
            super(Calculator, self).__init__()
            # загружаем demo.ui
            self.add_from_file(os.path.join(os.path.dirname(__file__),'demo.ui'))
            # подключаем обработчики сигналов, описанные в demo.ui к объекту self
            self.connect_signals(self)
            # создаем группу горячих клавишь, для клавиш с цифрами и подключаем её к окну
            agroup = gtk.AccelGroup()
            self.window1.add_accel_group(agroup)
            # создаем кнопочки, вешаем на них горячии клавиши и помещаем их в table1
            for i in xrange(10):
                btn = gtk.Button(str(i))
                btn.connect('clicked', self.put_text)
                btn.add_accelerator('clicked', agroup, ord(str(i)), 0, 0)
                y, x = i / 3, i % 3
                self.table1.attach(btn, x, x+1, y+1, y+2)
            # показываем окно и все виджеты на нем
            self.window1.show_all()
    
        def __getattr__(self, attr):
            # удобней писать self.window1, чем self.get_object('window1')
            obj = self.get_object(attr)
            if not obj:
                raise AttributeError('object %r has no attribute %r' % (self,attr))
            setattr(self, attr, obj)
            return obj
    
        # питоновский дескриптор, который позволяет нам гораздо удобнее работать со значениями в gtk.Entry
        expr = EntryDescriptor('entry1')
        
        def calculate(self, widget=None):
            if not self.expr: return
            try:
                self.expr = str(eval(self.expr))
            except Exception, e:
                # мы можем заделить на ноль и т.п.
                print e
    
        def reset(self, widget):
            self.expr = ''
    
        def quit(self, widget):
            gtk.main_quit()
    
        def put_text(self, widget):
            text = widget.get_label()
            expr = self.expr
            if not expr[-1:].isdigit() and not text.isdigit():
                # чтобы нельзя было написать 8/*2 и т.п.
                return
            self.expr += text
    
        def key_press(self, widget, event):
            # получаем название кнопки из её кода
            key = gtk.gdk.keyval_name(event.keyval)
            if key == 'BackSpace':
                if self.expr:
                    self.expr = self.expr[:-1]
            elif key == 'Escape':
                self.reset(None)
    
    if __name__ == '__main__':
        calculator = Calculator()
        gtk.main()
    


    demo.py
    demo.ui

    Запускаем python demo.py:


    Если тема интересна, в следующей статье я думаю описать создание браузера на базе pygtk и pywebkitgtk, для которого можно писать расширения на python в т.ч. в интерактивной консоли(ipython); интеграцией python и javascript.
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 18
    • +2
      Статья отличная, как раз для блога PyGTK :-)
      • +1
        Сказать, что интересно — ничего сказать. Пишите еще, с нетерпение… Мне это очень актуально.
        Спасибо.
        • 0
          Усложненный аналог Hello World. В хорошем смысле. Особенно полезно когда учишь новый язык сделать что-то простое, а заодно в процессе разобраться с кодом.
          • 0
            свойства лучше так оформлять. Через декораторы.
            • 0
              где там свойства?
              • 0
                class Calculator(gtk.Builder):?
                • 0
                  хм, это класс-наследник gtk.Builder. причем тут свойства?
            • 0
              Кстати, попутно вопрос, что вы считаете удобней для построения интерфеса кьют или гтк всетаки?
              • 0
                Интерфейс строить плюс/минус одинаково удобно и там и там.
                • 0
                  да, на самом деле очень похоже. раньше ещё вопрос лицензий стоял. если нужна поддержка macos, то однозначно лучше qt/pyside
                  • 0
                    GTK+ и под Windows не очень гладко выглядит.
                • 0
                  Плюс! Пишите, я как раз подумываю написать плагинчик под pygtk. Ваша статья пришлась крайне кстати, спасибо!
                  • 0
                    Жду статью про создание браузера и интеграцию с javascript :)
                    • +1
                      Ага. Я тоже обожаю присать калькулятор на новом языке.
                      Отличная разминка.

                      Тут калькуляторы для Mac и iPhone.
                      • 0
                        вот это я понимаю, статья так статья, где там мои плюсики… главное не останавливаться на сделанном, вы обещали новую статью, мы помним ;)
                        • 0
                          [offtopic]А можно увидеть обоину? :) [/offtopic]
                          • 0
                            Спасибо! Наглядно=)
                            • 0
                              Спасибо, было бы хорошо прочитать продолжение :)

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