Главная страница

ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов


Скачать 7.92 Mb.
НазваниеНиколай Прохоренок Владимир Дронов
Дата05.05.2023
Размер7.92 Mb.
Формат файлаpdf
Имя файлаПрохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен.pdf
ТипДокументы
#1111379
страница51 из 83
1   ...   47   48   49   50   51   52   53   54   ...   83
QtCore.Qt
, при сортировке регистр символов учитываться не будет, а если
CaseSensitive
— то будет;
 setSortLocaleAware(<Флаг>)
— если в качестве параметра указать значение
True
, при сортировке будут учитываться настройки локали;
 setFilterFixedString(<Фрагмент>)
— выбор из модели элементов, которые содержат заданный фрагмент. Если указать пустую строку, в результат попадут все строки из базовой модели. Метод является слотом;
 setFilterRegExp()
— выбор из модели элементов, соответствующих указанному регу- лярному выражению. Если указать пустую строку, в результат попадут все строки из базовой модели. Форматы метода: setFilterRegExp() setFilterRegExp(<Строка с шаблоном>)
В первом формате указывается экземпляр класса
QRegExp
, а во втором — строка с шаб- лоном регулярного выражения. Второй формат метода является слотом;
 setFilterWildcard(<Шаблон>)
— выбор из модели элементов, соответствующих указан- ной строке, которая может содержать подстановочные знаки:

528
Часть II. Библиотека PyQt 5

?
— один любой символ;

*
— нуль или более любых символов;

[...]
— диапазон значений.
Остальные символы трактуются как есть. Если в качестве параметра указать пустую строку, в результат попадут все элементы из базовой модели. Метод является слотом;
 setFilterKeyColumn(<Индекс>)
— задает индекс столбца, по которому будет произво- диться фильтрация. Если в качестве параметра указать значение
-1
, будут просматри- ваться элементы во всех столбцах. По умолчанию фильтрация производится по первому столбцу;
 setFilterRole(<Роль>)
— задает роль (см. разд. 22.3), по которой производится фильт- рация. По умолчанию сортировка производится по роли
DisplayRole
;
 setFilterCaseSensitivity(<Режим>)
— если в качестве параметра указать атрибут
CaseInsensitive класса
QtCore.Qt
, при фильтрации регистр символов учитываться не будет, а если
CaseSensitive
— то будет;
 setDynamicSortFilter(<Флаг>)
— если в качестве параметра указано значение
False
, при изменении базовой модели не будет производиться повторная сортировка или фильт- рация.
22.8. Использование делегатов
Все три представления, рассмотренные в разд. 22.5, дают возможность редактирования тек- ста их элементов. Например, в таблице (класс
QTableView
) мы можем дважды щелкнуть мышью на любом элементе, после чего в нем появится поле ввода. Введем в это поле новый текст и нажмем клавишу для подтверждения ввода или — для отмены.
За редактирование данных в представлении отвечает особый класс, называемый делегатом.
Он создает компонент, в котором будет выполняться редактирование значения (
редактор), задает его параметры, заносит в него само редактируемое значение, а по окончании редак- тирования переносит его назад, в модель.
По умолчанию в качестве делегата используется класс
QItemDelegate из модуля
QtWidgets
А в качестве компонента-редактора применяется однострочное поле ввода (класс
QLineEdit
, рассмотренный нами в главе 21).
Если мы хотим использовать для редактирования значения в каком-либо столбце или стро- ке другой редактор — например, многострочное поле ввода, поле ввода даты или целого числа, мы создадим другой делегат и назначим его представлению. Класс, представляющий делегат, должен быть унаследован от класса
QStyledItemDelegate
Иерархия наследования классов
QItemDelegate и
QStyledItemDelegate
:
QObject – QAbstractItemDelegate - QItemDelegate
QObject – QAbstractItemDelegate - QStyledItemDelegate
В новом классе-делегате нам следует переопределить следующие методы:
 createEditor()
— создает компонент, который будет использоваться для редактирова- ния данных, и задает его параметры. Формат метода: createEditor(self, <Родитель>, <Настройки>, <Индекс>)

Глава 22. Списки и таблицы
529
Вторым параметром передается ссылка на компонент-представление, который станет родителем создаваемого редактора (список, таблица или иерархический список). Треть- им параметром передается экземпляр класса
QStyleOptionViewItem
, хранящий дополни- тельные настройки делегата. Четвертым параметром можно получить индекс текущего элемента модели, представленный экземпляром класса
QModelIndex
Метод createEditor()
должен создать компонент-редактор, задать для него в качестве родителя компонент-представление (он передается вторым параметром) и вернуть соз- данный компонент в качестве результата.
Чтобы отказаться от использования собственного делегата и указать представлению ис- пользовать делегат по умолчанию, в методе createEditor()
следует вернуть значение
None
;
 setEditorData()
— заносит в компонент-редактор, созданный в методе createEditor()
, данные из текущего элемента модели, тем самым подготавливая редактор для редакти- рования этих данных. Формат метода: setEditorData(self, <Редактор>, <Индекс>)
Вторым параметром передается компонент-редактор, а третьим — индекс текущего эле- мента модели в виде экземпляра класса
QModelIndex
;
 updateEditorGeometry()
— задает размеры редактора соответственно размерам области, отведенной под него в компоненте-представлении. Формат: updateEditorGeometry(self, <Редактор>, <Настройки>, <Индекс>)
Вторым параметром передается ссылка на компонент-редактор, третьим — ссылка на экземпляр класса
QStyleOptionViewItem
, хранящий настройки делегата, четвертым — индекс текущего элемента модели, представленный экземпляром класса
QModelIndex
Размеры отведенной под редактор области мы можем получить из атрибута rect экземп- ляра класса
QStyleOptionViewItem
, переданного третьим параметром (полное описание класса
QStyleOptionViewItem приведено на странице https://doc.qt.io/qt-5/qstyleoption viewitem.html, а описание класса
QStyleOption
, от которого он порожден, — на страни- це https://doc.qt.io/qt-5/qstyleoption.html);
 setModelData()
— по окончании редактирования переносит значение из редактора в те- кущий элемент модели. Формат: setModelData(self, <Редактор>, <Модель>, <Индекс>)
Вторым параметром передается ссылка на компонент-редактор, третьим — ссылка на модель, четвертым — индекс текущего элемента модели, представленный экземпляром класса
QModelIndex
Полное описание класса
QAbstractItemDelegate можно найти на странице https://doc.qt.io/ qt-5/qabstractitemdelegate.html, класса
QitemDelegate
— на странице https://doc.qt.io/qt-5/ qitemdelegate.html, а класса
QStyledItemDelegate
— на странице https://doc.qt.io/qt-5/ qstyleditemdelegate.html.
Для назначения делегатов представлению следует применять следующие методы, унаследо- ванные от класса
QAbstractItemView
:
 setItemDelegate()
— назначает делегат для всего представления.
В параметре передается класс делегата, унаследованный от класса
QAbstractItemDelegate
;

530
Часть II. Библиотека PyQt 5
 setItemDelegateForColumn(<Индекс столбца>, )
— назначает делегат для столбца представления с указанным индексом. В параметре передается класс делегата, унаследованный от класса
QAbstractItemDelegate
;
 setItemDelegateForRow(<Индекс строки>, )
— назначает деле- гат для строки представления с указанным индексом. В параметре передается класс де- легата, унаследованный от класса
QAbstractItemDelegate
Если в какой-либо ячейке представления действуют одновременно два делегата, задан- ные для столбца и для строки, будет использоваться делегат, заданный для строки.
В качестве примера рассмотрим небольшое складское приложение (листинг 22.4), позво- ляющее править количество каких-либо имеющихся на складе позиций с применением поля ввода целочисленных значений (класс
QSpinBox
).
Листинг 22.4. Использование делегата from PyQt5 import QtCore, QtWidgets, QtGui import sys
# Создаем класс делегата class SpinBoxDelegate(QtWidgets.QStyledItemDelegate): def createEditor(self, parent, options, index):
# Создаем компонент-редактор, используемый для правки значений
# количества позиций editor = QtWidgets.QSpinBox(parent) editor.setFrame(False) editor.setMinimum(0) editor.setSingleStep(1) return editor def setEditorData(self, editor, index):
# Заносим в компонент-редактор значение количества value = int(index.model().data(index, QtCore.Qt.EditRole)) editor.setValue(value) def updateEditorGeometry(self, editor, options, index):
# Указываем размеры компонента-редактора editor.setGeometry(options.rect) def setModelData(self, editor, model, index):
# Заносим исправленное значение количества в модель value = str(editor.value()) model.setData(index, value, QtCore.Qt.EditRole); app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QTableView() window.setWindowTitle("Использование делегата") sti = QtGui.QStandardItemModel(parent = window) lst1 = ['Дискета', 'Бумага для принтера', 'Барабан для принтера'] lst2 = ["10", "3", "8"] for row in range(0, 3): item1 = QtGui.QStandardItem(lst1[row]) item2 = QtGui.QStandardItem(lst2[row]) sti.appendRow([item1, item2])

Глава 22. Списки и таблицы
531 sti.setHorizontalHeaderLabels(['Товар', 'Кол-во']) window.setModel(sti)
# Назначаем делегат второму столбцу таблицы window.setItemDelegateForColumn(1, SpinBoxDelegate()) window.setColumnWidth(0, 150) window.resize(300, 150) window.show() sys.exit(app.exec_())
Результат выполнения кода из листинга 22.4 показан на рис. 22.4.
Рис. 22.4. Использование делегата

ГЛ А В А
23
Работа с базами данных
PyQt 5 включает в свой состав средства для работы с базами данных формата SQLite,
MySQL, Oracle, PostgreSQL и др., не требующие установки никаких дополнительных
Python-библиотек. С помощью этих средств мы можем выполнять любые SQL-запросы и обрабатывать их результаты, получать доступ к отдельным таблицам базы, работать с тран- закциями, а также использовать особые модели для вывода содержимого таблиц или запро- сов в любом из компонентов-представлений, рассмотренных в главе 22.
В
НИМАНИЕ
!
Для успешного доступа к базам данных всех форматов, кроме SQLite и ODBC, требуется установить соответствующий клиент, поскольку в комплект поставки PyQt он не входит.
Все классы, обеспечивающие работу с базами данных и рассмотренные в этой главе, опре- делены в модуле
QtSql
23.1. Соединение с базой данных
За соединение с базой данных и обработку транзакций отвечает класс
QSqlDatabase
Чтобы установить соединение с базой, следует вызвать статический метод addDatabase()
этого класса. Формат вызова: addDatabase(<Формат базы данных>[, connectionName=""])
Первым параметром указывается строка, обозначающая формат открываемой базы данных.
Поддерживаются следующие форматы:
QMYSQL
(MySQL),
QODBC
(ODBC),
QPSQL
(PostgreSQL),
QSQLITE2
(SQLite версии 2) и
QSQLITE
(SQLite версии 3).
Вторым параметром можно задать имя соединения, что может оказаться полезным, если приложение работает сразу с несколькими базами. Если имя соединения не указано, уста- навливаемое соединение будет помечено как используемое по умолчанию.
Метод addDatabase()
возвращает экземпляр класса
QSqlDatabase
, представляющий базу данных, с которой установлено соединение. Теперь мы можем задать параметры базы, вос- пользовавшись одним из приведенных далее методов
QSqlDatabase
:
 setHostName(<Хост>)
— задает хост, на котором расположена база данных. Используется только для серверов данных наподобие MySQL;
 setPort(<Номер порта>)
— задает номер порта, через который будет выполнено под- ключение к хосту. Используется только для серверов данных и лишь в том случае, если сервер настроен на использование порта, отличного от порта по умолчанию;

Глава 23. Работа с базами данных
533
 setDatabaseName(<Имя или путь к базе данных>)
— задает имя базы данных (для серве- ров данных), путь к ней (для «настольных» баз данных, таких как SQLite) или полный набор параметров подключения (если используется ODBC);
 setUserName(<Имя>)
— задает имя для подключения к базе. Используется только для серверов данных;
 setPassword(<Пароль>)
— задает пароль для подключения к базе. Используется только для серверов данных;
 setConnectOptions(<Параметры>)
— задает набор дополнительных параметров для под- ключения к базе в виде строки. Набор поддерживаемых дополнительных параметров различен в зависимости от выбранного формата и приведен в документации по классу
QSqlDatabase
Для работы с базой предназначены следующие методы класса
QSqlDatabase
:
 open()
— открывает базу данных. Возвращает
True
, если база была успешно открыта, и
False
— в противном случае;
В
НИМАНИЕ
!
Перед созданием соединения с базой данных обязательно следует создать объект прило- жения (экземпляр класса QApplication). Если этого не сделать, PyQt не сможет загрузить драйвер указанного формата баз данных, и соединение не будет создано.
Открываемая база данных уже должна существовать на диске или сервере. Единственное исключение — база формата SQLite, которая, в случае ее отсутствия, будет создана авто- матически.
 open(<Имя>, <Пароль>)
— открывает базу данных с указанными именем и паролем. Воз- вращает
True
, если база была успешно открыта, и
False
— в противном случае;
 isOpen()
— возвращает
True
, если база данных в настоящее время открыта, и
False
— в противном случае;
 isOpenError()
— возвращает
True
, если при попытке открытия базы данных возникли ошибки, и
False
— в противном случае;
 transaction()
— запускает транзакцию, если формат базы поддерживает таковые. Если же формат базы не поддерживает транзакции, то не делает ничего. Возвращает
True
, если транзакция была успешно запущена, и
False
— в противном случае;
 commit()
— завершает транзакцию, если формат базы поддерживает таковые. Если же формат базы не поддерживает транзакции, то не делает ничего. Возвращает
True
, если транзакция была успешно завершена, и
False
— в противном случае;
 rollback()
— отменяет транзакцию, если формат базы поддерживает таковые. Если же формат базы не поддерживает транзакции, то не делает ничего. Возвращает
True
, если транзакция была успешно отменена, и
False
— в противном случае;
 lastError()
— возвращает сведения о последней возникшей при работе с базой ошибке в виде экземпляра класса
QSqlError
;
 connectionName()
— возвращает строку с именем соединения с базой или пустую строку для соединения по умолчанию;
 tables([type=Tables])
— возвращает список таблиц, хранящихся в базе. В параметре type можно указать тип таблиц в виде одного из атрибутов класса
QSql или их комбина- ции через оператор
|
:

534
Часть II. Библиотека PyQt 5

Tables

1
— обычные таблицы;

SystemTables

2
— служебные таблицы;

Views

4
— представления;

AllTables

255
— все здесь указанное;
 record(<Имя таблицы>)
— возвращает сведения о структуре таблицы с переданным име- нем, представленные экземпляром класса
QSqlRecord
, или пустой экземпляр этого клас- са, если таблицы с таким именем нет;
 primaryIndex(<Имя таблицы>)
— возвращает сведения о ключевом индексе таблицы с переданным именем, представленные экземпляром класса
QSqlIndex
, или пустой эк- земпляр этого класса, если таблицы с таким именем нет;
 close()
— закрывает базу данных.
Также нам могут пригодиться следующие статические методы класса
QSqlDatabase
:
 contains([connectionName=""])
— возвращает
True
, если имеется соединение с базой данных с указанным именем, и
False
— в противном случае;
 connectionNames()
— возвращает список имен всех созданных соединений с базами данных. Соединение по умолчанию обозначается пустой строкой;
 database([connectionName=""][, ][open=True])
— возвращает сведения о соединении с базой данных, имеющем указанное имя, в виде экземпляра класса
QSqlDatabase
. Если в параметре open указано значение
True
, база данных будет открыта. Если такового соеди- нения нет, возвращается некорректно сформированный экземпляр класса
QSqlDatabase
;
 cloneDatabase(, <Имя соединения>)
— создает копию указанного в пер- вом параметре соединения с базой и дает ему имя, заданное во втором параметре. Воз- вращаемый результат — экземпляр класса
QSqlDatabase
, представляющий созданную копию соединения;
 removeDatabase(<Имя соединения>)
— удаляет соединение с указанным именем. Соеди- нение по умолчанию обозначается пустой строкой;
 isDriverAvailable(<Формат>)
— возвращает
True
, если указанный в виде строки формат баз данных поддерживается PyQt, и
False
— в противном случае;
 drivers()
— возвращает список всех поддерживаемых PyQt форматов баз данных.
В листинге 23.1 показан код, выполняющий соединение с базами данных различных форма- тов и их открытие.
Листинг 23.1. Соединение с базами данных различных форматов from PyQt5 import QtWidgets, QtSql import sys
# Создаем объект приложения, иначе поддержка баз данных не будет работать app = QtWidgets.QApplication(sys.argv)
# Открываем базу данных SQLite, находящуюся в той же папке, что и файл
# с этой программой con1 = QtSql.QSqlDatabase.addDatabase('QSQLITE') con1.setDatabaseName('data.sqlite')

Глава 23. Работа с базами данных
535 con1.open() con1.close()
# Открываем базу данных MySQL con2 = QtSql.QSqlDatabase.addDatabase('QMYSQL') con2.setHostName("somehost"); con2.setDatabaseName("somedb"); con2.setUserName("someuser"); con2.setPassword("password"); con2.open(); con2.close()
# Открываем базу данных Microsoft Access через ODBC con3 = QtSql.QSqlDatabase.addDatabase("QODBC"); con3.setDatabaseName("DRIVER={Microsoft Access Driver (*.mdb)};
1   ...   47   48   49   50   51   52   53   54   ...   83


написать администратору сайта