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

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


Скачать 7.92 Mb.
НазваниеНиколай Прохоренок Владимир Дронов
Дата05.05.2023
Размер7.92 Mb.
Формат файлаpdf
Имя файлаПрохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен.pdf
ТипДокументы
#1111379
страница73 из 83
1   ...   69   70   71   72   73   74   75   76   ...   83

746
Часть II. Библиотека PyQt 5 settings.sync() print("Считываем настройки") lv1 = settings.value("Значение 1") lv2 = settings.value("Значение 2") lv3 = settings.value("Значение 3") print(lv1, lv2, lv3, sep=" | ") if settings.contains("Значение 4"): print("Значение 4 в хранилище присутствует") else: print("Значение 4 в хранилище отсутствует") print("Очищаем хранилище") settings.clear()
В консоли это приложение выведет:
123 | Python | PyQt5.QtCore.QSize(640, 480)
Сохраняем настройки
Считываем настройки
123 | Python | PyQt5.QtCore.QSize(640, 480)
Значение 4 в хранилище отсутствует
Очищаем хранилище
Теперь давайте прочитаем из реестра путь к системному каталогу Документы, для чего воспользуемся пятым форматом конструктора класса
QSettings
(см. разд. 31.1):
>>> settings = QtCore.QSettings("HKEY_CURRENT_USER\\Software\\

Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",

QtCore.QSettings.NativeFormat)
>>> settings.value("Personal")
'D:\\Data\\Документы'
31.2.2. Группировка сохраняемых значений. Ключи
PyQt позволяет нам объединять сохраняемые в хранилище настроек значения по какому- либо признаку в особые группы, называемые ключами. Каждый ключ может содержать произвольное количество значений, а разные ключи могут содержать значения с одинако- выми именами. Для создания ключей можно применить два способа: простой и сложный.
Простой способ заключается в том, что в первом параметре метода setValue()
имя значе- ния предваряется именем ключа, в которое его следует поместить, и отделяется от него прямым слэшем: settings.setValue("Ключ 1/Значение 1", v1) lv1 = settings.value("Ключ 1/Значение 1")
Ключи можно вкладывать внутрь других ключей: settings.setValue("Ключ 2/Вложенный ключ 1/Значение 4", v4) lv4 = settings.value("Ключ 2/ Вложенный ключ 1/Значение 4")
Сложный способ (который на самом деле не так уж и сложен) пригодится, если нам нужно сохранить в одном ключе сразу несколько значений или же прочитать ряд значений из одного и того же ключа. Для его реализации следует выполнить следующие шаги:

Глава 31. Сохранение настроек приложений
747 1. Вызвать метод beginGroup(<Имя или путь ключа>)
класса
QSettings
. В качестве пара- метра методу передается имя ключа, к содержимому которого следует обратиться, или же целый «путь», если нужно создать вложенный ключ: settings.beginGroup("Ключ 1") settings.beginGroup("Ключ 2/Вложенный ключ 1")
2. Выполнить запись или чтение нужных значений с помощью знакомых нам методов setValue()
и value()
. В этом случае значения будут записаны в ключ, указанный в пре- дыдущем вызове метода beginGroup()
, или же прочитаны из этого ключа.
3. Вызвать метод endGroup()
класса
QSettings
Использование методов beginGroup()
и endGroup()
имеет ряд особенностей, о которых нам обязательно следует знать.

Методы remove()
, contains()
и childKeys()
, если их вызовы помещены между вызовами упомянутых ранее методов, действуют только внутри указанного в вызове метода beginGroup()
ключа. Так, метод contains()
будет искать значение с указанным именем только в текущем ключе.

Вызов метода remove()
с передачей ему в качестве параметра пустой строки удалит все значения, сохраненные в текущем ключе, не затрагивая содержимое других ключей и
«корня» хранилища.

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

Для проверки существования какого-либо ключа можно использовать метод contains()
, вызвав его в ключе предыдущего уровня или же в «корне» хранилища, если ключ никуда не вложен.

Для удаления ключа можно использовать метод remove()
, который в этом случае вызы- вается точно так же.
При использовании ключей для группировки записываемых в хранилище значений нам мо- гут пригодиться три следующих метода класса
QSettings
:
 group()
— возвращает строку с именем или путем текущего ключа;
 childGroups()
— возвращает список с именами всех ключей, что имеются в текущем;
 allKeys()
— возвращает список полных путей ко всем значениям, что имеются в храни- лище, включая значения, которые сохранены в ключах.
В листинге 31.2 приведен код приложения, чье окно сохраняет свое местоположение при завершении и восстанавливает при запуске. Помимо этого, при нажатии специальной кноп- ки выполняется сохранение текста, занесенного пользователем в поле ввода. Местоположе- ние окна и введенный текст сохраняются в разных группах.
Листинг 31.2. Использование ключей from PyQt5 import QtCore, QtWidgets import sys class MyWindow(QtWidgets.QWidget): def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent, flags=QtCore.Qt.Window)

748
Часть II. Библиотека PyQt 5 self.setWindowTitle("Использование ключей") self.settings = QtCore.QSettings("Прохоренок и Дронов",
"Использование ключей") vbox = QtWidgets.QVBoxLayout() self.txtLine = QtWidgets.QLineEdit(parent=self) vbox.addWidget(self.txtLine) btnSave = QtWidgets.QPushButton("&Сохранить текст") btnSave.clicked.connect(self.saveText) vbox.addWidget(btnSave) self.setLayout(vbox) if self.settings.contains("Окно/Местоположение"): self.setGeometry(self.settings.value("Окно/Местоположение")) else: self.resize(200, 50) if self.settings.contains("Данные/Текст"): self.txtLine.setText(self.settings.value("Данные/Текст")) def closeEvent(self, evt): self.settings.beginGroup("Окно") self.settings.setValue("Местоположение", self.geometry()) self.settings.endGroup() def saveText(self): self.settings.beginGroup("Данные") self.settings.setValue("Текст", self.txtLine.text()) self.settings.endGroup() app = QtWidgets.QApplication(sys.argv) window = MyWindow() window.show() sys.exit(app.exec_())
31.2.3. Запись списков
Часто бывает необходимо записать в хранилище настроек список каких-либо значений, а потом прочитать его оттуда. Для таких случаев PyQt также предоставляет весьма удобные инструменты.
Для записи списка в хранилище настроек следует выполнить следующую последователь- ность действий:
1. Вызвать метод beginWriteArray(<Имя или путь ключа>[, size=-1])
класса
QSettings
Первым параметром методу передается
<Имя или путь ключа>
, в котором будут сохране- ны элементы списка. В необязательном параметре size можно указать размер списка — если задать значение
-1
или вообще опустить этот параметр, PyQt определит размер со- храняемого списка самостоятельно.
2. Перебрать в цикле весь сохраняемый список. Внутри цикла выполнить следующие дей- ствия:
• вызвать метод setArrayIndex(<Индекс записываемого элемента>)
класса
QSettings
, тем самым дав PyQt понять, что сейчас будет выполнена запись содержимого эле- мента списка с индексом, заданным в параметре
<Индекс записываемого элемента>
;

Глава 31. Сохранение настроек приложений
749
• собственно, записать значение элемента списка, индекс которого был передан методу setArrayIndex()
на первом шаге.
3. Закончив запись элементов списка, уже по завершении выполнения цикла, в котором выполняется его перебор, вызвать метод endArray()
класса
QSettings
. Это послужит сигналом окончания записи списка.
Прочитать список из хранилища настроек можно точно таким же образом, за единственным исключением. На шаге 1 вместо метода beginWriteArray()
следует вызвать метод beginReadArray(<Имя или путь ключа>)
того же класса
QSettings
. Метод в качестве резуль- тата возвращает размер списка, ранее сохраненный методом beginWriteArray()
. Этот размер понадобится нам для формирования цикла, который будет выполнять выборку элементов списка.
На шаге 2, после вызова метода setArrayIndex()
, можно пользоваться методами remove()
и contains()
для удаления и проверки существования значения соответственно. Эти методы будут действовать только для элемента списка с указанным в вызове метода setArrayIndex()
индексом.
При использовании описанного здесь подхода в хранилище настроек создается следующая структура ключей и значений:
 ключ, чье имя (путь) было задано в вызове метода beginWriteArray()
. В этом ключе бу- дут созданы:
• значение size
— хранящее размер записанного списка. Этот размер будет возвращен методом beginReadArray()
;
• ключ, чье имя совпадает с индексом, заданным очередным вызовом метода setArrayIndex()
и увеличенным на единицу.
В этом ключе будут созданы значения, записываемые последующими вызовами метода setValue()
В качестве примера рассмотрим листинг 31.3, в котором приведен код, формирующий спи- сок строк, записывающий его в хранилище настроек, считывающий впоследствии и выво- дящий на экран.
Листинг 31.3. Запись и чтение списков from PyQt5 import QtCore, QtWidgets import sys app = QtWidgets.QApplication(sys.argv) settings = QtCore.QSettings("Прохоренок и Дронов", "Тест 2") l = ["Python", "Ruby", "PHP", "JavaScript"] print(l) print("Сохраняем список") settings.beginWriteArray("Список") for i, el in enumerate(l): settings.setArrayIndex(i) settings.setValue("Элемент", el) settings.endArray() settings.sync() print("Считываем список")

750
Часть II. Библиотека PyQt 5 ll = [] lSize = settings.beginReadArray("Список") for i in range(lSize): settings.setArrayIndex(i) ll.append(settings.value("Элемент")) settings.endArray() print(ll) settings.clear()
В консоли это приложение выведет следующее:
['Python', 'Ruby', 'PHP', 'JavaScript']
Сохраняем список
Считываем список
['Python', 'Ruby', 'PHP', 'JavaScript']
31.3. Вспомогательные методы класса QSettings
Теперь рассмотрим вспомогательные методы класса
QSettings
, которые могут пригодиться в некоторых случаях.
 status()
— возвращает обозначение состояния, в котором пребывает хранилище на- строек после выполнения очередной операции, выраженное в виде одного из следующих атрибутов класса
QSettings
:

NoError

0
— операция была успешно выполнена, и никаких ошибок не возникло;

AccessError

1
— возникла ошибка доступа к реестру или INI-файлу (возможно, была произведена попытка чтения недоступного для текущего пользователя ключа реестра или файла или же запись в файл, недоступный для записи);

FormatError

2
— была выполнена попытка открыть некорректно сформированный
INI-файл;
 isWritable()
— возвращает
True
, если хранилище настроек доступно для записи, и
False в противном случае (например, если хранилищем является INI-файл, на запись в который текущий пользователь не имеет прав).
31.4. Где хранятся настройки?
Осталось выяснить, где же хранятся настройки, которые мы записали в хранилище. Не бу- дем рассматривать случай, когда экземпляр класса
QSettings создан с применением пятого формата конструктора, в котором месторасположение хранилища указано напрямую — в виде конкретного пути к ключу реестра или INI-файлу (за подробностями — к разд. 31.1).
Сосредоточимся на первых четырех форматах, в которых месторасположение хранилища не указано.

Если выполняется сохранение в реестр Windows (в качестве типа хранилища указаны атрибуты
NativeFormat
,
Registry32Format или
Registry64Format
):
• если выполняется сохранение на уровне текущего пользователя (в качестве диапазо- на указан атрибут
UserScope
):
 если название приложения указано (т. е. задан параметр application конструкто- ра) — в ветви
HKEY_CURRENT_USER\Software\<Название организации>\<Название при- ложения>
;

Глава 31. Сохранение настроек приложений
751
 если название приложения не указано (т. е. параметр application конструктора не задан) — в ветви
HKEY_CURRENT_USER\Software\<Название организации>\
OrganizationDefaults
(похоже, что в таком случае PyQt считает, что заданные настройки применяются сразу ко всем приложениям, разработанным данной организацией);
• если выполняется сохранение на уровне системы (в качестве диапазона указан атри- бут
SystemScope
):
 если название приложения указано — в ветви
HKEY_LOCAL_MACHINE\Software\<Название организации>\<Название приложения>
;
 если название приложения не указано — в ветви
HKEY_LOCAL_MACHINE\Software\<Название организации>\OrganizationDefaults
Приложения, работающие под управлением 32-разрядной редакции Python на 64-раз- рядной редакции Windows, если указан тип хранилища, отличный от
Registry64Format
, сохраняют настройки в ветвях
HKEY_LOCAL_MACHINE\Software\WOW6432node\<Название организации>\<Название приложения>
и
HKEY_LOCAL_MACHINE\Software\WOW6432node\
<Название организации>\OrganizationDefaults соответственно.

Если выполняется сохранение в INI-файл (в качестве типа хранилища указан атрибут
IniFormat
):
• если выполняется сохранение на уровне текущего пользователя:
 если название приложения указано — в файле
<каталог пользовательского про- филя>\AppData\Roaming\<Название организации>\<Название приложения>.ini
;
 если название приложения не указано — в файле
<каталог пользовательского профиля>\AppData\Roaming\<Название организации>.ini
;
• если выполняется сохранение на уровне системы:
 если название приложения указано — в файле
<корневой каталог системного дис- ка>\ProgramData\<Название организации>\<Название приложения>.ini;
 если название приложения не указано — в файле
<корневой каталог системного диска>\ProgramData\<Название организации>.ini

ГЛ А В А
32
Приложение «Судоку»
В завершение в качестве примера напишем на языке Python с применением библиотеки
PyQt приложение «Судоку». Оно предназначено для создания и решения головоломок судоку и позволит, помимо всего прочего, сохранять головоломки в файлах, загружать их из файлов и выводить на печать.
Изначально приложение было разработано Н. Прохоренком в 2011 году на языке C++. Для этой книги оно переписано на Python и несколько усовершенствовано В. Дроновым в конце
2017 года.
32.1. Правила судоку
Судоку — традиционная японская числовая головоломка (иногда ее неправильно называют магическим квадратом). Далее приведены правила ее решения (полное описание судоку можно найти по интернет-адресу https://ru.wikipedia.org/wiki/Судоку).

Поле судоку представляет собой квадрат, разбитый на 81 ячейку (9 столбцов по 9 строк).
Каждые 9 ячеек объединены в группу 3 × 3 — итого получается 9 групп.

В каждую ячейку поля можно подставить только одну цифру от 1 до 9.

Ячейки группы не должны содержать одинаковых цифр.

Одна и та же цифра должна присутствовать в каждой строке и каждом столбце поля только один раз.
На рис. 32.1 приведен пример решенной судоку.
Рис. 32.1. Решенная судоку (группы выделены утолщенными рамками)

Глава 32. Приложение «Судоку»
753
Как правило, судоку решают вдвоем: один игрок произвольно расставляет цифры в некото- рых ячейках поля, а второй, собственно, решает головоломку.
32.2. Описание приложения «Судоку»
Приложение «Судоку» выполнено в традиционном ключе, присущем обычным Windows- приложениям. Ее окно (рис. 32.2) включает в себя главное меню, панель инструментов, ос- новное содержимое — поле судоку и набор кнопок для установки цифр в ячейки, и строку состояния.
В самом поле судоку группы ячеек выделены различными цветами фона: оранжевым и светло-серым. Установленные в них цифры выводятся черным цветом.
Одна из ячеек является активной — именно с активной ячейкой осуществляется взаимо- действие. Активная ячейка закрашена желтым цветом (на рис. 32.2 это ячейка с цифрой 4).
Чтобы сделать какую-либо ячейку активной, следует:
 либо, пользуясь клавишами-стрелками, переместить на нее желтый фокус выделения;
 либо просто щелкнуть на ней мышью.
Чтобы установить в активную ячейку какую-либо цифру, следует:
 либо нажать соответствующую кнопку в наборе, расположенном ниже поля;
 либо нажать соответствующую цифровую клавишу.
Чтобы убрать цифру из активной ячейки, нужно:
 либо нажать кнопку Х, что находится в расположенном под полем наборе;
 либо нажать клавишу пробела, или .
Рис. 32.2. Окно приложения «Судоку»

754
Часть II. Библиотека PyQt 5
Чтобы случайно не занести в какую-либо ячейку другую цифру, есть возможность заблоки- ровать ее. Для этого следует сделать нужную ячейку активной и нажать клавишу .
В заблокированной ячейке цифра выводится красным шрифтом (на рис. 32.2 заблокирована ячейка с цифрой 5). Отметим, что блокировать можно только ячейки, содержащие цифры.
Снять блокировку с ячейки можно, сделав ее активной и нажав клавишу .
Главное меню приложения содержит следующие пункты:
 меню Файл:

Новый
(с ним связана комбинация клавиш +) — очистка поля;

Открыть
(+) — загрузка сохраненной ранее головоломки из выбранного пользователем файла;

Сохранить
(+) — сохранение головоломки в файле с указанным пользова- телем именем.
При выборе этого пункта производится сохранение в полном формате, т. е. для каж- дой ячейки, помимо находящейся в ней цифры, сохраняется признак того, заблоки- рована ли она;

Сохранить компактно
— сохранение головоломки в файле в компактном формате.
Компактный формат не предусматривает хранения признака блокировки ячейки.
Вследствие этого файл, сохраненный в компактном формате, вдвое меньше полно- форматного.
При открытии файла, сохраненного в компактном формате, производится автомати- ческая блокировка всех ячеек, содержащих цифры;

Печать
(+
) — вывод головоломки на печать;

Предварительный просмотр
— просмотр головоломки в том виде, в котором она будет выведена на печать;

Параметры страницы
— настройка параметров печатаемой страницы;

Выход
(+) — завершение работы приложения;
 меню Правка:

Копировать
1   ...   69   70   71   72   73   74   75   76   ...   83


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