Компоновка — начало начал

    В этой статье я расскажу о компоновке элементов интерфейса в PyGTK. Мы будем использовать дизайнер интерфейсов Glade и сделаем первое кросплатформенное приложение на PyGTK.

    Подготовка


    Сперва несколько слов о подготовке Windows-машины: установим всё необходимое для разработки.

    Если у вас не установлен Python, и нет желания скачивать всё по отдельности, качайте полный архив всего, что нужно для Windows (20 Мб), который я залил на Яндекс. Все файлы проверены ClamWin. Ставьте в порядке, описанном ниже:
    • Python: Python 2.5.2 Windows installer. Версию Python я указываю ту, под которую в момент написания статьи есть инсталляторы PyGTK для Windows. Т.е., для беспроблемной установки. Если вы видите, что есть PyGTK под 2.6 или более позднюю версию, скачивайте её.
    • GTK+: скачиваем полную сборку GTK+ для Windows (gtk+-win32-runtime), устанавливаем.
    • Теперь скачиваем и ставим PyCairo, PyGObject и PyGTK для Windows. Прямые ссылки для версии Python 2.5.х: PyCairo, PyGObject, PyGTK
    • Ну, и наконец, Glade. Берём glade-win32, распаковываем (например, C:\GTK\glade). В каталоге bin находится программа, glade-3.exe (до перезагрузки машины она у вас вряд ли заработает)
    После установки всех компонентов перезагрузите машину.

    В Ubuntu нужно поставить пакет glade-3:
    sudo apt-get install glade-3

    Я использую Ubuntu, поэтому все последующие скриншоты процесса разработки сделаны в Ubuntu. Тем не менее, в Windows Glade работает аналогично, никакой разницы нет.

    Горизонтальная и вертикальная


    Есть два основных вида компоновки (деление на 3 области тут сделано для примера, может быть задано произвольное количество областей):
    Горизонтальная Вертикальная


    Чтобы сразу понять, как это работает, посмотрите на картинку с горизонтальной компоновкой, и представьте, что это макет «резинового» сайта. Если вы увеличите размеры окна, области расширятся, и наоборот.

    Промежутки задаются в пикселах, поэтому они всегда остаются одинаковыми.

    Цифры внутри областей являются их порядковыми номерами. Как вы уже поняли, нумерация начинается с нуля и идёт слева направо и сверху вниз.

    Glade


    Glade — это визуальный редактор интерфейсов, он сохраняет дерево элементов в XML файл. Этот XML файл читается программой, и PyGTK создаёт реальные окна и виджеты на экране. Таким образом, с интерфейсом приложения можно работать отдельно от логики. Это правильный подход.

    Запустим GLade (в Windows программа glade-3.exe, о чём я уже писал выше) и попробуем сделать что-то на основе HBox. Для начала добавим окно:



    выберем горизонтальную компоновку:



    оставим количество областей по умолчанию, появится горизонтальная компоновка с 3 областями:



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



    В редакторе свойств «Интервал» задаёт промежутки в пикселах между областями для размещения элементов, «Гомогенность» определяет, будут ли все области одинакового размера, «Число элементов» задаёт количество областей. Оставим всё, как есть.

    Область прокрутки, редактор текста


    У GTK есть такая интересная особенность: если мы в текстовое поле будем добавлять строки, и дойдём до конца видимой области, текстовое поле начнёт увеличиваться по высоте, и в конце концов выйдет за пределы экрана. Чтобы этого не происходило, нужно поместить текстовое поле в область прокрутки. Область прокрутки автоматически покажет скроллы, если текста больше, чем помещается на экране, и уберёт, если меньше.

    Добавим в области 0 и 2 (т.е. в крайние области) область прокрутки:





    в каждую область прокрутки поместим редактор текста:





    Вертикальная группа кнопок


    Теперь в оставшуюся пустой среднюю область добавим ещё один элемент компоновки, вертикальную группу кнопок c 2 элементами:





    Поменяем стиль размещения кнопок на «Рассеивание»:





    так интерфейс выглядит более органично.

    Кнопки, сигналы


    Добавим в каждую ячейку по кнопочке:





    В редакторе свойств кнопки button1 поменяем метку на «Туда ->», а для кнопки button2 на "< — Сюда":





    При нажатии кнопки GTK отправит сигнал. Чтобы получить его и обработать, необходимо дать сигналу имя. Выберем button1 и перейдём на закладку «Сигналы». Назовём сигнал нажатия кнопки button1 «button1_clicked_cb», а кнопки button2 «button2_clicked_cb»:



    В общем-то, почти всё готово, кроме одной мелочи: главное окно не имеет нормального названия, и оно невидимое :-)
    Исправим это, и заодно зададим начальные размеры окна:





    Вот, в общем-то, и всё, первый интерфейс в стиле хабра готов. Сохраним его в файл pygtk001.glade. Расширение glade означает, что это файл в формате glade. Вы можете скачать готовый файл, который сделал я.

    Первая работающая программа


    Интерфейс, который мы создали, может использоваться для каких-то операций с текстом. Например, перевод с одного языка на другой, шифровка и расшифровка и так далее. Интерфейс находится в файле pygtk001.glade, теперь нужно его оживить с помощью кода. Наша программа будет очень умной, она будет уметь перемещать текст туда-сюда :-)
    Код очень простой (проверок нет, т.к. это не «боевая» программа), всего 50 строчек, с комментариями 60:

    #!/usr/bin/env python
    # coding: utf-8
    import sys
    import os
    
    try:
            import pygtk
            pygtk.require('2.0')
    except:
            sys.exit(1)
    try:
            import gtk
            import gtk.glade
    except:
            sys.exit(1)
            
    class App:
    
        def __init__(self):
            # Загружаем файл интерфейса
            self.gladefile = "pygtk001.glade"
            # дерево элементов интерфейса
            self.widgetsTree = gtk.glade.XML(self.gladefile)
            # Словарик, задающий связи событий с функциями-обработчиками
            dic = { 
    		"button1_clicked_cb" : self.text_operation,
                    "button2_clicked_cb": self.text_operation,
    	      }
            # Магическая команда, соединяющая сигналы с обработчиками
            self.widgetsTree.signal_autoconnect(dic)
            # Соединяем событие закрытия окна с функцией завершения приложения
            self.window = self.widgetsTree.get_widget("window1")
            if (self.window):
                self.window.connect("destroy", self.close_app)
            # А это уже логика приложения. Задём маршруты обработки текста для каждой кнопки.
            # Первый элемент - имя виджета-источника текста, второй - имя виджета-получателя  
            self.routes = {'button1': ('textview1','textview2'),
            	       'button2': ('textview2','textview1')}
    
        def text_operation(self,widget):
            "Функция, которая перебрасывает текст туда-сюда"
            # виджет-источник
        	source = self.widgetsTree.get_widget(self.routes[widget.name][0])
            # виджет-получатель
    	destination = self.widgetsTree.get_widget(self.routes[widget.name][1])
            # текстовый буфер источника
    	source_text_buffer = source.get_buffer()
            # массив итераторов границ текста в текстовом буфере источника (начало и конец)
            source_text_buffer_bounds = source_text_buffer.get_bounds()
            # собственно текст
    	source_text = source_text_buffer.get_text(source_text_buffer_bounds[0],
                                                      source_text_buffer_bounds[1])
            # устанавливаем текст в текстовом буфере виджета-получателя
            destination.get_buffer().set_text(source_text)
            # очищаем текстовый буфер источника
            source_text_buffer.set_text('')
               
        def close_app(self, widget):	
            gtk.main_quit()        
        
    if __name__ == "__main__":
        app = App()
        gtk.main()
    

    Скачать файл исходников.

    Запускаем под Ubuntu:



    Запускаем под Windows:


    (у меня немного отрегулированы размеры шрифтов в Windows, поэтому немножко нестандартно)

    Итоги


    Мы немножко узнали о том, какие виды компоновок есть в PyGTK, сделали простой GUI с помощью Glade, и запустили его под Ubuntu и Windows XP. Всё работает, как положено :-)

    В следующих статьях мы продолжим знакомство с PyGTK, жду ваших отзывов.
    Метки:
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 25
    • 0
      Спасибо! Для начала самое то.
      У меня был опыт использования Qt и WxWidgets, поэтому интересуют также и другие способы кроссплатформенного программирования.
      • +1
        Извините, у меня такой вопрос, почему import pygtk и import gtk, находятся в разных try блоках? Ведь вы явно не указываете на тип обрабатываемых исключений в этих блоках, а обработчик у вас тот-же самый, думаю имеет смысл объединить все в один блок. Правда я бы вообще не обрабатывал такое исключение, поскольку бы программа и так бы вылетела с ошибкой ImportEror: No module named…

        • 0
          В следующей статье помещу в один блок :-)
          • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              ОК, в следующей статье уберу try блок :-)
        • 0
          спасибо за блог, давно хотел научиться писать хорошие guiшки на питоне
          • 0
            Большое спасибо за блог и этот пост. Повторил все шаги — получилось на ура. Только вот сначала был озадачен разницей внешнего вида glade в ubuntu. Оказалось их несколько и надо ставить пакет glade-3
            • 0
              Разве он не установлен по умолчанию?
              • 0
                Нет его по умолчанию ни в 8.04, ни в 8.10
                • 0
                  Спасибо, добавил в статью этот момент.
            • 0
              Присоединяюсь к благодарностям.
            • НЛО прилетело и опубликовало эту надпись здесь
              • +1
                Спасибо! Да, есть такое за мной — никак не привыкну к python-naming. Привык на C++ писать, никак не отвыкну. Кстати, как правильно? Чтобы запомнить раз и навсегда :-)

                Да, по поводу source_text_buffer — ну что тут сказать. У меня такая теория, что главное, чтобы было понятно программеру, поэтому я не боюсь длинных названий. М.б. это плохо, но я много раз убеждался на своём опыте, читая старый код, что мне так удобнее, потому что сразу читается смысл. Мнемоничнее. Наверное, дело вкуса :-)
                • НЛО прилетело и опубликовало эту надпись здесь
                  • 0
                    Спасибо, обязательно запомню!
                    Нужно pep-ы поштудировать. Эх, времени бы ещё где-то взять :-) Ничего, прорвёмся :-)
                    • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              спасибо, было бы неплохо увидеть это все без использования glade ;)

              ps: с нетерпением ждем продолжения
              • +1
                Без glade тоже будет код, потому что не всё можно сделать с glade.

                Постараюсь на этой неделе написать продолжение, большие проблемы с временем, наверное, буду строчек по 20-30 каждый день в свободных «окнах» писать, в конце недели выкладывать статьёй.
              • 0
                Вот вовремя я нашел этот блог, мне как раз надо написать кроссплатформенную прогу на питоне с использование этой библиотеки, Спасибо огромное, жду продолжения!!!
                • 0
                  Ну, теперь уж продолжение только в 2009 году :-)
                  Было очень много дел (да их и сейчас не меньше), так что никак не получилось написать. Думаю, в начале января продолжу :-)
                • 0
                  чтобы программка запускалась без консоли на заднем фоне нужно расширение файла сменить с .py на .pyw
                  • 0
                    ой, а у меня не запускается :(
                    maksymov@maksymov-ubuntu:~$ python pygtk001.py

                    (pygtk001.py:18333): libglade-WARNING **: Expected <glade-interface>. Got.

                    (pygtk001.py:18333): libglade-WARNING **: did not finish in PARSER_FINISH state
                    Traceback (most recent call last):
                    File «pygtk001.py», line 62, in app = App()
                    File «pygtk001.py», line 23, in __init__
                    self.widgetsTree = gtk.glade.XML(self.gladefile)
                    RuntimeError: could not create GladeXML object
                    • 0
                      В настройках проекта в Glade необходимо выбрать формат libglade.

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