пятница, 14 сентября 2012 г.

Python Qt

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

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

Для того, чтобы проверить это, откройте оболочку Python, просто набрав "python" в консоли в введите:

import qt

Если не появилось сообщения об ошибке, вы уже готовы начать. Начнём с простого. Программа открывает окно и показывает что-нибудь. Приведённый дальше код показывает окно, в котором написано "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)


















На картинке вы можете видеть простой интерфейс. Зелёным цветом написаны имена виджетов. Всё что нам надо сделать это:
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. Вы можете протестировать как виджет выглядит, увидеть что доступно в Python Qt и посмотреть свойства, которые вы можете захотеть использовать.

Комментариев нет:

Отправить комментарий