Вступление
В этом руководстве мы рассмотрим, как использовать среду Python PyQT для разработки графического интерфейса пользователя (GUI) для настольного приложения на Python.
Популярные альтернативы Python для разработки графического интерфейса включают Tkinter , Kivy , PySimpleGUI и wxPython .
Примечание. На момент написания этого руководства PyQt6 - это последняя и наиболее продвинутая версия инфраструктуры Python PyQT, а также версия, которую мы будем использовать.
Мы пройдем через процесс установки и познакомимся с ключевыми элементами PyQT, прежде чем перейти к менеджерам компоновки , виджетам , сигналам и слотам, а также к тому, как стилизовать виджеты , а также взглянем на файлы пользовательского интерфейса, и как создавать пользовательские интерфейсы с помощью интуитивно понятного интерфейса перетаскивания, который мы затем можем экспортировать в исполняемые скрипты Python:
-
Монтаж
-
Введение в PyQt
-
Менеджеры по компоновке
-
Виджеты
- Этикетки
- Кнопки
- Редактирование строки
- Поля со списком
- Радио-кнопки
- Отображение данных с помощью виджета таблицы
- Отображение данных с помощью виджета в виде дерева
-
Сигналы и слоты
-
Стилизация приложений-виджетов
-
Файлы пользовательского интерфейса
- qtDesigner
- Преобразование файлов пользовательского интерфейса в Python
-
Заключение
Монтаж
Чтобы использовать фреймворк PyQt, нам сначала нужно установить его с помощью диспетчера пакетов pip.
Если в вашей системе установлен pip, давайте запустим следующую команду, чтобы установить новейшую версию PyQt:
$ pip install pyqt6
Если pip install pyqt6
завершится неудачно, вы можете проверить
наличие изменений при установке
здесь
.
Введение в PyQt
PyQt - это набор инструментов, который является продуктом библиотеки Qt и языка программирования Python. Поскольку PyQt является одним из наиболее часто используемых GUI-фреймворков для Python, существует как тонна хорошо написанной документации, так и большое сообщество.
Одним из основных классов PyQt является
QWidget
- реализация виджета . Виджеты - это компоненты графического интерфейса и основные строительные блоки пользовательских интерфейсов. Виджет может быть меткой, кнопкой, меню, полем со списком, скроллером, панелью инструментов, диалоговым окном файла и т. Д.
Есть много виджетов, и чтобы привыкнуть к ним, нужно время. Мы рассмотрим наиболее часто используемые виджеты, которые по большей части будут присутствовать почти в каждом приложении PyQt.
Относительный порядок этих виджетов во фрейме приложения диктуется и управляется менеджером компоновки . Мы также рассмотрим доступные менеджеры компоновки и их влияние на расположение компонентов графического интерфейса.
Точкой входа в каждое приложение PyQt является QApplication
, который
представляет само приложение. Он обрабатывает всю инициализацию и
«холст», на котором мы рисуем.
Примечание. Всегда существует только один QApplication
,
независимо от количества окон или модальных блоков в вашем приложении.
Давайте сделаем рывок и инициализируем приложение PyQt, а также инициализируем окно с пустым холстом:
import sys
from PyQt6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
root = QWidget()
root.setWindowTitle('A Simple PyQt6 App')
root.setGeometry(100, 100, 280, 80)
root.show()
sys.exit(app.exec())
Запуск этого кода инициализирует простое приложение:
{.ezlazyload}
Давайте рассмотрим эту инициализацию построчно.
Во-первых, мы импортируем встроенный sys
который предоставляет нам
функции для управления средой выполнения Python . В нашем случае мы
будем использовать этот модуль для обработки статуса выхода приложения -
когда пользователь нажимает кнопку «X»:
import sys
Затем мы можем импортировать QApplication
(основу) и QWidget
(компоненты GUI) из модуля PyQt6.QtWidgets
from PyQt6.QtWidgets import QApplication, QWidget
Далее, эта строка является требованием QT. Он инициализирует PyQT. Sys.argv содержит список всех аргументов командной строки, переданных приложению. Каждое созданное вами приложение с графическим интерфейсом пользователя должно иметь ровно один экземпляр QApplication.
Теперь, поскольку QApplication
отвечает за инициализацию большинства
элементов, участвующих в разработке приложений PyQt, мы хотим сначала
создать его экземпляр. Конструктор принимает sys.argv
поскольку вы
также можете передавать аргументы командной
строки :
app = QApplication(sys.argv)
Теперь в QApplication
фактически нет окон. Запуск приложения без окна
даст нам невидимый результат. Чтобы на самом деле представить окно в
миксе, мы создадим корневой виджет , который также известен как
оконный виджет . В любом случае он представляет собой самый нижний
виджет, в который мы будем добавлять другие компоненты:
root = QWidget()
Давайте установим собственный заголовок окна с помощью
setWindowTitle()
:
root.setWindowTitle('A Simple PyQt6 App')
Метод setGeometry()
принимает 4 аргумента: x_coordinate
,
y_coordinate
, width
и height
. x_coordinate
и y_coordinate
определяют исходную точку окна при отображении:
root.setGeometry(100, 100, 280, 80)
Теперь, чтобы отобразить созданный графический интерфейс на экране, мы
вызываем метод show()
в root
:
root.show()
Наконец, мы выполняем приложение через app.exec()
и запускаем основной
цикл приложения, пока пользователь не закроет его:
sys.exit(app.exec())
Менеджеры по компоновке
Менеджеры компоновки PyQt предоставляют нам эффективный способ упорядочивания виджетов PyQt в графическом интерфейсе. Чем лучше мы размещаем наши виджеты, тем более изысканным и профессиональным может выглядеть наше приложение с графическим интерфейсом пользователя. Неуклюжие, огромные промежутки между кнопками без особого использования пространства не очень удобны для пользователя. То же самое касается и наоборот - если мы поместим кнопки слишком близко, их станет неудобно легко нажимать неправильно.
Самыми популярными классами диспетчера макетов PyQt являются:
- QVBoxLayout размещает виджеты вертикально.
- QHBoxLayout размещает виджеты по горизонтали.
- QGridLayout размещает виджеты в сетке.
- QFormLayout размещает виджеты в двух столбцах.
При создании приложений с графическим интерфейсом пользователя с PyQt вы часто будете использовать более одного из четырех менеджеров компоновки общего назначения, даже в одном приложении, для разных типов окон.
Давайте воспользуемся предыдущим примером и обновим его, добавив
несколько виджетов, таких как QPushButton
и управляя ими с помощью
диспетчера макетов.
1. QVBoxLayout
Диспетчер макетов ящиков (как QVBox, так и QHBox) использует все пространство, которое он получает от родительского макета или виджета, и делит его на несколько ящиков.
Каждый виджет, управляемый менеджером, заполнит одно поле.
QVBoxLayout
позволяет нам расположить наши виджеты вертикально. Макет
добавляет виджеты к себе последовательно сверху вниз. Таким образом,
первый виджет, добавленный в ваш код, будет самым верхним виджетом, а
последний виджет, добавленный в ваш код, будет самым нижним виджетом в
макете.
Давайте добавим несколько кнопок в наше приложение через QVBoxLayout
:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
# Create the Qt Application
app = QApplication(sys.argv)
# Create the root Widget/Window
window = QWidget()
# Create the Vertical Box Layout Manager, setting `window` as parent by passing it in the constructor.
layout = QVBoxLayout(window)
# Create and add the QPushButton Widgets to the `layout`
layout.addWidget(QPushButton('One'))
layout.addWidget(QPushButton('Two'))
layout.addWidget(QPushButton('Three'))
layout.addWidget(QPushButton('Four'))
layout.addWidget(QPushButton('Five'))
# Show the parent Widget
window.show()
# Run the main Qt loop and allow safe exiting
sys.exit(app.exec())
Запустив этот код, мы увидим на экране следующее окно:
{.ezlazyload}
Это окно содержит 5 кнопок, расположенных вертикально сверху вниз. Когда мы нажимаем на них, ничего не происходит, потому что мы еще не добавили для них никакой логики.
2. QHBoxLayout
QHBoxLayout
- это макет блока, который позволяет нам расположить
наши виджеты по горизонтали. Макет добавляет виджеты к себе слева
направо. Таким образом, первый виджет, добавленный в ваш код, будет
самым левым виджетом, а последний виджет, добавленный в ваш код, будет
самым правым виджетом в макете.
Заменим вертикальный прямоугольник на горизонтальный:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QHBoxLayout, QWidget
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget of the Widgets added to the layout
window = QWidget()
# Create the Horizontal Box Layout Manager, setting `window` as parent by passing it in the constructor
layout = QHBoxLayout(window)
# Create and add the QPushButton Widgets to the `layout`
layout.addWidget(QPushButton('One'))
layout.addWidget(QPushButton('Two'))
layout.addWidget(QPushButton('Three'))
layout.addWidget(QPushButton('Four'))
layout.addWidget(QPushButton('Five'))
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
Запустив этот код, мы увидим на экране следующее окно:
{.ezlazyload}
Это окно содержит 5 кнопок, расположенных по горизонтали слева направо.
3. QGridLayout
QGridLayout
используется, когда мы хотим расположить виджеты в сетке
из строк и столбцов. В этой сетке, используя координаты, мы можем
определить относительное положение каждого виджета как: (строка,
столбец).
Примечание. И row
и column
должны быть целыми числами.
QGridLayout
также использует все пространство, которое он получает от
своего родительского макета или виджета, и делит его на несколько
блоков. Как и в предыдущих менеджерах компоновки, каждый виджет
помещается в свое собственное поле. Количество ящиков рассчитывается
автоматически в зависимости от количества виджетов и их координат.
Давайте использовать QGridLayout
вместо горизонтального прямоугольного
макета:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QGridLayout, QWidget
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget
window = QWidget()
# Create the buttons
button1 = QPushButton('One')
button2 = QPushButton('Two')
button3 = QPushButton('Three')
button4 = QPushButton('Four')
button5 = QPushButton('Five')
# Create the QGrid Layout Manager
layout = QGridLayout(window)
# Add button Widgets to the QGridLayout
# addWidget([object], [row number], [column number])
layout.addWidget(button1,0,0)
layout.addWidget(button2,1,0)
layout.addWidget(button3,2,0)
layout.addWidget(button4,0,1)
layout.addWidget(button5,0,2)
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
Запустив этот код, мы увидим на экране следующее окно:
{.ezlazyload}
Это окно содержит 5 кнопок, которые расположены так, как мы указали в
addWidget()
. Сам метод принимает 3 аргумента:
- Виджет, который нужно разместить в сетке.
- Ряд, в который он должен быть помещен.
- Столбец, в который он должен быть помещен.
Существует необязательный четвертый аргумент, alignment
, который
определяет параметр выравнивания каждого Widget внутри своего поля.
Значение по умолчанию ( Qt.Alignment.AlignCenter
) означает, что
каждый виджет должен заполнять все свое поле от центра кнаружи.
Подробнее о Qt
в следующих разделах.
Наконец, есть также columnSpan
и rowSpan
, которые определяют,
занимает ли виджет несколько строк или столбцов:
addWidget(Widget, fromRow, fromColumn, rowSpan, columnSpan, Qt.Alignment)
Qt.Alignment
строк и столбцов, а также Qt.Alignment (до PyQt6 это был
бы Qt.AlignLeft
):
# New import other than the ones already present
from PyQt6.QtCore import Qt
# addWidget([object], [row number], [column number], [columnSpan], [rowSpan], Qt.Alignment)
layout.addWidget(button1, 0, 0, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button2, 1, 0, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button3, 2, 0, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button4, 0, 1, 1, 1, Qt.Alignment.AlignLeft)
layout.addWidget(button5, 0, 2, 1, 1, Qt.Alignment.AlignLeft)
Вы можете AlignLeft
, AlignTop
, AlignBottom
, AlignRight
и
AlignCenter
. Изменив размер окна, мы увидим, что каждая кнопка
выровнена по левому краю своего поля, а не по центру:
{.ezlazyload}
Тогда как, если бы мы использовали AlignCenter
или оставили его по
умолчанию:
{.ezlazyload}
4. QFormLayout
QFormLayout
упрощает создание макетов форм для настольных приложений.
Он состоит из двух столбцов - для меток и для входов.
Обычно виджет ввода - это QLineEdit
, QSpinBox
, QComboBox
или
аналогичные виджеты ввода. Создадим QFormLayout
:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit
def addLabel(layout, text):
layout.addWidget(QLabel(text))
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget and the QVBoxLayout Layout Manager
window = QWidget()
layout = QVBoxLayout(window)
# Create a label Widget and add it to the layout
label = QLabel('Enter some text!')
layout.addWidget(label)
line_edit = QLineEdit()
layout.addWidget(line_edit)
# Create a QPushButton object with a caption on it
qbtn= QPushButton('Add Label')
# Add the QPushButton to the layout
layout.addWidget(qbtn)
# Close the application when the button is pressed
# Here I am using slots & signals, which I will demonstrate later in this tutorial
qbtn.clicked.connect(lambda:addLabel(layout, line_edit.text()))
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
Запустив этот код, мы увидим на экране следующее окно:
{.ezlazyload}
Это окно содержит 2 метки и 2 QLineEdit
добавленных с помощью
addRow()
. addRow()
принимает 2 аргумента:
- Текст метки (строка)
- Виджет ввода ( QWidget )
Метод автоматически создаст и добавит новый QLabel
с нашим labelText
в качестве текста. Кроме того, вы также можете добавить QLabel
вместо
строки, которая пропускает автоматическое преобразование:
layout.addRow(QLabel('Nickname:'), QLineEdit())
layout.addRow(QLabel('Score:'), QLineEdit())
Это также приводит к:
{.ezlazyload}
Виджеты
Теперь, когда мы знакомы с менеджерами компоновки, которые предлагает PyQt, давайте перейдем к тому, чем они управляют. Виджеты - это ключевая концепция Qt и, как следствие, PyQt.
Виджет отражает графический компонент пользовательского интерфейса. Пользовательский интерфейс состоит из нескольких виджетов, расположенных внутри окна. Каждый виджет содержит ряд атрибутов и методов, которые позволяют нам моделировать их внешний вид и поведение.
PyQt6 в настоящее время предлагает более 40 виджетов, и вы даже можете создавать свои собственные виджеты.
Начиная с PyQt5, базовые классы были перетасованы в разные модули. PyQt6 использует несколько фундаментальных высокоуровневых модулей, в том числе:
Qt
: Все модули, упомянутые ниже, могут быть упакованы вместе в один модуль.QtCore
:QtCore
содержит все основные неграфические модули, используемые другими модулями. В этом модуле реализованы сигналы, слоты и т. Д.QtWidgets
: этот модуль содержит большинство виджетов, доступных в PyQt6.QtGui
:QtGui
расширяетQtCore
и содержит компоненты графического интерфейса.QtSql
: этот модуль реализует интеграцию базы данных для баз данных SQL.QtMultimedia
: В этом модуле можно найти низкоуровневую мультимедийную функциональность.QtNetwork
: Классы, используемые для реализации сетевого программирования (сокеты, обработка SSL, сетевые сеансы, DNS, ...), можно найти в этом модуле.
В этом разделе мы сосредоточимся на модуле QtWidgets и предлагаемых им виджетах.
1. Этикетки
Самый популярный виджет, метка , чаще всего используется для
объяснения цели или использования вашего графического интерфейса,
например, для аннотирования того, для чего предназначено поле.
Мы можем создать метку, вызвав класс QLabel
Имейте в виду, что этот
виджет не обеспечивает взаимодействия с пользователем.
Мы можем изменить внешний вид этикетки различными способами:
setAlignment()
выравнивает заголовок в соответствии с константами выравнивания, которые могут быть следующими:Alignment.AlignLeft
Alignment.AlignRight
Alignment.AlignCenter
Alignment.AlignJustify
Text()
используется для получения заголовка метки.setText()
вместо получения заголовка установит заголовок метки.setIndent()
установит отступ.setWordWrap()
будет заключать слова в метку или нет, в зависимости от переданногоboolean
.
Теперь давайте создадим небольшое приложение PyQt6, используя только метки, чтобы отображать некоторую информацию о Бельгии:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
from PyQt6.QtCore import Qt
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget and the QVBoxLayout Layout Manager
window = QWidget()
layout = QVBoxLayout(window)
# Create a label beforehand
firstLabel = QLabel('Countrycode: BE')
secondLabel = QLabel('Brussels waffles are the best food ever.')
# Add labels to layout, creating an anonymous label while adding
layout.addWidget(firstLabel)
layout.addWidget(secondLabel, alignment = Qt.Alignment.AlignJustify)
layout.addWidget(QLabel('The Belgian flag consists of the colors black, yellow and red', wordWrap=True), alignment = Qt.Alignment.AlignLeft)
# using setText() we can change the caption of a label
firstLabel.setText('Belgium is a country located in Europe')
firstLabel.setAlignment(Qt.Alignment.AlignRight)
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
Вы можете QLabel
как с firstLabel
. Затем, даже после добавления его
в макет - вы можете манипулировать им и устанавливать текст,
выравнивание и т. Д. С помощью его методов установки. Последние
состояния, установленные установщиками, в конце будут отрисованы в окне.
Если вы не хотите создавать объекты заранее и не вызывать много методов
- вы можете просто создать виджет и добавить его сразу после, в самом
addWidget()
. Мы установили для аргументаwordWrap
QLabel
значение true, поскольку он немного длиннее двух других, и мы могли бы захотеть обернуть слова, если они длиннее, чем может вместить окно.
Примечание. Начиная с PyQt6, Qt
является частью PyQt6.QtCore
, а
параметры Align_
являются частью Alignment
приводит к
Qt.Alignment.Align_
. До PyQt6 Qt
был частью PyQtX
, а не QtCore
, а параметры Align_
были частью Qt
поэтому вызовы были бы больше
похожи на Qt.Align_
вместо этого.
Если мы запустим этот код, мы увидим наши три метки, выровненные в
соответствии с нашими настройками Alignment
{.ezlazyload}
2. Сигналы и слоты
Сигналы и слоты в PyQt используются для связи между объектами. Этот механизм является центральной особенностью фреймворка Qt.
Например, если пользователь нажмет кнопку «Удалить» , мы хотим, чтобы
вызывалась функция delete()
Для этого 2 виджета должны
взаимодействовать друг с другом.
Событие - это действие, выполняемое пользователем в нашем графическом интерфейсе.
Когда происходит событие, соответствующий виджет излучает сигнал. Виджеты, доступные в Qt, имеют много предопределенных сигналов, но вы всегда можете сделать дополнительные настраиваемые сигналы.
Слот - это функция, которая вызывается в ответ на сигнал . И снова у виджетов, доступных в Qt, есть много предопределенных слотов, но очень распространенной практикой является создание собственных.
Наиболее полезные функции сигналов и слотов включают в себя:
- Сигнал может быть подключен к другому сигналу
- Сигнал может быть подключен к одному или нескольким слотам
- Слот может быть подключен к одному или нескольким сигналам
Общий синтаксис подключения сигнала к слоту:
widget.signal.connect(slot_function)
Этот код соединит slot_function
с Widget.signal
, и всякий раз,
когда будет испускаться сигнал, будет вызываться функция
slot_function()
Чтобы избежать неожиданного поведения, важно аннотировать каждую функцию
слота с помощью декоратора @pyqtSlot()
from PyQt6.QtCore import pyqtSlot
# Slot function - Note the @pyqtSlot() annotation!
@pyqtSlot()
def hello_world():
print('Button is clicked, Hello World!')
Теперь давайте создадим приложение, которое использует механизм сигналов и слотов, поместив кнопку, которая просто выводит сообщение на консоль:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QPushButton
from PyQt6.QtCore import pyqtSlot
@pyqtSlot()
def hello_world():
print('You shall not pass!')
# Create the Qt Application
app = QApplication(sys.argv)
# Create a QPushButton Object
button = QPushButton('Click me')
# Connect the button to the hello_world slot function
button.clicked.connect(hello_world)
# Show the button to the user
button.show()
# Run the main Qt loop
sys.exit(app.exec())
Запустив этот код, мы увидим на экране следующее окно:
{.ezlazyload}
После запуска этого кода и нажатия кнопки на консоль выводится следующий текст:
You shall not pass!
3. Кнопки
Теперь, когда мы можем пометить другие компоненты графического
интерфейса в приложении - давайте взглянем на первый интерактивный
компонент, который мы будем реализовывать - QButton
. Кнопки приводят
к результатам - в нашем случае их можно использовать для вызова
определенных функций. Есть несколько предопределенных кнопок по
умолчанию: ОК, Да, Нет, Отмена, Применить и Закрыть , хотя вы также
можете добавить на них собственный текст.
Вы можете прикрепить обработчик событий к кнопке, которая запускает
функцию или любой другой фрагмент кода при нажатии кнопки. Давайте
создадим кнопку, которая позволяет пользователю добавлять QLabel
на
экран.
Как только пользователь вводит текст в QLineEdit
и было обнаружено
нажатие кнопки, мы собираем данные из QLineEdit
и используем этот
текст для установки текста нового QLabel
, который затем добавляется в
макет.
Поскольку кнопки ожидают, что вызываемая функция будет передана в
качестве обработчика события щелчка, мы определим новую функцию
add_label()
которую можно использовать для добавления любого QLabel
в указанный макет:
def addLabel(layout, text):
layout.addWidget(QLabel(text))
Теперь давайте напишем наш графический интерфейс и вызовем эту функцию с текстом, предоставленным пользователем:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit
def addLabel(layout, text):
layout.addWidget(QLabel(text))
# Create the Qt Application
app = QApplication(sys.argv)
# Create the parent Widget and the QVBoxLayout Layout Manager
window = QWidget()
layout = QVBoxLayout(window)
# Create a Qlabel Widget and add it to the layout
label = QLabel('Enter some text!')
layout.addWidget(label)
# Create a QLineEdit to collect user data
line_edit = QLineEdit()
layout.addWidget(line_edit)
# Create a QPushButton object with a caption on it
qbtn= QPushButton('Add Label')
layout.addWidget(qbtn)
# When clicked, perform a callable function - `addLabel()`
qbtn.clicked.connect(lambda:addLabel(layout, line_edit.text()))
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
После того, как мы запустим этот код, мы можем написать текст в
QLineEdit
, которое добавляется в макет как QLabel
когда мы нажимаем
на Add Label :
{.ezlazyload}
4. Редактирование строк
Мы дважды кратко рассмотрели QLineEdit
- давайте посмотрим, что он
предлагает. Как было показано ранее, он позволяет пользователям вводить
строку текста - это элементарный способ сбора пользовательских данных,
будь то для добавления или редактирования уже существующих данных.
Конечно, мы можем выполнять обычные операции, такие как копирование ,
вставка , отмена , повтор, во время написания текста внутри них.
Вот некоторые из распространенных методов, которые вы будете использовать с ними:
setAlignment()
снова выровняет заголовок в соответствии с константами выравниванияsetMaxLength()
устанавливает максимальное количество символов, которое пользователь не может превзойтиtext()
- извлекает текст вQLineEdit
setText()
- устанавливает текст вQLineEdit
clear()
сотрет все содержимоеQLineEdit
Давайте перепишем предыдущий пример, но на этот раз уже есть некоторый
предопределенный текст в QLineEdit
, изменим уже существующий QLabel
вместо добавления нового - и кратко рассмотрим использование слотов
PyQt , которые будут рассмотрены более подробно позже. в руководстве.
Мы создадим простейшее приложение для цитат, в котором есть корпус известных цитат и которое выдает случайные по запросу. Вы можете расширить этот список, добавив новый и нажав Добавить цитату , которая затем будет включена в пул котировок, когда вы решите получить новую случайную цитату с помощью Get Random Quote :
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit
from PyQt6.QtCore import pyqtSlot
import random
# Deifne helper functions as PyQt Slots
@pyqtSlot()
def randomQuote():
# Set label to random quote from the list
quoteLabel.setText(random.choice(quotes))
@pyqtSlot()
def addQuote():
# Add new quote to the list and clear the input field
quotes.append(newQuoteLineEdit.text())
newQuoteLineEdit.clear()
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout(window)
# Default quote list
quotes = ['Do or do not, there is no try.', 'The meaning of life is 42']
# Get a random quote for the user
quoteLabel = QLabel(random.choice(quotes))
# QLineEdit field to collect new quote information, and a button for it
newQuoteLineEdit = QLineEdit('Add new quote...')
addQuoteButton = QPushButton('Add New Quote')
# Button to get random quote
getQuoteButton = QPushButton('Get Random Quote')
# Add the previous Widgets to the layout
layout.addWidget(newQuoteLineEdit)
layout.addWidget(quoteLabel)
layout.addWidget(addQuoteButton)
layout.addWidget(getQuoteButton)
# On click - call the slots (functions)
getQuoteButton.clicked.connect(randomQuote)
addQuoteButton.clicked.connect(addQuote)
# Show the parent Widget
window.show()
# Run the main Qt loop
sys.exit(app.exec())
Это приводит к:
{.ezlazyload}
5. Поля со списком
Комбинированные поля позволяют пользователям выбирать из списка опций
- аналогично
<select>
в HTML. Это может быть достигнуто с помощью виджетаQComboBox
БазовыйQComboBox
для чтения, что означает, что пользователь должен выбирать исключительно из предопределенного списка и не может добавлять свои собственные параметры. Однако они также могут быть редактируемыми, что позволяет пользователю добавлять новый параметр, если он не соответствует его потребностям.
Ниже приведены наиболее часто используемые методы класса QComboBox:
addItem()
добавляет строку в коллекциюaddItems()
добавит каждую из строк в данном списке в коллекциюClear()
используется для удаления всех элементов в коллекцииcount()
используется для получения количества элементов в коллекцииcurrentText()
используется для получения текста текущего выбранного элементаitemText()
принимаетindex
и возвращает текст этого элементаcurrentIndex()
возвращает индекс текущего выбранного элемента
Давайте создадим мини-приложение для заказа, в котором пользователь выбирает элемент из меню и вводит комментарий для ресторана. Затем при нажатии кнопки пользователю показывается такой порядок:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QLineEdit, QComboBox
from PyQt6.QtCore import pyqtSlot
@pyqtSlot()
def placeOrder():
order_format = "Placed order for {} with comment '{}'"
layout.addWidget(QLabel(order_format.format(comboBox.currentText(), commentLineEdit.text())))
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout(window)
label1 = QLabel('Pick one of the following options:')
comboBox = QComboBox()
comboBox.addItems(['Pasta', 'Pizza', 'Lasagna'])
layout.addWidget(label1)
layout.addWidget(comboBox)
commentLineEdit = QLineEdit('Comment for the restaurant...')
placeOrderButton = QPushButton('Place order')
layout.addWidget(commentLineEdit)
layout.addWidget(placeOrderButton)
placeOrderButton.clicked.connect(placeOrder)
window.show()
sys.exit(app.exec())
Теперь разместим заказ и прикрепим к нему запрос:
{.ezlazyload}
6. Радиокнопки и флажки
Радиокнопки и флажки в основном используются с той же целью - позволяя кому-то выбрать вариант из нескольких. Единственное отличие состоит в том, что радиобоксы используются, когда мы хотим ограничить пользователя выбором одного варианта, а флажки используются, когда мы хотим разрешить пользователю выбирать несколько опций.
Например, мы можем заставить пользователя выбрать между новым или старым клиентом (не могут быть оба одновременно), но разрешить ему выбрать несколько услуг, на которые они хотели бы подписаться.
QCheckBox
, они реализованы как QRadioButton
и QCheckBox. Мы можем
проверить, отмечены ли они, установить для них отмеченный или снятый
флажок, установить их текст, а также получить текст их меток:
setChecked()
проверяет переключатель или флажокsetText()
устанавливает метку, связанную с кнопкой или флажкомtext()
получит метку кнопки / флажкаisChecked()
проверяет, выбрана ли кнопка / флажок.
Давайте создадим простое приложение, которое позволяет пользователям выбирать между парой услуг, которые предлагает воображаемая автомойка:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QRadioButton, QCheckBox
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout(window)
label_customer = QLabel('Pick one of the following options:')
# Create two radio buttons for the customer, assuming they might be a new customer
qradioButton = QRadioButton('Old Customer')
qradioButton2 = QRadioButton('New Customer')
qradioButton2.setChecked(True)
layout.addWidget(label_customer)
layout.addWidget(qradioButton)
layout.addWidget(qradioButton2)
label_service = QLabel("Pick the services you'd like:")
qCheckBox = QCheckBox('Car Wash')
qCheckBox2 = QCheckBox('Car Polish')
qCheckBox3 = QCheckBox('Vacuuming')
layout.addWidget(label_service)
layout.addWidget(qCheckBox)
layout.addWidget(qCheckBox2)
layout.addWidget(qCheckBox3)
window.show()
sys.exit(app.exec())
Это подсказывает нам приложение, похожее на опрос, которое позволяет нам выбирать, старый мы или новый клиент, и позволяет нам выбирать между услугами, которые предлагает автомойка:
{.ezlazyload}
7. Отображение данных с помощью виджета таблицы
QTableWidget
- это виджет, который без особой настройки позволяет нам
создавать в PyQt потрясающие таблицы, похожие на Excel, в которых мы
можем отображать данные.
Каждая таблица представляет собой таблицу на основе элементов со строками и столбцами.
Имейте в виду, что использование QTableWidget
- не единственный способ
отображения информации в таблицах. Модели данных также можно создавать и
отображать с помощью виджета QTableView
Хотя QTableWidget
своей сути
использует QTableView
под капотом для фактического создания таблицы,
поэтому мы будем использовать подход более высокого уровня, используя
таблицу с самого начала.
Учитывая столбцовую природу таблиц, мы можем удобно создавать словари для хранения данных для них или даже списков списков. При создании таблицы мы захотим установить количество столбцов и строк перед добавлением в нее каких-либо данных, а затем просто заполнить ее циклами:
setRowCount()
устанавливает количество строкsetColumnCount()
устанавливает количество столбцовsetHorizontalHeaderLabels()
устанавливает метки горизонтальных заголовков
Теперь давайте создадим простое приложение, которое содержит таблицу с несколькими северными странами и их столицами:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6.QtWidgets import (QApplication, QTableWidget, QTableWidgetItem)
from PyQt6.QtGui import QColor
# Declare our table values
nordic_countries = [('Norway', 'Oslo', 'Yes'),
('Iceland', 'Reykjavik', 'Yes'),
('Denmark', 'Copenhagen', 'Yes'),
('Belgium', 'Brussels','No')]
# Create the Qt Application
app = QApplication(sys.argv)
table = QTableWidget()
# Configure QTableWidget to have a number of rows equivalent to the amount of items from the nordic_countries struct
table.setRowCount(len(nordic_countries))
# Since every country in our 'nordic_countries' variable has the same amount of attributes
# we take the amount (3) of the first country and use this as the number of columns
table.setColumnCount(len(nordic_countries[0]))
# Set the Horizontal headers using setHorizontalHeaderLabels()
table.setHorizontalHeaderLabels(['Country', 'Capital', 'Scandinavian?'])
# Loop through every country in our 'nordic_countries' variable
for i, (country, capital, scandinavian_bool) in enumerate(nordic_countries):
# Make a QTableWidgetItem --> acts as an item in a table
item_country = QTableWidgetItem(country)
item_capital = QTableWidgetItem(capital)
item_scandinavian_bool = QTableWidgetItem(scandinavian_bool)
# Set the items: item, index, QTableWidgetItem
table.setItem(i, 0, item_country)
table.setItem(i, 1, item_capital)
table.setItem(i, 2, item_scandinavian_bool)
# Finally show the table
table.show()
# Launch the application
sys.exit(app.exec())
Запустив этот код, мы увидим на экране следующее окно:
{.ezlazyload}
8. Отображение данных с помощью виджета в виде дерева.
Деревянные виджеты действительно полезны для отображения древовидных
структур, таких как файловые иерархии или подсписки, относящиеся к
определенным спискам элементов. Чтобы приспособиться к этому типу
виджетов, PyQt предлагает QTreeWidget
.
Подобно тому, как QTableWidget
построен поверх QTableView
-
QTreeWidget
построен поверх QTreeView
.
Дерево состоит из заголовков и элементов . Заголовки - это имена столбцов. Каждому элементу может быть назначено несколько элементов. Элемент, например, может быть каталогом, в то время как его собственные элементы - это файлы в этом каталоге - или элемент может быть задачей, а его элементы - это люди, назначенные для этой задачи.
Вот некоторые из распространенных методов, которые мы будем использовать для работы с Tree Widgets:
setHeaderLabels()
устанавливает имя столбца для виджета дереваclear()
чтобы удалить все данные из ДереваeditItem()
для редактирования определенного элемента в деревеaddTopLevelItem()
для добавления элемента верхнего уровняaddTopLevelItems()
для добавления списка элементов верхнего уровня
Каждый элемент может быть назначен родительскому компоненту. Для
элемента верхнего уровня мы можем назначить его самому QTreeWidget
, а
для элементов более низкого уровня - мы можем назначить их уже
существующим элементам верхнего уровня. Вы можете пойти в этом
направлении настолько далеко, насколько захотите, однако слишком большое
количество уровней может сбивать с толку пользователя.
Давайте продолжим и составим быстрый список покупок - с Food
и
Furniture
в качестве предметов верхнего уровня (категории предметов,
которые мы хотели бы купить), а их дети будут фактическими предметами
сами:
#!/usr/bin/python
# Import all needed modules
import sys
from PyQt6 import QtWidgets
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout(window)
# Create the QTreeWidget Widget
tree_widget = QtWidgets.QTreeWidget()
# Set the column name for the Tree Widget
tree_widget.setHeaderLabels(['Items', 'Total Cost'])
# Populate first tree with QTreeWidgetItem objects
foodList = QtWidgets.QTreeWidgetItem(tree_widget, ['Food', '€ 15'])
QtWidgets.QTreeWidgetItem(foodList, ['Apples', '€ 6'])
QtWidgets.QTreeWidgetItem(foodList, ['Pears', '€ 4'])
QtWidgets.QTreeWidgetItem(foodList, ['Oranges', '€ 5'])
# Populate second tree with QTreeWidgetItem objects
furnitureList = QtWidgets.QTreeWidgetItem(tree_widget, ['Furniture', '€ 225'])
QtWidgets.QTreeWidgetItem(furnitureList, ['Table', '€ 150'])
QtWidgets.QTreeWidgetItem(furnitureList, ['Chairs', '€ 75'])
layout.addWidget(tree_widget)
window.show()
sys.exit(app.exec())
Запустив этот код, мы увидим на экране следующее окно:
Заключение
В этом руководстве мы перешли к PyQt - оболочке Python для популярной библиотеки Qt.
Мы рассмотрели некоторые ключевые концепции библиотеки и приступили к работе с ней через менеджеры компоновки, познакомились с виджетами и создали несколько действительно простых демонстрационных приложений, демонстрирующих, как вы можете их использовать.