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 и посмотреть свойства, которые вы можете захотеть использовать.
Для успешного выполнения всех заданий необходимо иметь базовые знания 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 и посмотреть свойства, которые вы можете захотеть использовать.