Пользователь
0,0
рейтинг
15 ноября 2008 в 21:42

Разработка → Программирование на PyQt4. Часть 1

Qt*
Данный цикл статей является работой одного очень креативного и умного человека с ником Liksys. Благодаря хорошим людям он получил инвайт и продолжение этого цикла статей будет безусловно! ;)

image

Часть №1


       Когда люди говорят о Qt, многим из нас сразу вспоминается KDE с его обилием настроек. Программисты следом представляют исходники, написанные на C++ с весьма изящным подходом к решению проблемы. И это вполне оправданно: KDE — это, пожалуй, самый известный Qt-проект, а сама Qt написана на C++ и предназначена в первую очередь именно для него. За долгое время существования этого инструментария он стал своеобразным стандартом в Linux для написания графических приложений наряду с GTK, wxWidgets и т.д. Мощь языка C++ дала возможность создать много отличных программ, а стиль Qt является образцом для подражания многих программистов.

       Но не все так просто. Ирония заключается в том, что навороченность и функциональность C++ для конечных программ очень часто избыточна. Для написания небольшого приложения приходится выполнять очень много действий, да и использование в коде указателей и прочих «наворотов» C++ наряду со средствами Qt выглядит не очень хорошо. Ведь не всегда программа по сложности сравнима с тем же KDE, который использует все возможности Qt (ему, кстати, их мало, и KDE`шники написали много расширений). Не забудем еще то время, которое тратится на компиляцию программы — из-за этого сильно снижается продуктивность работы.
       Однако в мире OpenSource всегда найдется альтернатива, и тут она тоже есть. Это Python. Python, в отличие от C++, гораздо более прост в изучении, обладает интуитивным и логичным синтаксисом, а его динамическая типизация, автоматическое управление памятью и богатый набор встроенных высокоуровневых типов позволяют писать весьма эффективный и компактный код. Сочетание же Python и Qt4 дает возможность быстро создавать удобные приложения
с графическим интерфейсом.
       Еще одно неоспоримое приемущество Python — его реализация. Можно подумать, что Python — интерпретируемый язык, но это не совсем так. При запуске программы создаются файлы ".pyc"
используемых модулей — это откомпилированный байт-код Python. Компиляция в бай-код происходит автоматически (по возможности) и занимает очень мало времени, в отличие от компиляции в исполняемые файлы с C++ — можно заменить пару строчек и сразу запустить программу — не надо дожидаться окончания сборки программы, все происходит абсолютно незаметно. Это очень удобно
для программиста.
        И наконец, вопрос скорости. Python работает достаточно быстро, поэтому пользователь даже не замечает разницы, а если все-таки хочется ускорить программу, можно применить модуль Psyco — он включает JIT-компиляцию, и производительность программы, выполняющей много вычислений, сразу возрастает.
       Если вам некоторые из всех этих терминов непонятны — не огорчайтесь, по мере чтения я все-все вам объясню. Итак, давайте приступим.
       Мы будем использовать Qt4, потому что она все-таки скоро вытеснит Qt3, да и имеет по сравнению с ней много нововведений, и писать программы гораздо более приятно.
       Реализация Qt4 для Python называется PyQt4 (логично, не так ли?) и производится компанией Riverbank. Распространяется она таким же образом, как и Qt4: по проприетарной лицензии и по GPL. Скачать последню версию можно обычно из репозитория вышего дистрибутива, но если там ее не оказалось, то это можно сделать на сайте www.riverbankcomputing.co.uk. Существуют реализации PyQt4 не только для Linux, но и для MacOSX, Windows. Я, например, часто
пишу программы на Python для Windows (хоть это мне и не нравится, но никого это не волнует). Программы, написаные на Python и Qt4 пересноимы — их легко можно запустить на другой платформе
даже без перекомпиляции!
        PyQt4 предствляет собой «обертку» к библиотеке Qt4, выполненном с помощью SIP — инструментария для создания привязок к библиотекам. Поэтому для работы PyQt4 необходима сама Qt4. Ее так же можно установить из репозитория или с сайта компании Trolltech: www.trolltech.com.
       Установка PyQt4 не должна вызвать трудностей, даже если вы устанавливаете из исходных текстов. Однако я все таки рекомендовал бы поискать в репозиториях вашего дистрибутива.
       После установки можно сразу приступить к созданию программ. Думаю, что я уже вас достаточно раззадорил, поэтому давайте напишем парочку простых программ — одну на C++, а вторую — на Python, имспользуя Qt4. Заодно и сравним легкость написания, чтобы мои заявления не выглядели голословными.
       Начнем с C++. Будем работать в консоли, поэтому вам, как настоящему джигиту, необходимо уметь ее обуздать. Типичные действия такие — создать каталог проекта, создать файлы исходных текстов,
создать проектный файл Qt, создать из него Makefile (файл-сценарий для GNU make) и запустить сборку. Затем, если ваши мольбы к небесам были услышаны, вы получите готовый исполняемых файл с именем, как у каталога вашего проекта. Описание выглядит жутковато (я уже не говорю о том, как все это состыковать с файлами, созданными autotools, но это к делу не относится). Итак, открываем консоль.

	[liksys@max ~]$ mkdir helloqt
	[liksys@max ~]$ cd helloqt
	[liksys@max helloqt]$ cat > main.cpp
	#include <QApplication>
	#include <QLabel>
	int main(int argc, char **argv)
	{
		QApplication app(argc, argv);
		QLabel *label = new QLabel("Hello, Qt4!");
		label->show();
		return app.exec();
	}
	<Ctrl+D>
	[liksys@max helloqt]$ qmake-qt4 -project
	[liksys@max helloqt]$ qmake-qt4
	[liksys@max helloqt]$ make
	-Тут идут сообщения компилятора, надеюсь, все прошло успешно-
	[liksys@max helloqt]$ ./helloqt

Вот и наше первое приложение на Qt4. Если вы получили сообщения в духе:

	main.cpp:1:24: error: QApplication: Нет такого файла или каталога
	main.cpp:2:18: error: QLabel: Нет такого файла или каталога
	main.cpp: In function ‘int main(int, char**)’:
	main.cpp:5: ошибка: нет декларации ‘QApplication’ в этой области видимости
	...
	


       то вы использовали утилиты от Qt3, а не от Qt4. Поэтому уточните пути к ним и попробуйте еще раз и используйте qmake-qt4, чем просто qmake (это скорее всего принадлежит к Qt3).
       Процесс немного страшноват, но теперь успокоимся и напишем то же самое на Python. Нам необходимо знать только одно — путь к интерпретатору Python, это можно сделать с помощью команды which. Перейдя в
домашний каталог, сделаем следующее:

	[liksys@max helloqt]$ which python
	/usr/bin/python
	[liksys@max ~]$ mkdir hellopyqt
	[liksys@max ~]$ cd hellopyqt
	[liksys@max hellopyqt]$ cat > hellopyqt
	#!/usr/bin/python
	from PyQt4 import Qt
	import sys
	if __name__ == "__main__" :
		app = Qt.QApplication(sys.argv)
		label = Qt.QLabel("Hello, PyQt4!")
		label.show()
		app.exec_()
	[liksys@max hellopyqt]$ chmod +x hellopyqt
	[liksys@max hellopyqt]$ ./hellopyqt


       Как видно, в случае с Python все намного проще. Просто узнаем путь к интерпретатору, создаем файл с Python-программой и делаем его исполняемым. Все! Теперь можно запустить программу как любую другую.
Давайте разберем подробнее все, что мы сделали, и начнем, пожалуй, с консоли.
       Сначала мы узнали путь к интерпретатору. Для чего? Чтож, если вы ас консоли и знакомы с написанием сценариев оболочки, то сразу поймете, в чем дело. Для тех, кто не знает, объясню. Система не знает, как
запустить на исполнение файл. В UNIX нет привязки к расширению файла, вместо этого используются «Волшебные числа», однозначно идентифицирующие тип файла. Исполняемые бинарные файлы Linux имеют в самом начале определенное волшебное число, по которому система и узнает, что это за файл. Тогда как быть со сценариями (еще один термин, который неплохо бы запомнить, это любой интерпретируемый файл, часто например можно услышать — сценарии оболочки)? Для этого была предусмотрена специальная последовательность символов — "#!", называемая так же «шибенг». После этой последовательности символов указывают путь к программе, которая выполняет сценарий. В данном случае это Python. Программу можно так же запустить и напосредственно вызвав интерпретатор (при этом ваша программа желательно, должна иметь расширение .py, хотя бы для удобочитаемости):

	[liksys@max ~] $ python myprog.py


       Далее мы создали каталог для программы. Вообще говоря, для такой простой программы, как «Hello», делать это было не обязательно, но для больших проектов просто необходимо. Python ищет модули, кроме системных (и заданных пользователем) путей еще и в текущем каталоге, поэтому хорошо бы его как-то ограничить.
       После создания файла мы сделали его исполняемым и запустили. Это стандартные действия, и если до этого вы писали сценарии оболочки, то узнаете эту последовательность комманд.
       Давайте подробнее остановимся на самой программе. Сразу видна разница с аналогом на C++ — визуально программа выглядит проще и занимает немного меньше места.
       Про первую строчку уже было сказано — мы задаем путь к интерпретатору. Следующие две строчки импортируют необходимые модули — это PyQt4 и sys. Модуль sys импортируется полностью, а вот от PyQt4 импортируется только часть — Qt. В нем импортируются автоматически модули QtGui, QtCore и т.д. Конечно, можно импортировать и каждую часть PyQt4 по отдельности, но можно поступить проще, создав таким образом себе меньше проблем (ведь не обязательно помнить, в каком модуле находится нужный класс). Импортируя Qt, мы избавляемся еще и от проблемы совместимости — наши собственные классы не будут конфликтовать с библиотечными. Четвертая строка программы может быть не совсем ясна тем, кто в Python совсем недавно. Модуль Python может исполняться сам по себе (например, при отладке), таким образом, мы включаем код по условию: если файл исполняется, то делаем определенные действия. Если же этот файл прсто импортируется, то эти действия не будут выполняться. За такую магию отвечает переменная __name__, которая содержит имя функции. В нашем «Hello» это было не обязательно, но хороший стиль требует оформления функции main() (как во многих другх языках, например, в C++).
       Затем следует собстенно код, отвечающий за интерфейс. Сначала создается объект-экзампляр QApplication, управляющий всеми ресурсами приложения. Qt сам обрабатывает некоторые опции командной строки, поэтому в качестве параметра мы передаем конструктору sys.argv — список опций, с которыми была запущщена программа.
       В следующей строке создается виджет label — объект-экземпляр класса QLabel. Это текстовая метка, содержащая надпись. Виджет (widget) — это еще один термин, с которым вам часто придется столкнуться. Он
обозначает любой элемент пользовательского интерфейса, например текстовую метку или кнопку. Одни виджеты могут содержать в себе другие виджеты — например, в качестве главного окна часто выступает QMainWindow, содержащий в себе остальные элементы управления. Но никто не принуждает использовать именно QMainWindow, что мы и сделали в предыдущем примере — Qt позволяет использовать любой виджет в качестве окна.
       Если вы знаете HTML (что вообще говоря желательно при работе с Qt) — то можете немного развлечся и заменить текст метки в конструкторе QLabel на "Hello, PyQt4!". Почти все виджеты Qt, работающие тем или иным образом с текстом, поддерживают простейшие средства форматирования HTML.
       Следующая короткая строка — «label.show()», делает наш виджет видимым. В Qt все виджеты по умолчанию создаются невидимыми, чтобы обеспечить возможность их настройки — и затем уде отображаются на экран. Это позволяет избежать мерцания и прочих неприятных эффектов. В большом приложении вам достаточно сделать видимым один главный виджет, а все содержащиеся в нем виджеты станут видимыми автоматически.
       И последняя строка — передача управления приложению6 а именно объекту-экземпляру QApplication. В этом месте программа переходит в цикл обработки событий, ожидая действий со стороны пользователя. Однако мы видим небольшую разницу — в C++ функция называлась exec(), а в Python — exec_(). Почему же это так? В Python существует ключевое слово exec, поэтому разработчики PyQt4 приняли простое правило: если имя оригинальной функции Qt4 совпадает с ключевым словом Python, то после имени функции ставится символ "_". Это правило справедливо для всех функций PyQt4.
       Как видим, на Python программа получилась проще. Никаких заголовочных файлов отдельно для каждого класса, никаких указателей и прочих примудростей C++. Конечно, придется немного привыкнуть к разным премудростям Python, но одно ясно — для программ с графическим интерфейсом Python подходит очень хорошо. Можно создавать программы быстрее и короче, используя всю мощь Qt4 для C++ и удобство Python. Не даром такой подход пользуется популярностью у многих разработчиков, как OpenSource, так и коммерческих компаний, благо Python распространяется по большому количеству лиценизий на любой вкус, заплатить коммерческим компаниям, выпускающим продукты с закрытыми исходными текстами, только за Qt4 и PyQt4. Но мы же пока только учимся, не так ли? Поэтому вполне можем пользоваться этими библиотеками на условиях лицензии GPL, выпуская все наши творения в открытом виде. А закрытый софт — это дело коммерческих компаний, которые могут себе позволить и такое.
       Надеюсь, мне удалось заинтересовать вас, ведь дальше будет еще интереснее! Мы научимся создавать свои приложения на PyQt4, собственные виджеты, я расскажу вам, как правильно располагать модули, использовать такие современные технологии, как интернационализацию. Мы поговорим о том, как следует организовывать приложение
с точки зрения эргономики и дизайна — ведь интерфейс, это важнейшая деталь продукта, именно его видит пользователь перед собой. По мере изучения мы напишем много простых приложений, иллюстрирующих ту или иную концепцию, а в конце попробуем написать что-то интересное, используя весь багаж знаний.
image
Ждите часть №2. Надеюсь вы узнали много нового, спасибо за внимание ;)


Сергей @Assuri
карма
269,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

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

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

  • –1
    Зачем нужны лишние переносы строк?
    • 0
      Не думаю, что это так существенно. Привык, что каждый абзац должен начинаться с новой строки + хабр добавляет перенос.
      • 0
        Они стоят после каждой строки.
    • +2
      Видимо текст готовился в чём-то типа Notepad :) После каждых n символов — перевод на новую строку.

      Assuri, может всё-таки исправишь?
  • 0
    Отличный старт, только небольшая проблема с форматированием — слишком много преносов строки.
    И небольшое замечание по поводу нижней картинки — второй абзац раздела истории из статьи про питон в википедии =)
    • +1
      Вы имеете ввиду, что питон в статье не соответствует с Wikipedia'вской? :)
      • 0
        Я имею ввиду что язык питон это не змея, а Монти Пайтон =)
        • 0
          Ну в этом и заключается юмористичность сей картинки :)
  • +2
    Прошу прощения у всех — даже не знаю могло вызвать такое странное форматирование. Вроде бы всё исправил. Ещё раз извините. :(
  • +2
    Лучше путь к интерпретатору указывать как
    #!/usr/bin/env python
    • 0
      Почему, кстати?
      • +1
        Потому что путь может различатся на разных системах (например /opt/pythonXX/bin/python в Solaris), а env практически всегда находится в /usr/bin/
        en.wikipedia.org/wiki/Shebang_(Unix)#Portability
    • –3
      Не соглашусь. Откуда в переменных окружения на большинстве систем может взяться python?
      При установке из портов на FreeBSD оно никуда ничего не прописывает для этого.
      Так что лучше сначала which python, и явно указать в начале скрипта путь к интерпретатору.
      • +2
        Прочитал man env, понял свою ошибку.
        Там сказано что таким образом оно ищет по путям в PATH интерпретатор и вызывает оный.
  • +1
    Шикарная статья. Вопрос к писавшему (ни на что не надеясь правда): а возможно ли создавать интерфейсы в QtDesigner'е и использовать UI файлы? Или вдруг есть какая-нибудь ide?
    • +1
      Возможно.

      Вот скелет. Как создавать ресурсы и форму — в коментах в нем написано.
      pastebin.mozilla.org/572234
      • 0
        Остальные 2 камента там — как биндить действия на слоты, это пример.
    • +2
      Да, конечно можно. PyQt4 тем и хорош, что он вообще не ограничивает возможности Qt.
      • +2
        справедливости ради хотелось бы добавить, что непосредственно перед использованием .ui таки нужно «скомпилировать» в .py
        • 0
          Кстати, не обязательно

          #!/usr/bin/python
          import sys
          from PyQt4.QtGui import *
          from PyQt4.QtCore import *
          from PyQt4 import uic

          app = QApplication(sys.argv)
          widget = QWidget()
          uic.loadUi(«mywidget.ui», widget)
          widget.show()
          app.exec_()
          • 0
            а оно будет в свою очередь компилироваться в .pyc? если нет — то трюк, имхо, не совсем практичный
            • 0
              Обычно интерфейсы грузятся один раз и в самом начале программы. По-моему, не самое страшное место для того, чтобы немного попарсить XML.
              • НЛО прилетело и опубликовало эту надпись здесь
                • 0
                  Я какбэ не про это, а про то, что не компилировать совсем не критично.
                • 0
                  … в том смысле, что динамически они тоже, наверное, создаются все-таки не в цикле из ста итераций.
                  • НЛО прилетело и опубликовало эту надпись здесь
    • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Отличная статья! Дайте человеку кто-нибудь инвайт в конце-концов!

    Немного к автару:
    поправьте, пожалуйста, переносы-паразиты и исправьте: «Скачать последнюЮ версию можно обычно из репозитория вАшего дистрибутива», «а вторую — на Python, ИСпользуя Qt4», ну и т.д. :)
    • 0
      Инвайт получили, огромное вам всем спасибо за это!!! Прожолжение точно будет ;)
      • 0
        И Вам спасибо ;)
  • +1
    интересующимся сабжем я бы посоветовал ещё прочитать книгу Rapid GUI Programming
    with Python and Qt (http://torrents.ru/forum/viewtopic.php?t=1149901)
  • 0
    Если вы знаете HTML (что вообще говоря желательно при работе с Qt) — то можете немного развлечся и заменить текст метки в конструкторе QLabel на «Hello, PyQt4!». Почти все виджеты Qt, работающие тем или иным образом с текстом, поддерживают простейшие средства форматирования HTML.

    Круто, но сами теги, которые написать надо — не видно :) Поправьте.

    Вы не первый, кто пишет на эту тему, но именно у Вас — интересно получается. Ждем продолжения!

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