ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 840
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
— устанавливает текстовые данные в формате HTML (MIME-тип text/html
): data.setHtml("Перетаскиваемый HTML-текст")
html()
— возвращает текстовые данные в формате HTML;
hasHtml()
— возвращает значение
True
, если объект содержит текстовые данные в фор- мате HTML, и
False
— в противном случае;
setUrls(<Список URI-адресов>)
— устанавливает список URI-адресов (MIME-тип text/uri-list
). В качестве значения указывается список с экземплярами класса
QUrl
С помощью этого MIME-типа можно обработать перетаскивание файлов: data.setUrls([QtCore.QUrl("https://www.google.ru/")])
urls()
— возвращает список URI-адресов: uri = e.mimeData().urls()[0].toString()
hasUrls()
— возвращает значение
True
, если объект содержит список URI-адресов, и
False
— в противном случае;
setImageData(<Объект изображения>)
— устанавливает изображение (MIME-тип application/x-qt-image
). В качестве значения можно указать, например, экземпляр класса
QImage или
QPixmap
: data.setImageData(QtGui.QImage("pixmap.png")) data.setImageData(QtGui.QPixmap("pixmap.png"))
imageData()
— возвращает объект изображения (тип возвращаемого объекта зависит от типа объекта, указанного в методе setImageData()
);
hasImage()
— возвращает значение
True
, если объект содержит изображение, и
False
— в противном случае;
setData(
— позволяет установить данные произвольного MIME- типа. В первом параметре указывается MIME-тип в виде строки, а во втором парамет- ре — экземпляр класса
QByteArray с данными. Метод можно вызвать несколько раз с различными MIME-типами. Вот пример передачи текстовых данных: data.setData("text/plain",
QtCore.QByteArray(bytes("Данные", "utf-8")))
data(
— возвращает экземпляр класса
QByteArray с данными, соответст- вующими указанному MIME-типу;
hasFormat(
— возвращает значение
True
, если объект содержит данные ука- занного MIME-типа, и
False
— в противном случае;
formats()
— возвращает список с поддерживаемыми объектом MIME-типами;
removeFormat(
— удаляет данные, соответствующие указанному MIME-типу;
clear()
— удаляет все данные.
Если необходимо перетаскивать данные какого-либо специфического типа, нужно наследо- вать класс
QMimeData и переопределить в нем методы retrieveData()
и formats()
. За под- робной информацией по этому вопросу обращайтесь к документации.
Глава 19. Обработка сигналов и событий
429 19.10.3. Обработка сброса
Прежде чем обрабатывать перетаскивание и сбрасывание объекта, необходимо сообщить системе, что компонент может обрабатывать эти события. Для этого внутри конструктора компонента следует вызвать метод setAcceptDrops()
, унаследованный от класса
QWidget
, и передать этому методу
True
: self.setAcceptDrops(True)
Обработка перетаскивания и сброса объекта выполняется следующим образом:
1.
Внутри метода dragEnterEvent()
компонента проверяется MIME-тип перетаскиваемых данных и действие. Если компонент способен обработать сброс этих данных и соглаша- ется с предложенным действием, необходимо вызвать метод acceptProposedAction()
объекта события. Если нужно изменить действие, методу setDropAction()
объекта собы- тия передается новое действие, а затем у того же объекта вызывается метод accept()
вместо acceptProposedAction()
2.
Если необходимо ограничить область сброса некоторым участком компонента, следует дополнительно определить в нем метод dragMoveEvent()
. Этот метод будет постоянно вызываться при перетаскивании внутри области компонента. При достижении указате- лем мыши нужного участка компонента следует вызвать метод accept()
и передать ему экземпляр класса
QRect с координатами и размером этого участка. В этом случае при перетаскивании внутри участка метод dragMoveEvent()
повторно вызываться не будет.
3.
Внутри метода dropEvent()
компонента производится обработка сброса.
Обработать события, возникающие в процессе перетаскивания и сбрасывания, позволяют следующие методы класса
QWidget
:
dragEnterEvent(self,
— вызывается, когда перетаскиваемый объект входит в область компонента. Через параметр
доступен экземпляр класса
QDragEnterEvent
;
dragLeaveEvent(self,
— вызывается, когда перетаскиваемый объект покидает область компонента. Через параметр
доступен экземпляр класса
QDragLeaveEvent
;
dragMoveEvent(self,
— вызывается при перетаскивании объекта внутри об- ласти компонента. Через параметр
доступен экземпляр класса
QDragMoveEvent
;
dropEvent(self,
— вызывается при сбрасывании объекта в области компонен- та. Через параметр
доступен экземпляр класса
QDropEvent
Класс
QDragLeaveEvent наследует класс
QEvent и не несет никакой дополнительной инфор- мации. Достаточно просто знать, что перетаскиваемый объект покинул область компонента.
Цепочка наследования остальных классов выглядит так:
QEvent — QDropEvent — QDragMoveEvent — QDragEnterEvent
Класс
QDragEnterEvent не содержит собственных методов, но наследует все методы классов
QDropEvent и
QDragMoveEvent
Класс
QDropEvent поддерживает следующие методы:
mimeData()
— возвращает экземпляр класса
QMimeData с перемещаемыми данными и ин- формацией о MIME-типе;
pos()
— возвращает экземпляр класса
QPoint с целочисленными координатами сбрасы- вания объекта;
430
Часть II. Библиотека PyQt 5
posF()
— возвращает экземпляр класса
QPointF
с вещественными координатами сбрасы- вания объекта;
possibleActions()
— возвращает комбинацию возможных действий при сбрасывании.
Вот пример определения значений: if e.possibleActions() & QtCore.Qt.MoveAction: print("MoveAction") if e.possibleActions() & QtCore.Qt.CopyAction: print("CopyAction")
proposedAction()
— возвращает действие по умолчанию при сбрасывании;
acceptProposedAction()
— сообщает о готовности принять переносимые данные и согласии с действием, возвращаемым методом proposedAction()
. Метод acceptProposedAction()
(или метод accept()
, поддерживаемый классом
QDragMoveEvent
) необходимо вызвать внутри метода dragEnterEvent()
, иначе метод dropEvent()
вызван не будет;
setDropAction(<Действие>)
— позволяет указать другое действие при сбрасывании. По- сле изменения действия следует вызвать метод accept()
, а не acceptProposedAction()
;
dropAction()
— возвращает действие, которое должно быть выполнено при сбрасыва- нии. Оно может не совпадать со значением, возвращаемым методом proposedAction()
, если действие было изменено с помощью метода setDropAction()
;
keyboardModifiers()
— позволяет определить, какие клавиши-модификаторы (
mouseButtons()
— позволяет определить кнопки мыши, которые были нажаты в процес- се переноса данных;
source()
— возвращает ссылку на компонент внутри приложения, являющийся источ- ником события, или значение
None
, если данные переносятся из другого приложения.
Теперь рассмотрим методы класса
QDragMoveEvent
:
accept([
— сообщает о согласии с дальнейшей обработкой события. В качест- ве параметра можно указать экземпляр класса
QRect с координатами и размерами прямо- угольной области, в которой будет доступно сбрасывание;
ignore([
— отменяет операцию переноса данных. В качестве параметра можно указать экземпляр класса
QRect с координатами и размерами прямоугольной области, в которой сбрасывание запрещено;
answerRect()
— возвращает экземпляр класса
QRect с координатами и размерами прямо- угольной области, в которой произойдет сбрасывание, если событие будет принято.
Некоторые компоненты в PyQt уже поддерживают технологию drag & drop — так, в одно- строчное текстовое поле можно перетащить текст из другого приложения. Поэтому, прежде чем изобретать свой «велосипед», убедитесь, что поддержка технологии в компоненте не реализована.
19.11. Работа с буфером обмена
Помимо технологии drag & drop, для обмена данными между приложениями используется буфер обмена — одно приложение помещает данные в буфер обмена, а второе приложение
Глава 19. Обработка сигналов и событий
431
(или то же самое) может их извлечь. Получить ссылку на глобальный объект буфера обмена позволяет статический метод clipboard()
класса
QApplication
: clipboard = QtWidgets.QApplication.clipboard()
Класс
QClipboard поддерживает следующие методы:
setText(<Текст>)
— заносит текст в буфер обмена: clipboard.setText("Текст")
text()
— возвращает из буфера обмена текст или пустую строку;
text(<Тип>)
— возвращает кортеж из двух строк: первая хранит текст из буфера обмена, вторая — название типа. В параметре
<Тип>
могут быть указаны значения "plain"
(про- стой текст),
"html"
(HTML-код) или пустая строка (любой тип);
setImage(
— заносит в буфер обмена изображение, представленное экземпля- ром класса
QImage
: clipboard.setImage(QtGui.QImage("image.jpg"))
image()
— возвращает из буфера обмена изображение, представленное экземпляром класса
QImage
, или пустой экземпляр этого класса;
setPixmap(
— заносит в буфер обмена изображение, представленное экземп- ляром класса
QPixmap
: clipboard.setPixmap(QtGui.QPixmap("image.jpg"))
pixmap()
— возвращает из буфера обмена изображение, представленное экземпляром класса
QPixmap
, или пустой экземпляр этого класса;
setMimeData(
— позволяет сохранить в буфере данные любого типа, пред- ставленные экземпляром класса
QMimeData
(см. разд. 19.10.2);
mimeData([<Режим>])
— возвращает данные, представленные экземпляром класса
QMimeData
;
clear()
— очищает буфер обмена.
Отследить изменение состояния буфера обмена позволяет сигнал dataChanged
. Назначить обработчик этого сигнала можно так:
QtWidgets.qApp.clipboard().dataChanged.connect(on_change_clipboard)
19.12. Фильтрация событий
События можно перехватывать еще до того, как они будут переданы компоненту. Для этого необходимо создать класс, который является наследником класса
QObject
, и переопределить в нем метод eventFilter(self, <Объект>,
. Через параметр
<Объект>
доступна ссылка на компонент, а через параметр
— на объект с дополнительной информаци- ей о событии. Этот объект различен для разных типов событий — так, для события
MouseButtonPress объект будет экземпляром класса
QMouseEvent
, а для события
KeyPress
— экземпляром класса
QKeyEvent
. Из метода eventFilter()
следует вернуть значение
True
, если событие не должно быть передано дальше, и
False
— в противном случае. Вот пример такого класса-фильтра, перехватывающего нажатие клавиши : class MyFilter(QtCore.QObject): def __init__(self, parent=None):
QtCore.QObject.__init__(self, parent)
432
Часть II. Библиотека PyQt 5 def eventFilter(self, obj, e): if e.type() == QtCore.QEvent.KeyPress: if e.key() == QtCore.Qt.Key_B: print("Событие от клавиши не дойдет до компонента") return True return QtCore.QObject.eventFilter(self, obj, e)
Далее следует создать экземпляр этого класса, передав в конструктор ссылку на компонент, а затем вызвать у того же компонента метод installEventFilter()
, передав в качестве единственного параметра ссылку на объект фильтра. Вот пример установки фильтра для надписи: self.label.installEventFilter(MyFilter(self.label))
Метод installEventFilter()
можно вызвать несколько раз, передавая ссылку на разные объекты фильтров. В этом случае первым будет вызван фильтр, который был добавлен по- следним. Кроме того, один фильтр можно установить сразу в нескольких компонентах.
Ссылка на компонент, который является источником события, доступна через второй пара- метр метода eventFilter()
Удалить фильтр позволяет метод removeEventFilter(<Фильтр>)
, вызываемый у компонента, для которого был назначен этот фильтр. Если таковой не был установлен, при вызове мето- да ничего не произойдет.
19.13. Искусственные события
Для создания искусственных событий применяются следующие статические методы из класса
QCoreApplication
:
sendEvent(
— немедленно посылает событие компоненту и воз- вращает результат выполнения обработчика;
postEvent(
— добавляет собы- тие в очередь. Параметром priority можно передать приоритет события, использовав один из следующих атрибутов класса
QtCore.Qt
:
HighEventPriority
(
1
, высокий прио- ритет),
NormalEventPriority
(
0
, обычный приоритет — значение по умолчанию) и
LowEventPriority
(
-1
, низкий приоритет). Этот метод является потокобезопасным, сле- довательно, его можно использовать в многопоточных приложениях для обмена собы- тиями между потоками.
В параметре
указывается ссылка на объект, которому посылается событие, а в параметре
— объект события. Последний может быть экземпляром как стандарт- ного (например,
QMouseEvent
), так и пользовательского класса, являющегося наследником класса
QEvent
. Вот пример отправки события
QEvent.MouseButtonPress компоненту label
: e = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress,
QtCore.QPointF(5, 5), QtCore.Qt.LeftButton,
QtCore.Qt.LeftButton, QtCore.Qt.NoModifier)
QtCore.QCoreApplication.sendEvent(self.label, e)
Для отправки пользовательского события необходимо создать класс, наследующий
QEvent
В этом классе следует зарегистрировать пользовательское событие с помощью статического метода registerEventType()
и сохранить идентификатор события в атрибуте класса:
Глава 19. Обработка сигналов и событий
433 class MyEvent(QtCore.QEvent): idType = QtCore.QEvent.registerEventType() def __init__(self, data):
QtCore.QEvent.__init__(self, MyEvent.idType) self.data = data def get_data(self): return self.data
Вот пример отправки события класса
MyEvent компоненту label
:
QtCore.QCoreApplication.sendEvent(self.label, MyEvent("512"))
Обработать пользовательское событие можно с помощью методов event(self,
или customEvent(self,
: def customEvent(self, e): if e.type() == MyEvent.idType: self.setText("Получены данные: {0}".format(e.get_data()))
ГЛ А В А
20
Размещение компонентов в окнах
При размещении в окне нескольких компонентов возникает вопрос их взаимного располо- жения и минимальных размеров. Следует помнить, что по умолчанию размеры окна можно изменять, а значит, необходимо перехватывать событие изменения размеров и производить перерасчет позиции и размера каждого компонента. Библиотека PyQt избавляет нас от лиш- них проблем и предоставляет множество компонентов-контейнеров, которые производят такой перерасчет автоматически. Все, что от нас требуется, это выбрать нужный контейнер, добавить в него компоненты в определенном порядке, а затем поместить контейнер в окно или в другой контейнер.
20.1. Абсолютное позиционирование
Прежде чем изучать контейнеры, рассмотрим возможность абсолютного позиционирования компонентов в окне. Итак, если при создании компонента указана ссылка на родительский компонент, то он выводится в позицию с координатами
(0, 0)
. Иными словами, если мы добавим несколько компонентов, то все они отобразятся в одной и той же позиции, нало- жившись друг на друга. Последний добавленный компонент окажется на вершине этой кучи, а остальные компоненты станут видны лишь частично или вообще не видны. Размеры добавляемых компонентов будут соответствовать их содержимому.
Для перемещения компонента можно воспользоваться методом move()
, а для изменения размеров — методом resize()
. Выполнить одновременное изменение позиции и размеров позволяет метод setGeometry()
. Все эти методы, а также множество других, позволяющих изменять позицию и размеры, мы уже рассматривали в разд. 18.3 и 18.4. Если компонент не имеет родителя, эти методы изменяют характеристики окна, а если родительский компо- нент был указан, они изменяют характеристики только самого компонента.
Для примера выведем внутри окна надпись и кнопку, указав позицию и размеры для каждо- го компонента (листинг 20.1).
Листинг 20.1. Абсолютное позиционирование
# -*- coding: utf-8 -*- from PyQt5 import QtWidgets import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() window.setWindowTitle("Абсолютное позиционирование")
Глава 20. Размещение компонентов в окнах
435 window.resize(300, 120) label = QtWidgets.QLabel("Текст надписи", window) button = QtWidgets.QPushButton("Текст на кнопке", window) label.setGeometry(10, 10, 280, 60) button.resize(280, 30) button.move(10, 80) window.show() sys.exit(app.exec_())
Абсолютное позиционирование имеет следующие недостатки:
при изменении размеров окна необходимо самостоятельно пересчитывать и изменять характеристики всех компонентов в программном коде;
при указании фиксированных размеров надписи на компонентах могут выходить за их пределы. Помните, что в разных операционных системах используются разные стили оформления, в том числе и характеристики шрифта. Подогнав размеры в одной опера- ционной системе, можно прийти в ужас при виде приложения в другой операционной системе, где размер шрифта в два раза больше. Поэтому лучше вообще отказаться от указания фиксированных размеров или задавать размер и название шрифта для каждого компонента явно. Кроме того, приложение может поддерживать несколько языков ин- терфейса, а поскольку длина слов в разных языках различается, это также станет причи- ной искажения компонентов.
1 ... 36 37 38 39 40 41 42 43 ... 83
20.2. Горизонтальное и вертикальное выравнивание
Компоненты-контейнеры (их еще называют менеджерами компоновки и менеджерами геометрии) лишены недостатков абсолютного позиционирования. При изменении размеров окна производится автоматическое изменение характеристик всех компонентов, добавлен- ных в контейнер. Настройки шрифта при этом также учитываются, поэтому изменение раз- меров шрифта в два раза приведет только к увеличению компонентов и окон.
Для автоматического выравнивания компонентов используются два класса:
QHBoxLayout
— выстраивает все добавляемые компоненты по горизонтали (по умолча- нию — слева направо). Конструктор класса имеет следующий формат:
<Объект> = QHBoxLayout([<Родитель>])
QVBoxLayout
— выстраивает все добавляемые компоненты по вертикали (по умолча- нию — сверху вниз). Формат конструктора класса:
<Объект> = QVBoxLayout([<Родитель>])
Иерархия наследования для этих классов выглядит так:
(QObject, QLayoutItem) — QLayout — QBoxLayout — QHBoxLayout
(QObject, QLayoutItem) — QLayout — QBoxLayout — QVBoxLayout
Обратите внимание, что указанные классы не являются наследниками класса
QWidget
, а сле- довательно, не обладают собственным окном и не могут использоваться отдельно. Поэтому контейнеры обязательно должны быть привязаны к родительскому компоненту. Передать ссылку на родительский компонент можно в конструкторе классов
QHBoxLayout и
QVBoxLayout
. Кроме того, можно передать ссылку на контейнер в метод setLayout()
роди-
436
Часть II. Библиотека PyQt 5 тельского компонента. После этого все компоненты, добавленные в контейнер, автоматиче- ски привязываются к родительскому компоненту.
Типичный пример использования класса
QHBoxLayout показан в листинге 20.2, а увидеть результат выполнения этого кода можно на рис. 20.1.
Листинг 20.2. Использование контейнера QHBoxLayout
# -*- coding: utf-8 -*- from PyQt5 import QtWidgets import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() # Родительский компонент — окно window.setWindowTitle("QHBoxLayout") window.resize(300, 60) button1 = QtWidgets.QPushButton("1") button2 = QtWidgets.QPushButton("2") hbox = QtWidgets.QHBoxLayout() # Создаем контейнер hbox.addWidget(button1) # Добавляем компоненты hbox.addWidget(button2) window.setLayout(hbox) # Передаем ссылку родителю window.show() sys.exit(app.exec_())
Рис. 20.1. Контейнер
QHBoxLayout с двумя кнопками
Добавить компоненты в контейнер, удалить их и заменить другими позволяют следующие методы:
addWidget()
— добавляет компонент в конец контейнера. Формат метода: addWidget(<Компонент>[, stretch=0][, alignment=0])
В первом параметре указывается ссылка на компонент. Необязательный параметр stretch задает фактор растяжения для ячейки, а параметр alignment
— выравнивание компонента внутри ячейки. Два последних параметра можно задавать в порядке следо- вания или по именам в произвольном порядке: hbox.addWidget(button1, 10, QtCore.Qt.AlignRight) hbox.addWidget(button2, stretch=10) hbox.addWidget(button3, alignment=QtCore.Qt.AlignRight)
insertWidget()
— добавляет компонент в указанную позицию контейнера. Формат ме- тода: insertWidget(<Индекс>, <Компонент>[, stretch=0][, alignment=0])
Если в первом параметре указано значение
0
, компонент будет добавлен в начало кон- тейнера, а если — отрицательное значение, компонент добавляется в конец контейнера.
Глава 20. Размещение компонентов в окнах
437
Иное значение указывает определенную позицию. Остальные параметры аналогичны параметрам метода addWidget()
: hbox.addWidget(button1) hbox.insertWidget(-1, button2) # Добавление в конец hbox.insertWidget(0, button3) # Добавление в начало
removeWidget(<Компонент>)
— удаляет указанный компонент из контейнера;
replaceWidget()
— заменяет присутствующий в контейнере компонент другим. Формат метода: replaceWidget(<Заменяемый компонент>, <Заменяющий компонент>
[, options= FindChildrenRecursively])
В необязательном параметре options можно задать режим поиска заменяемого компо- нента с помощью одного из атрибутов класса
QtCore.Qt
:
FindDirectChildrenOnly
(
0
, ис- кать только среди содержимого текущего контейнера) и
FindChildrenRecursively
(
1
, ис- кать среди содержимого текущего и всех вложенных в него контейнеров — поведение по умолчанию);
addLayout()
— добавляет другой контейнер в конец текущего контейнера. С помощью этого метода можно вкладывать один контейнер в другой, создавая таким образом структуру любой сложности. Формат метода: addLayout(<Контейнер>[, stretch=0])
insertLayout()
— добавляет другой контейнер в указанную позицию текущего контей- нера. Если в первом параметре задано отрицательное значение, контейнер добавляется в конец. Формат метода: insertLayout(<Индекс>, <Контейнер>[, stretch=0])
addSpacing(<Размер>)
— добавляет пустое пространство указанного размера в конец контейнера. Размер пустого пространства задается в пикселах: hbox.addSpacing(100)
insertSpacing(<Индекс>, <Размер>)
— добавляет пустое пространство указанного раз- мера в определенную позицию. Размер пустого пространства задается в пикселах. Если первым параметром передается отрицательное значение, то пространство добавляется в конец;
addStretch([stretch=0])
— добавляет пустое растягиваемое пространство с нулевым минимальным размером и фактором растяжения stretch в конец контейнера. Это про- странство можно сравнить с пружиной, вставленной между компонентами, а параметр stretch
— с жесткостью пружины;
insertStretch(<Индекс>[, stretch=0])
— метод аналогичен методу addStretch()
, но добавляет растягиваемое пространство в указанную позицию. Если в первом параметре задано отрицательное значение, пространство добавляется в конец контейнера.
Параметр alignment в методах addWidget()
и insertWidget()
задает выравнивание компо- нента внутри ячейки. В этом параметре можно указать следующие атрибуты класса
QtCore.Qt
:
AlignLeft
—
1
— горизонтальное выравнивание по левому краю;
AlignRight
—
2
— горизонтальное выравнивание по правому краю;
AlignHCenter
—
4
— горизонтальное выравнивание по центру;
438
Часть II. Библиотека PyQt 5
AlignJustify
—
8
— заполнение всего пространства;
AlignTop
—
32
— вертикальное выравнивание по верхнему краю;
AlignBottom
—
64
— вертикальное выравнивание по нижнему краю;
AlignVCenter
—
128
— вертикальное выравнивание по центру;
AlignBaseline
—
256
— вертикальное выравнивание по базовой линии;
AlignCenter
—
AlignVCenter | AlignHCenter
— горизонтальное и вертикальное вырав- нивание по центру;
AlignAbsolute
—
16
— если в методе setLayoutDirection()
из класса
QWidget указан атрибут
QtCore.Qt.RightToLeft
, атрибут
AlignLeft задает выравнивание по правому краю, а атрибут
AlignRight
— по левому краю. Чтобы атрибут
AlignLeft всегда соответ- ствовал именно левому краю, необходимо указать комбинацию
AlignAbsolute |
AlignLeft
. Аналогично следует поступить с атрибутом
AlignRight
Можно задавать и комбинации атрибутов. В них может присутствовать только один атри- бут горизонтального выравнивания и только один атрибут вертикального выравнивания.
Например, комбинация
AlignLeft | AlignTop задает выравнивание по левому и верхнему краям. Противоречивые значения приводят к непредсказуемым результатам.
Помимо рассмотренных, контейнеры поддерживают также следующие методы (здесь при- ведены только основные — полный их список ищите в документации):
setDirection(<Направление>)
— задает направление вывода компонентов. В параметре можно указать следующие атрибуты из класса
QBoxLayout
:
•
LeftToRight
—
0
— слева направо (значение по умолчанию для горизонтального кон- тейнера);
•
RightToLeft
—
1
— справа налево;
•
TopToBottom
—
2
— сверху вниз (значение по умолчанию для вертикального контей- нера);
•
BottomToTop
—
3
— снизу вверх;
setContentsMargins()
— задает величины отступов от границ контейнера до компонен- тов. Форматы метода: setContentsMargins(<Слева>, <Сверху>, <Справа>, <Снизу>) setContentsMargins(
Примеры: hbox.setContentsMargins(2, 4, 2, 4) m = QtCore.QMargins(4, 2, 4, 2) hbox.setContentsMargins(m)
setSpacing(<Расстояние>)
— задает расстояние между компонентами.
20.3. Выравнивание по сетке
Помимо выравнивания компонентов по горизонтали и вертикали, существует возможность размещения компонентов внутри ячеек сетки. Для этого предназначен класс
QGridLayout
Иерархия его наследования:
(QObject, QLayoutItem) — QLayout — QGridLayout
Глава 20. Размещение компонентов в окнах
439
Создать экземпляр класса
QGridLayout можно следующим образом:
<Объект> = QGridLayout([<Родитель>])
В необязательном параметре можно указать ссылку на родительский компонент. Если тако- вой не указан, следует передать ссылку на сетку в метод setLayout()
родительского компо- нента. Код, иллюстрирующий типичный пример использования класса
QGridLayout
, пред- ставлен в листинге 20.3, а результат его выполнения — на рис. 20.2.
Листинг 20.3. Использование контейнера QGridLayout
# -*- coding: utf-8 -*- from PyQt5 import QtWidgets import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() # Родительский компонент — окно window.setWindowTitle("QGridLayout") window.resize(150, 100) button1 = QtWidgets.QPushButton("1") button2 = QtWidgets.QPushButton("2") button3 = QtWidgets.QPushButton("3") button4 = QtWidgets.QPushButton("4") grid = QtWidgets.QGridLayout() # Создаем сетку grid.addWidget(button1, 0, 0) # Добавляем компоненты grid.addWidget(button2, 0, 1) grid.addWidget(button3, 1, 0) grid.addWidget(button4, 1, 1) window.setLayout(grid) # Передаем ссылку родителю window.show() sys.exit(app.exec_())
Рис. 20.2. Компонент
QGridLayout с четырьмя кнопками
Добавить компоненты позволяют следующие методы:
addWidget()
— добавляет компонент в указанную ячейку сетки. Метод имеет следую- щие форматы: addWidget(<Компонент>, <Строка>, <Столбец>[, alignment=0]) addWidget(<Компонент>, <Строка>, <Столбец>, <Количество строк>,
<Количество столбцов>[, alignment=0])
В первом параметре указывается ссылка на компонент, во втором параметре — индекс строки, а в третьем — индекс столбца. Нумерация строк и столбцов начинается с нуля.
Параметр
<Количество строк>
задает количество занимаемых компонентом ячеек по
440
Часть II. Библиотека PyQt 5 вертикали, а параметр
<Количество столбцов>
— по горизонтали. Параметр alignment задает выравнивание компонента внутри ячейки. Значения, которые можно указать в этом параметре, мы рассматривали в предыдущем разделе.
Пример: grid = QtGui.QGridLayout() grid.addWidget(button1, 0, 0, alignment=QtCore.Qt.AlignLeft) grid.addWidget(button2, 0, 1, QtCore.Qt.AlignRight) grid.addWidget(button3, 1, 0, 1, 2)
addLayout()
— добавляет контейнер в указанную ячейку сетки. Метод имеет следующие форматы: addLayout(<Контейнер>, <Строка>, <Столбец>[, alignment=0]) addLayout(<Контейнер>, <Строка>, <Столбец>, <Количество строк>,
<Количество столбцов>[, alignment=0])
В первом параметре указывается ссылка на контейнер. Остальные параметры аналогич- ны параметрам метода addWidget()
Для удаления и замены компонентов следует пользоваться методами removeWidget()
и replaceWidget()
, описанными в разд. 20.2.
Класс
QGridLayout поддерживает следующие методы (здесь приведены только основные методы — полный их список смотрите на странице https://doc.qt.io/qt-5/qgridlayout.html):
setRowMinimumHeight(<Индекс>, <Высота>)
— задает минимальную высоту строки с ин- дексом
<Индекс>
;
setColumnMinimumWidth(<Индекс>, <Ширина>)
— задает минимальную ширину столбца с индексом
<Индекс>
;
setRowStretch(<Индекс>, <Фактор растяжения>)
— задает фактор растяжения по верти- кали для строки с индексом
<Индекс>
;
setColumnStretch(<Индекс>, <Фактор растяжения>)
— задает фактор растяжения по го- ризонтали для столбца с индексом
<Индекс>
;
setContentsMargins()
— задает величины отступов от границ сетки до компонентов.
Форматы метода: setContentsMargins(<Слева>, <Сверху>, <Справа>, <Снизу>) setContentsMargins(
setSpacing(<Значение>)
— задает расстояние между компонентами по горизонтали и вертикали;
setHorizontalSpacing(<Значение>)
— задает расстояние между компонентами по гори- зонтали;
setVerticalSpacing(<Значение>)
— задает расстояние между компонентами по вертикали;
rowCount()
— возвращает количество строк сетки;
columnCount()
— возвращает количество столбцов сетки;
cellRect(<Индекс строки>, <Индекс колонки>)
— возвращает экземпляр класса
QRect
, который хранит координаты и размеры ячейки, расположенной на пересечении строки и колонки с указанными индексами.
Глава 20. Размещение компонентов в окнах
441 20.4. Выравнивание компонентов формы
Класс
QFormLayout позволяет выравнивать компоненты формы. Контейнер по умолчанию состоит из двух столбцов: первый предназначен для вывода надписи, а второй — для выво- да самого компонента. При этом надпись связывается с компонентом, что позволяет назна- чать клавиши быстрого доступа, указав символ
&
перед буквой внутри текста надписи. По нажатию комбинации клавиш быстрого доступа (комбинация
(QObject, QLayoutItem) — QLayout — QFormLayout
Создать экземпляр класса
QFormLayout можно следующим образом:
<Объект> = QFormLayout([<Родитель>])
В необязательном параметре можно указать ссылку на родительский компонент. Если тако- вой не указан, необходимо передать ссылку на контейнер в метод setLayout()
родительско- го компонента.
В листинге 20.4 показан код, создающий форму с контейнером
QFormLayout
. Результат выполнения этого кода можно увидеть на рис. 20.3.
Рис. 20.3. Пример использования контейнера
QFormLayout
Листинг 20.4. Использование контейнера QFormLayout
# -*- coding: utf-8 -*- from PyQt5 import QtWidgets import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() window.setWindowTitle("QFormLayout") window.resize(300, 150) lineEdit = QtWidgets.QLineEdit() textEdit = QtWidgets.QTextEdit() button1 = QtWidgets.QPushButton("О&тправить") button2 = QtWidgets.QPushButton("О&чистить") hbox = QtWidgets.QHBoxLayout() hbox.addWidget(button1) hbox.addWidget(button2) form = QtWidgets.QFormLayout() form.addRow("&Название:", lineEdit)