| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- 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_()
|