PySide6
132 строки · 9.2 Кб
1"""
2Пример создания пользовательского виджета.
36-ой шаг - отрисовка непосредственно делений шкалы
4"""
5import sys
6
7from PySide6.QtWidgets import QApplication, QVBoxLayout, QDial, QWidget, QSizePolicy
8from PySide6.QtGui import QPaintEvent, QPainter, QBrush, QColor
9from PySide6.QtCore import Qt, QRect, QSize
10
11"""
12Модуль sys нужен для доступа к аргументам командной строки. Если использование аргументов
13командной строки не предполагается, то импорт можно не выполнять. При этом, при создании
14приложения в класс QApplication([]) в качестве аргумента передается пустой список.
15Импорт из модуля PySide6.QtWidgets класса для управления приложением QApplication и класса слоев
16для виджетов с вертикальной организацией QVBoxLayout, класса виджета вращающегося регулятора QDial,
17класса базового виджета QWidget, класса политики изменения размера QSizePolicy.
18Импорт из модуля PySide6.QtCore класса Qt,содержащего различные идентификаторы, используемые
19в библиотеке Qt, класса примитива прямоугольника QRect.
20Импорт из модуля PySide6.QtGui класса обработчика событий рисования QPaintEvent, класса виджета
21для рисования QPainter, класса кисти QBrush, класса объекта цветов QColor, класса размеров QSize.
22Другие виджеты можно найти по ссылке https://doc.qt.io/qt-5/widget-classes.html#basic-widget-classes
23"""
24
25
26class _Bar(QWidget):
27"""
28Подкласс силовой шкалы от супер-класса базового виджета
29"""
30
31def __init__(self):
32"""
33Конструктор шкалы измерителя
34"""
35QWidget.__init__(self) # Явный вызов конструктора родительского класса
36self.setSizePolicy(QSizePolicy.MinimumExpanding,
37QSizePolicy.MinimumExpanding
38)
39
40def sizeHint(self) -> QSize:
41"""
42Метод, возвращающий минимальные размеры виджета
43:return: QSize - минимальный размер виджетов
44"""
45return QSize(40, 120)
46
47def paintEvent(self, e: QPaintEvent) -> None:
48"""
49Метод пользовательский обработчик события рисования
50:param e: QPaintEvent - событие базового обработчика рисования
51:return: None
52"""
53painter = QPainter(self) # создание экземпляра класса рисовальщика
54brush = QBrush() # создание экземпляра класса кисти
55brush.setColor(QColor('black')) # установка цвета кисти
56brush.setStyle(Qt.SolidPattern) # установка стиля заполнения сплошное
57rect = QRect(0, 0, painter.device().width(), painter.device().height())
58# Рисование прямоугольника. Использование метода .device() позволяют рисовать
59# прямоугольник согласно размеру окна виджета. Методы .width() и height() извлекают
60# размеры окна рисовальщика
61painter.fillRect(rect, brush) # заливка прямоугольника цветом кисти
62
63# Отображение текущего состояния
64dial = self.parent()._dial # передача ссылки на регулятор в переменную через специальный
65# метод родительского класса
66vmin, vmax = dial.minimum(), dial.maximum() # установка минимального и максимального значения регулятора
67value = dial.value() # извлечение текущего значения регулятора
68
69pc = (value - vmin) / (vmax - vmin) # вычисление доли шкалы, соответствующей значению регулятора
70n_steps_to_draw = int(pc * 5) # вычисление количества сегментов, которые должны быть
71# отрисованы (всего 5 сегментов для значений от 0 (ничего) до 5)
72
73padding = 5 # установка величины отступов
74d_height = painter.device().height() - (padding * 2) # вычисление высоты области рисования делений
75# шкалы с учетом отступов
76d_width = painter.device().width() - (padding * 2) # вычисление ширины области рисования делений
77# шкалы с учетом отступов
78step_size = d_height / 5 # вычисление доли высоты на одно деление
79bar_height = step_size * 0.6 # вычисление высоты прямоугольника деления
80brush.setColor('red') # установка цвета кисти для заливки
81for n in range(n_steps_to_draw): # цикл отрисовки делений шаклы
82ypos = (1 + n) * step_size # вычисление положения ЛВУ прямоугольника деления относительно самого деления
83rect = QRect(padding, # отрисовка прямоугольника с вычисленными параметрами
84padding + d_height - int(ypos), # вычисление высоты ЛВУ прямоугольника деления на шкале
85d_width,
86int(bar_height)
87)
88painter.fillRect(rect, brush) # заливка прямоугольника деления шкалы цветом
89painter.end() # метод завершения работы рисовальщика
90
91def _trigger_refresh(self):
92"""
93Метод ресивер (слот) сигнала обновления виджета
94:return:
95"""
96self.update() # вызов метода обновления виджета родительского класса QWidget
97
98
99class PowerBar(QWidget):
100"""
101Подкласс пользовательского виджета от супер-класса базового виджета
102"""
103
104def __init__(self, parent=None, steps: int = 5) -> None:
105"""
106Конструктор пользовательского виджета
107"""
108QWidget.__init__(self, parent) # явный вызов конструктора родительского класса
109layout = QVBoxLayout() # создание экземпляра класса слоев для виджетов
110self._bar = _Bar() # создание экземпляра класса силовой шкалы
111layout.addWidget(self._bar) # размещение силовой объекта силовой шкалы в слое
112self._dial = QDial() # создание экземпляра класса виджета вращающегося регулятора
113self._dial.valueChanged.connect(self._bar._trigger_refresh) # создание сигнала на изменение
114# положения регулятора
115layout.addWidget(self._dial) # размещение виджета регулятора на слое
116self.setLayout(layout) # размещение слоя с виджетами в окне пользовательского виджета
117
118
119def main() -> None:
120"""
121Функция запуска кода верхнего уроня
122:return: None
123"""
124app = QApplication(sys.argv) # создание экземпляра основного цикла главного окна приложения
125volume = PowerBar() # создание экземпляра пользовательского виджета
126volume.show() # вызов метода вывода виджета (по умолчанию виджет спрятан)
127app.exec() # запуска основного цикла пользовательского виджета
128
129
130if __name__ == '__main__': # данное условие нужно для предотвращения запуска кода верхнего уровня при
131# импортировании данного файла как модуля
132main() # вызов функции запуска кода верхнего
133