Files
Martin Fitzpatrick b74592ea41 Add versions for PySide6, PyQt6 & PySide2.
Break down examples into module files to make easier to read. Use
full-definitions on Enums (PyQt6 compatible, better documenting).
Add fixes for Qt6 versions & some general bugfixes.
2024-02-19 13:36:32 +01:00

141 lines
4.1 KiB
Python

from PySide6.QtCore import QRect, QRectF, QSize, Qt, QTimer
from PySide6.QtGui import QBrush, QColor, QPainter
from PySide6.QtWidgets import QSizePolicy, QWidget
class EqualizerBar(QWidget):
def __init__(self, bars, steps):
super().__init__()
self.setSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.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")
# Bar appearance.
self.n_bars = bars
self._x_solid_percent = 0.8
self._y_solid_percent = 0.8
self._background_color = QColor("black")
self._padding = 25 # n-pixel gap around edge.
# Bar behaviour
self._timer = None
self.setDecayFrequencyMs(100)
self._decay = 10
# Ranges
self._vmin = 0
self._vmax = 100
# Current values are stored in a list.
self._values = [0.0] * bars
def paintEvent(self, e):
painter = QPainter(self)
brush = QBrush()
brush.setColor(self._background_color)
brush.setStyle(Qt.BrushStyle.SolidPattern)
rect = QRect(0, 0, painter.device().width(), painter.device().height())
painter.fillRect(rect, brush)
# Define our canvas.
d_height = painter.device().height() - (self._padding * 2)
d_width = painter.device().width() - (self._padding * 2)
# Draw the bars.
step_y = d_height / self.n_steps
bar_height = step_y * self._y_solid_percent
bar_height_space = step_y * (1 - self._x_solid_percent) / 2
step_x = d_width / self.n_bars
bar_width = step_x * self._x_solid_percent
bar_width_space = step_x * (1 - self._y_solid_percent) / 2
for b in range(self.n_bars):
# Calculate the y-stop position for this bar, from the value in range.
pc = (self._values[b] - self._vmin) / (self._vmax - self._vmin)
n_steps_to_draw = int(pc * self.n_steps)
for n in range(n_steps_to_draw):
brush.setColor(QColor(self.steps[n]))
rect = QRectF(
self._padding + (step_x * b) + bar_width_space,
self._padding + d_height - ((1 + n) * step_y) + bar_height_space,
bar_width,
bar_height,
)
painter.fillRect(rect, brush)
painter.end()
def sizeHint(self):
return QSize(20, 120)
def _trigger_refresh(self):
self.update()
def setDecay(self, f):
self._decay = float(f)
def setDecayFrequencyMs(self, ms):
if self._timer:
self._timer.stop()
if ms:
self._timer = QTimer()
self._timer.setInterval(ms)
self._timer.timeout.connect(self._decay_beat)
self._timer.start()
def _decay_beat(self):
self._values = [max(0, v - self._decay) for v in self._values]
self.update() # Redraw new position.
def setValues(self, v):
self._values = v
self.update()
def values(self):
return self._values
def setRange(self, vmin, vmax):
assert float(vmin) < float(vmax)
self._vmin, self._vmax = float(vmin), float(vmax)
def setColor(self, color):
self.steps = [color] * self._bar.n_steps
self.update()
def setColors(self, colors):
self.n_steps = len(colors)
self.steps = colors
self.update()
def setBarPadding(self, i):
self._padding = int(i)
self.update()
def setBarSolidXPercent(self, f):
self._x_solid_percent = float(f)
self.update()
def setBarSolidYPercent(self, f):
self._y_solid_percent = float(f)
self.update()
def setBackgroundColor(self, color):
self._background_color = QColor(color)
self.update()