Написание приложений, основаных на Qt, на языке Python

http://vizzzion.org/?id=pyqt
  • Перевод
Доброе время суток.
Недавно решил изучить ещё один язык программирования. Выбор пал на python. Написал несколько маленьких скриптов. Но прежде всего я хотел писать приложения с графическим интерфейсом. В интернете наткнулся на этот небольшой туториал, прочтение которого вылилось в предлагаемый Вашему вниманию перевод. Надеюсь, что кому-нибудь он будет полезен.


Это руководство нацелено на получение представления о том как писать маленькие приложения на python, использующие библотеку Qt.


Для успешного выполнения всех заданий необходимо иметь базовые знания python, однако, Qt знать не обязательно. Я использую linux в этих примерах и я предполагаю, что вы уже имеете работающий Python и PyQt. Для того, чтобы проверить это, откройте оболочку python, просто набрав «python» в консоли в введите

import qt


Если не появилось сообщения об ошибке, вы уже готовы начать. Примеры в этом руководстве упрощены насколько это возможно, и показывают полезные способы чтобы писать и структурировать вашу программу. Важно, чтобы вы прочитали исходный код примеров, болшинство вещей объяснены там. Используйте примеры и попытайтесь изменить их, поиграйте с ними. Это лучший способ привыкнуть.

Hello, world!


Начнём с простого. Программа открывает окно и показывает что-нибудь. Приведённый дальше код показывает окно, в котором написано «Hello, world!». Очевидно.

#!/usr/bin/python
import sys
from qt import *
#создадим приложение и передадим аргументы
a = QApplication(sys.argv)
#создание виджета
#Первый аргумент – текст, который мы хотим увидеть.
#Воторой аргумент – родительский виджет, 
#т.к. Hello – единственный виджет, то у него нет родителя
hello = QLabel("Hello world!",None)
#делаем виджет главным
a.setMainWidget(hello)
#показать виджет
hello.show()
#запустить приложение
a.exec_loop()


Около 7 строк кода, и это настолько просто как только можно.
А вот так это выглядит:


Кнопка


Добавим немного нтерактивности! Мы заменим надпись «Hello, World!» кнопкой и назначим ей действие. Это назанчение называется «присоединением сигнала», событие, которое посылается слоту когда кнопка нажата, который является функцией. Эта функция запускается, когда возникает событие.

#!/usr/bin/python
# coding=utf-8
import sys
from qt import *
a = QApplication(sys.argv)
# Наша функция, которая будет вызвана пр нажатии на кнопку
def sayHello():
    print "Hello, World!"
#создание кнопки
hellobutton = QPushButton("Say 'Hello world!'",None)
#назначить обработчик клика кнопке
a.connect(hellobutton, SIGNAL("clicked()"), sayHello)
#назначить кнопку главным виджетом
a.setMainWidget(hellobutton)
#показать виждет
hellobutton.show()
#запустить приложение
a.exec_loop()




Это уже больше похоже на нормальное приложение


Вы можете вообразить, что программирование таким образом не расширяемо и не заходите продолжать. Чтож давайте сделаем это по-питоновски, добавив структуру и использовав объектно-ориентированный подход. Мы создадим наш собственный класс, наследованный от QApplication и поместим необходимые нам вещи в его методы: один метод для того чтобы создать виджеты и слот, который сожержит код, запускаемый при приходе сигнала.

#!/usr/bin/python
# coding=UTF-8
import sys
from qt import *
#класс наследуем от QApplication
class HelloApplication(QApplication):
    def __init__(self, args):
        """
            В конструкторе мы делаем всё, что необходимо для запуска нашего приложения, которое
            создаёт QApplication в __init__ методе, затем добваляет наши виджеты и, наконец,
            запускает exec_loop
        """
        QApplication.__init__(self, args)
        self.addWidgets()
        self.exec_loop()        
    def addWidgets(self):
        """ В этом методе мы добавляем виджеты и присоединяем обработчики сигналов.
            Обработчик сигнала для виджета так же называется "слотом"
        """
        self.hellobutton = QPushButton("Say 'Hello, World!'",None)
        self.connect(self.hellobutton, SIGNAL("clicked()"), self.slotSayHello)
        self.setMainWidget(self.hellobutton)
        self.hellobutton.show()
    def slotSayHello(self):
        """
            Это пример слота - метода, который вызывается, когда приходит сигнал.
        """
        print "Hello, World!"
# Этот скрипт должен выполняться только отдельно, так что мы должны проверить это,
# но мы также должны иметь возможность подключать эту программу без запуска какого-либо кода
if __name__ == "__main__":
    app = HelloApplication(sys.argv)


Кодирование интерфейсов – отстой



Так что мы хотим использовать Qt3 Designer для создания GUI. На картинке вы можете видеть простой интерфейс. Зелёным цветом написаны имена виджетов. Всё что нам надо сделать
  1. Скомпилировать .ui файл из Qt designer'а в класс на python
  2. Написать подкласс и использовать его как mainWidget

Таким образом, мы сможем изменять нтерфейс в Qt designer'е, не копаясь в коде

Команда
pyuic testapp_ui.ui -o testapp_ui.py


сделает класс на python, с которым мы сможем работать.

Работу нашей программы можно описать следующим образом:
  1. Мы заполняем lineedit
  2. К нажатию на кнопку добавления мы присоединим метод, который читает текст из lineedit и добавляет его в listview
  3. Нажатие на кнопку удаления удалит выбранный элемент из listview.

Вот код с комментариями:
#!/usr/bin/python
# coding=utf-8
from testapp_ui import TestAppUI
from qt import *
import sys
class HelloApplication(QApplication):
    def __init__(self, args):
        """
            В конструкторе мы делаем всё, что необходимо для запска нашего приложения, которое
            создаёт QApplication в __init__ методе, затем добваляет наши виджеты и, наконец,
            запускает exec_loop
        """
        QApplication.__init__(self,args)
        # Мы передаём None т.к. этот виджет верхнего уровня
        self.maindialog = TestApp(None)
        self.setMainWidget(self.maindialog)
        self.maindialog.show()
        self.exec_loop()
class TestApp(TestAppUI):
    def __init__(self,parent):
        # Запускаем родительский конструктор и присоединяем слоты к методам
        TestAppUI.__init__(self,parent)
        self._connectSlots()
        # Изначально список пуст, так что кнопка удаления не должна работать
        # Сделаем её неактивной
        self.deletebutton.setEnabled(False)
    def _connectSlots(self):
        # Устанавливаем обработчики сингналов на кнопки
self.connect(self.addbutton,SIGNAL("clicked()"),self._slotAddClicked)
self.connect(self.lineedit,SIGNAL("returnPressed()"),self._slotAddClicked)
self.connect(self.deletebutton,SIGNAL("clicked()"),self._slotDeleteClicked)
    def _slotAddClicked(self):
        # Читаем тескт из lineedit,
        text = self.lineedit.text()
        # если lineedit не пуст,
        if len(text):
            # вставим новый элемент в список ...
            lvi = QListViewItem(self.listview)
            # с текстом из lineedit ...
            lvi.setText(0,text)
            # и очистим lineedit.
            self.lineedit.clear()
            # Кнопка удаления м.б. выключена, так что включим её.
            self.deletebutton.setEnabled(True)
    def _slotDeleteClicked(self):
        # Удаляем выбранный элемент из списка
        self.listview.takeItem(self.listview.currentItem())
        # Check if the list is empty - if yes, disable the deletebutton.
        # Если список после этого оказался пустым, то сделаем кнопку удаления неактивной
        if self.listview.childCount() == 0:
            self.deletebutton.setEnabled(False)
if __name__ == "__main__":
    app = HelloApplication(sys.argv)


И вот результат трудов:

Полезно знать


Создание интерфейса в Qt designer'е не только делает проще создание GUI, но это также хороший инструмент для изучения Qt. Вы можете протестировать как виджет выглядит, увидеть что доступно в Qt и посмотреть свойства, которые вы можете захотеть использовать.

Документация API для C++ также очень полезна (читайте необходима), когда работаете с PyQt. API переведён очень просто, так что попрактиковавшись, вы поймёте, что документация API для разработчиков, один из действительно нужных вам инструментов. Во врема работы в KDE вы можете ввести qt:[widgetname] в конквероре. Т.о. qt:qbutton откроет вам документацию прямо на описании qbutton. Сайт Trolltech содержит гораздо больше документации, которая может оказаться вам полезной.

Примеры в этом руководстве созданы с использованием Qt 3.3. Я быть может обновлю руководство когда появится пригодная к использованию версия pyQt для Qt 4.
Метки:
Поделиться публикацией
Похожие публикации
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 34
    • 0
      Спасибо! Ссылка то что надо!
    • +1
      Спасибо за статью, всегда хотел хоть как-то взгянуть на питон на что он похож :-)
      • 0
        А теперь еще про GTK и будет всё просто отлично.
        Спасибо. Нового конечно ничего не узнал, зато опять рад за Python на котором все лаконично и просто, и за Qt на котором писать GUI безумно удобно.
        • 0
          Без сомнений в букмарки.
          • 0
            Отличная статья.

            P.S. «бызовые» и «насладованный» исправьте :)
          • 0
            В мемориз!
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Спасибо, очень интересно!
                • +1
                  Предпочитаю wxWidgets. Да и большинство GUI-софта, написанного на Питоне, использует их. По крайней мере того что я видел ;)
                  • 0
                    Моё субъективное мнение, что работа с WxWigets даёт "более родные", если так можно выразиться, интерфейсы на всех системах, с которыми она работает.
                    • 0
                      Все верно. WxWidgets использует стандартные интерфейсы (GTK, Cocoa, Windows Controls и т.д.) там, где это возможно. Поэтому GUI, построенный на WxWidgets выглядит «родным» на каждой платформе.
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • 0
                      зато у него есть много других недостатков;) ну создание интерфейса я опущу (хотя честно говоря мне показалось крайне неудобным распихивание каждой кнопочки и лейбла в свой контейнер для нормального их отображения, хотя сейчас могло что-то поменяться), но вот многопоточная система слаба (приоритеты выставляются настолько странно, что фоновые потоки ели чуть ли не все ресурсы, в то время как основные ожидали), несколько странная система событий (когда надо написать свое событие надо писать слишком много кода) ну и по мелочам. Пользовался как Qt так и wxWidgets и все-таки остался на Qt. Имхо гораздо более удобная и продуманная библиотека.
                    • 0
                      Отличная статья, стремление к питону и Qt ускоряется.. :)
                      • –6
                        а теперь делаем все красиво.

                        #!/usr/bin/env ruby

                        Shoes.app :width => 300, :height => 150, :margin => 10 do
                        def answer(v)
                        @answer.replace v.inspect
                        end

                        button "Ask" do
                        answer ask("What is your name?")
                        end
                        button "Confirm" do
                        answer confirm("Would you like to proceed?")
                        end
                        button "Open File..." do
                        answer ask_open_file
                        end
                        button "Save File..." do
                        answer ask_save_file
                        end
                        button "Color" do
                        answer ask_color("Pick a Color")
                        end

                        @answer = para "Answers appear here"
                        end
                        • 0
                          позновательно.. по крайней мере создает представление в доступной форме
                          • 0
                            Присоединюсь к благодарностям. Как раз изучаю способы построения GUI, вот Tcl/Tk не понравился. А судя по отзывам Qt мне подойдет.
                            • 0
                              > когда появится пригодная к использованию версия pyQt для Qt 4
                              Скажите, а что не так с PyQt4? На первый взгляд всё работает..
                              • 0
                                Это же переводная статья. Оригинал датируется декабрём 2005го года. Возможно тогда какие-то проблемы существовали.
                                Я использовал Qt3 только потому, что он уже был установлен на моём стареньком ноутбуке.
                              • 0
                                В избранное :-)
                                • +1
                                  PyQt3 это уже прошлый век, весь софт уже давно на PyQt4 пишут и местами на PyKDE4 даже. И еще имхо лучше использовать для подгрузки гуя модуль uic, дабы не приходилось каждый раз генерить нужный код через pyic
                                  • 0
                                    Очень интересно. А модуль uic где можно взять? А то поискал у себя - нет такого.
                                    • 0
                                      А понял, он есть в PyQt4. Чтож надо будет попробовать.
                                      • 0
                                        from PyQt4 import uic

                                        потом в классе формы
                                        uic.loadUi("main.ui", self) и все
                                        • 0
                                          Попробовал. Возникла проблема:
                                          assert version in ("4.0",)
                                          Если в main.ui поменять версию на 4.0, то
                                          тоже ничего хорошего.
                                          Создавался файл .ui в KDevelop 3.5.0
                                          • 0
                                            я использовал QtDesigner в составе Qt-4.3.3, PyQt4-4.3.3
                                    • 0
                                      "from qt import *"

                                      Никогда не делай такого.

                                      http://python.net/~goodger/projects/pycon/2007/idiomatic/presentation.html - Смотри страницу 48.Importing
                                      • 0
                                        Давно использую Питон для написание чего простого+ГУИ, особенно в Линуксе, вообще помоему Питон это отличная замена баша, только для ГУИ... впрочем он так же очень удобен ив консоли(правда тут уже мнения расходятся =) )
                                        • 0
                                          замена баша - это совсем неправда =).
                                        • 0
                                          А что значит "Кодирование интерфейсов – отстой" ?
                                          • 0
                                            Это значит что в ручную кодить интерфейсы - отстой. Лучше использовать Designer'ы
                                          • 0
                                            Qt3 Designer( ныне KDevelop Designer - прим. пер.)
                                            глупости какие, "прим. пер." выкинуть.

                                            И ещё, имхо, использование GUI утилит для создания интерфейсов возможно для очень простых программулек только. Сложные интерфейсы проще кодировать ручками.

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