-
Notifications
You must be signed in to change notification settings - Fork 0
/
barwidget.py
128 lines (94 loc) · 3.76 KB
/
barwidget.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import Qt
class _Bar(QtWidgets.QWidget):
clickedValue = QtCore.Signal(int)
def __init__(self, steps, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setSizePolicy(
QtWidgets.QSizePolicy.MinimumExpanding,
QtWidgets.QSizePolicy.MinimumExpanding
)
if isinstance(steps, list):
# list of colours
self.n_steps = len(steps)
self.steps = steps
elif isinstance(steps, int):
# int number of bars, defaults to red
self.n_steps = steps
self.steps = ['red'] * steps
else:
raise TypeError('steps must be a list or int')
self._bar_solid_percent = 0.8
self._background_color = QtGui.QColor('black')
self._padding = 4.0
def siezeHint(self):
return QtCore.QSize(40,120)
def paintEvent(self, e):
painter = QtGui.QPainter(self)
brush = QtGui.QBrush()
brush.setColor(self._background_color)
brush.setStyle(Qt.SolidPattern)
rect = QtCore.QRect(0, 0, painter.device().width(), painter.device().height())
painter.fillRect(rect, brush)
# Get current state
dial = self.parent()._dial
vmin, vmax = dial.minimum(), dial.maximum()
value = dial.value()
# Define our canvas
# padding = 5
d_height = painter.device().height() - (self._padding * 2)
d_width = painter.device().width() - (self._padding * 2)
# Draw the bars
step_size = d_height / self.n_steps
bar_height = step_size * self._bar_solid_percent
bar_spacer = step_size * (1 - self._bar_solid_percent) / 2
pc = (value - vmin) / (vmax - vmin)
n_step_to_draw = int(pc * self.n_steps)
for n in range(n_step_to_draw):
brush.setColor(QtGui.QColor(self.steps[n]))
rect = QtCore.QRect(
self._padding,
self._padding + d_height - ((1 + n) * step_size) + bar_spacer,
d_width,
bar_height
)
painter.fillRect(rect, brush)
painter.end()
def _trigger_refresh(self):
self.update()
def _calculate_clicked_value(self, e):
parent = self.parent()
vmin, vmax = parent.minimum(), parent.maximum()
d_height = self.size().height() + (self._padding * 2)
step_size = d_height / self.n_steps
click_y = e.y() - self._padding - step_size / 2
pc = (d_height - click_y) / d_height
value = vmin + pc *(vmax - vmin)
self.clickedValue.emit(value)
def mouseMoveEvent(self, e):
self._calculate_clicked_value(e)
def mousePressEvent(self, e):
self._calculate_clicked_value(e)
class PowerBar(QtWidgets.QWidget):
"""Custom Qt widget to show a power bar and dial
Demostarating compound and custom-drawn wiget"""
def __init__(self, steps=5, *args, **kwargs):
super(PowerBar, self).__init__(*args, **kwargs)
layout = QtWidgets.QVBoxLayout()
self._bar = _Bar(steps)
layout.addWidget(self._bar)
self._dial = QtWidgets.QDial()
layout.addWidget(self._dial)
self.setLayout(layout)
self._dial.valueChanged.connect(self._bar._trigger_refresh)
self._bar.clickedValue.connect(self._dial.setValue)
def __getattr__(self, name):
"""Returns parameters for us in bar paretn"""
if name in self.__dict__:
return self[name]
try:
return getattr(self._dial, name)
except AttributeError:
raise AttributeError(
"'{}' object has no attribute '{}'".format(self.__class__.__name__, name)
)