Время прочтения: 4 мин.

PyQt – один из самых распространённых инструментариев для создания графического интерфейса пользователя (GUI) на языке Python. В данной статье рассмотрим несколько его возможностей, которых с лихвой хватит для покрытия большинства задач, с которыми мы сталкиваемся каждый день.

Весь код графического интерфейса можно писать самостоятельно с нуля. А можно воспользоваться конструктором Qt Designer, который входит в состав Anaconda (в более старых версия его можно установить через pip install). В этом конструкторе можно собрать все необходимые элементы в одном или нескольких окнах, как того требует функциональность или личные предпочтения.

Итак, предположим, что перед нами стоит задача написать программу с GUI, которая будет разбивать один исходный файл с данными по разным городам на несколько конечных файлов, содержащих данные по каждому городу отдельно. В Qt Designer соберём вот такую конструкцию:

На основной форме (QWidget) мы разместили следующие элементы:

  1. QLineEdit под именем lineEdit. В нём будет отображено расположение выбранного файла.
  2. QToolButton под именем toolButton. Эта кнопка (…) будет вызывать окно для выбора файла с исходными данными.
  3. Три кнопки QPushButton (pushButton, pushButton_2, pushButton_3) для запуска процесса разбиения (Ок), закрытия окна (Закрыть) и предварительного чтения файла (Прочитать файл) соответственно.
  4. QCheckBox под именем checkBox. Этот элемент (Только выбранные) позволит ограничить итоговый набор файлов по выбранным условиям.
  5. QListWidget под именем listWidget. Здесь будет отображаться список городов, которые присутствуют в исходном файле. И здесь же можно будет выбрать только те города, по которым мы хотим получить данные. В свойстве selectionMode этого объекта выбираем MultiSelection.

Когда наш макет готов, сохраняем его. На этом этапе у нас есть файл sample.ui, содержащий информацию в формате XML. Конвертируем в привычный python-код командой

pyuic5 sample.ui –o sample.py 

в командной строке. Получаем следующий код:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(464, 230)
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(10, 180, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(9, 9, 133, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.toolButton = QtWidgets.QToolButton(Form)
        self.toolButton.setGeometry(QtCore.QRect(140, 8, 22, 22))
        self.toolButton.setObjectName("toolButton")
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(90, 180, 75, 23))
        self.pushButton_2.setObjectName("pushButton_2")
        self.checkBox = QtWidgets.QCheckBox(Form)
        self.checkBox.setGeometry(QtCore.QRect(10, 140, 141, 21))
        self.checkBox.setObjectName("checkBox")
        self.pushButton_3 = QtWidgets.QPushButton(Form)
        self.pushButton_3.setGeometry(QtCore.QRect(10, 50, 133, 23))
        self.pushButton_3.setObjectName("pushButton_3")
        self.listWidget = QtWidgets.QListWidget(Form)
        self.listWidget.setGeometry(QtCore.QRect(190, 9, 256, 192))
        self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        self.listWidget.setObjectName("listWidget")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton.setText(_translate("Form", "Ok"))
        self.toolButton.setText(_translate("Form", "..."))
        self.pushButton_2.setText(_translate("Form", "Закрыть"))
        self.checkBox.setText(_translate("Form", "Только выбранные"))
        self.pushButton_3.setText(_translate("Form", "Прочитать файл"))
        self.listWidget.setSortingEnabled(False)

Приступим к написанию кода основной программы. Нам потребуются дополнительные библиотеки:

import sys
import pandas as pd
from PyQt5.QtWidgets import QFileDialog

Следующие функции необходимо размещать в классе Ui_Form. Для выбора файла напишем функцию с QFileDialog.getOpenFileName():

def open_dialog_box(self):
        filename = QFileDialog.getOpenFileName()
        self.path = filename[0]
        self.lineEdit.setText(self.path)

Читаем выбранный файл и заполняем наш listWidget:

def readfile(self):
        self.df = pd.read_excel(self.path)
        self.uniqueCity = self.df["city"].unique()
        self.listWidget.clear()
        for item in self.uniqueCity:
            self.listWidget.addItem(item)

Не забудем про выход из программы:

    def quit(self):
        sys.exit()

В следующей функции проверяется, отмечена ли опция «Только выбранные». Если да, то будут созданы только файлы по выбранным в окне listWidget городам. Если нет, то будут созданы файлы по всем города, которые имеются в исходном файле.

def job(self):
        if self.checkBox.checkState() == 2:
            for city in self.listWidget.selectedItems():
                self.df[self.df['city']==city.text()].to_excel(f"excel_{city.text()}.xlsx", index=None)
        else:
            for city in self.uniqueCity:
                self.df[self.df['city']==city].to_excel(f"excel_{city}.xlsx", index=None)

Теперь свяжем написанные функции с элементами на форме, а также создадим два датафрейма, которые используются в функциях выше. Этот код необходимо дописать в функцию setupUi:

self.toolButton.clicked.connect(self.open_dialog_box)
self.pushButton_3.clicked.connect(self.readfile)
self.pushButton.clicked.connect(self.job)
self.pushButton_2.clicked.connect(self.quit)
self.uniqueCity = pd.DataFrame()
self.df = pd.DataFrame()

Осталось только написать код для запуска нашей программы:

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QMainWindow()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

Готово. Запускаем программу, выбираем файл, читаем его, ставим при необходимости отметку «Только выбранные», отмечаем нужные нам города, кликаем «Ок» и получаем отчеты в разрезе городов.

Мы описали лишь небольшую часть инструментов библиотеки PyQt, но большинство остальных программируется аналогичным способом. Теперь вашей программой могут пользоваться другие коллеги без необходимости разбираться в коде для ввода своих данных.