Написание приложений, основаных на Qt, на языке Python
Доброе время суток.
Недавно решил изучить ещё один язык программирования. Выбор пал на python. Написал несколько маленьких скриптов. Но прежде всего я хотел писать приложения с графическим интерфейсом. В интернете наткнулся на этот небольшой туториал, прочтение которого вылилось в предлагаемый Вашему вниманию перевод. Надеюсь, что кому-нибудь он будет полезен.
Это руководство нацелено на получение представления о том как писать маленькие приложения на python, использующие библотеку Qt.
Для успешного выполнения всех заданий необходимо иметь базовые знания python, однако, Qt знать не обязательно. Я использую linux в этих примерах и я предполагаю, что вы уже имеете работающий Python и PyQt. Для того, чтобы проверить это, откройте оболочку python, просто набрав «python» в консоли в введите
Если не появилось сообщения об ошибке, вы уже готовы начать. Примеры в этом руководстве упрощены насколько это возможно, и показывают полезные способы чтобы писать и структурировать вашу программу. Важно, чтобы вы прочитали исходный код примеров, болшинство вещей объяснены там. Используйте примеры и попытайтесь изменить их, поиграйте с ними. Это лучший способ привыкнуть.
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. На картинке вы можете видеть простой интерфейс. Зелёным цветом написаны имена виджетов. Всё что нам надо сделать
- Скомпилировать .ui файл из Qt designer’а в класс на python
- Написать подкласс и использовать его как mainWidget
Таким образом, мы сможем изменять нтерфейс в Qt designer’е, не копаясь в коде
pyuic testapp_ui.ui -o testapp_ui.py
сделает класс на python, с которым мы сможем работать.
- Мы заполняем lineedit
- К нажатию на кнопку добавления мы присоединим метод, который читает текст из lineedit и добавляет его в listview
- Нажатие на кнопку удаления удалит выбранный элемент из 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.