Работа с Python PyQT Framework

Введение В этом руководстве мы рассмотрим, как использовать среду Python PyQT [https://www.riverbankcomputing.com/static/Docs/PyQt6/] для разработки графического интерфейса пользователя (GUI) для настольного приложения в Python. Популярные альтернативы Python для разработки графического интерфейса включают Tkinter [https://docs.python.org/3/library/tkinter.html], Kivy [https://kivy.org/#home], PySimpleGUI [https: // pysimplegui .readthedocs.io / en / latest /] и wxPython [https://www.wxpython.org/]. Примечание: на момент написания

Вступление

В этом руководстве мы рассмотрим, как использовать среду 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 являются:

  1. QVBoxLayout размещает виджеты вертикально.
  2. QHBoxLayout размещает виджеты по горизонтали.
  3. QGridLayout размещает виджеты в сетке.
  4. 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()) 

Запустив этот код, мы увидим на экране следующее окно:

QVBoxLayoutПример{.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()) 

Запустив этот код, мы увидим на экране следующее окно:

QHBoxLayoutПример{.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()) 

Запустив этот код, мы увидим на экране следующее окно:

QGridLayoutПример{.ezlazyload}

Это окно содержит 5 кнопок, которые расположены так, как мы указали в addWidget() . Сам метод принимает 3 аргумента:

  1. Виджет, который нужно разместить в сетке.
  2. Ряд, в который он должен быть помещен.
  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()) 

Запустив этот код, мы увидим на экране следующее окно:

QFormLayoutПример{.ezlazyload}

Это окно содержит 2 метки и 2 QLineEdit добавленных с помощью addRow() . addRow() принимает 2 аргумента:

  1. Текст метки (строка)
  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()) 

Запустив этот код, мы увидим на экране следующее окно:

Пример таблицыWigdet{.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()) 

Запустив этот код, мы увидим на экране следующее окно:

Пример Tree Wigdet

Заключение

В этом руководстве мы перешли к PyQt - оболочке Python для популярной библиотеки Qt.

Мы рассмотрели некоторые ключевые концепции библиотеки и приступили к работе с ней через менеджеры компоновки, познакомились с виджетами и создали несколько действительно простых демонстрационных приложений, демонстрирующих, как вы можете их использовать.

comments powered by Disqus