|
|
@@ -0,0 +1,150 @@
|
|
|
+from PyQt5 import QtWidgets, QtGui, QtCore
|
|
|
+from PyQt5.QtCore import Qt
|
|
|
+
|
|
|
+
|
|
|
+class _Bar(QtWidgets.QWidget):
|
|
|
+ clickedValue = QtCore.pyqtSignal(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 colors
|
|
|
+ self.n_steps = len(steps)
|
|
|
+ self.steps = steps
|
|
|
+ elif isinstance(steps, int):
|
|
|
+ self.n_steps = steps
|
|
|
+ self.steps = ['red'] * steps
|
|
|
+ else:
|
|
|
+ raise TypeError('step must be a list or int')
|
|
|
+
|
|
|
+ self._bar_solid_parent = 0.8
|
|
|
+ self._background_color = QtGui.QColor('black')
|
|
|
+ self._padding = 4.0
|
|
|
+
|
|
|
+ def sizeHint(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()
|
|
|
+
|
|
|
+ pc = (value - vmin) / (vmax - vmin)
|
|
|
+ n_steps_to_draw = int(pc * self.n_steps)
|
|
|
+
|
|
|
+ # Define our canvas
|
|
|
+ padding = 5
|
|
|
+ d_height = painter.device().height() - (padding * 2)
|
|
|
+ d_width = painter.device().width() - (padding * 2)
|
|
|
+
|
|
|
+ # Draw the bars
|
|
|
+ step_size = d_height / self.n_steps
|
|
|
+ bar_height = int(step_size * self._bar_solid_parent)
|
|
|
+ bar_spacer = int(step_size * self._bar_solid_parent / 2)
|
|
|
+
|
|
|
+ for n in range(n_steps_to_draw):
|
|
|
+ brush.setColor(QtGui.QColor(self.steps[n]))
|
|
|
+ rect = QtCore.QRect(
|
|
|
+ padding,
|
|
|
+ int(padding + d_height - ((n + 1) * step_size) + bar_spacer),
|
|
|
+ d_width,
|
|
|
+ bar_height
|
|
|
+ )
|
|
|
+ painter.fillRect(rect, brush)
|
|
|
+
|
|
|
+ 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: QtGui.QMouseEvent):
|
|
|
+ self._calculate_clicked_value(e)
|
|
|
+
|
|
|
+ def mouseReleaseEvent(self, e: QtGui.QMouseEvent):
|
|
|
+ self._calculate_clicked_value(e)
|
|
|
+
|
|
|
+
|
|
|
+class PowerBar(QtWidgets.QWidget):
|
|
|
+ """
|
|
|
+ Custom Qt Widget to show a power bar and dial.
|
|
|
+ Demonstrating compound and custom-drawn widget.
|
|
|
+
|
|
|
+ Left-clicking the button shows the color-chooser, while
|
|
|
+ right-clicking resets the color tho None (no color).
|
|
|
+ """
|
|
|
+
|
|
|
+ colorChanged = QtCore.pyqtSignal()
|
|
|
+
|
|
|
+ def __init__(self, steps=5, *args, **kwargs):
|
|
|
+ super(PowerBar, self).__init__(*args, **kwargs)
|
|
|
+
|
|
|
+ layout = QtWidgets.QVBoxLayout()
|
|
|
+ self._bar = _Bar(steps)
|
|
|
+ layout.addWidget(self._bar)
|
|
|
+
|
|
|
+ # Create the QDial widget and set up defaults.
|
|
|
+ self._dial = QtWidgets.QDial()
|
|
|
+ self._dial.setNotchesVisible(True)
|
|
|
+ self._dial.setWrapping(False)
|
|
|
+ self._dial.valueChanged.connect(self._bar._trigger_refresh)
|
|
|
+
|
|
|
+ self._bar.clickedValue.connect(self._dial.setValue)
|
|
|
+
|
|
|
+ layout.addWidget(self._dial)
|
|
|
+ self.setLayout(layout)
|
|
|
+
|
|
|
+ def __getattr__(self, name):
|
|
|
+ if name in self.__dict__:
|
|
|
+ return self[name]
|
|
|
+ return getattr(self._dial, name)
|
|
|
+
|
|
|
+ def setColor(self, color):
|
|
|
+ self._bar.steps = [color] * self._bar.n_steps
|
|
|
+ self._bar.update()
|
|
|
+
|
|
|
+ def setColors(self, colors):
|
|
|
+ self._bar.n_steps = len(colors)
|
|
|
+ self._bar.steps = colors
|
|
|
+ self._bar.update()
|
|
|
+
|
|
|
+ def setBarPadding(self, i):
|
|
|
+ self._bar._padding = int(i)
|
|
|
+ self._bar.update()
|
|
|
+
|
|
|
+ def setBarSolidPercent(self, f):
|
|
|
+ self._bar._bar_solid_percent = float(f)
|
|
|
+ self._bar.update()
|
|
|
+
|
|
|
+ def setBackgroundColor(self, color):
|
|
|
+ self._bar._background_color = QtGui.QColor(color)
|
|
|
+ self._bar.update()
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ app = QtWidgets.QApplication([])
|
|
|
+ volume = PowerBar()
|
|
|
+ volume.show()
|
|
|
+ app.exec_()
|