power_bar_better.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. from PyQt5 import QtWidgets, QtGui, QtCore
  2. from PyQt5.QtCore import Qt
  3. class _Bar(QtWidgets.QWidget):
  4. clickedValue = QtCore.pyqtSignal(int)
  5. def __init__(self, steps, *args, **kwargs):
  6. super().__init__(*args, **kwargs)
  7. self.setSizePolicy(
  8. QtWidgets.QSizePolicy.MinimumExpanding,
  9. QtWidgets.QSizePolicy.MinimumExpanding
  10. )
  11. if isinstance(steps, list):
  12. # list of colors
  13. self.n_steps = len(steps)
  14. self.steps = steps
  15. elif isinstance(steps, int):
  16. self.n_steps = steps
  17. self.steps = ['red'] * steps
  18. else:
  19. raise TypeError('step must be a list or int')
  20. self._bar_solid_parent = 0.8
  21. self._background_color = QtGui.QColor('black')
  22. self._padding = 4.0
  23. def sizeHint(self):
  24. return QtCore.QSize(40, 120)
  25. def paintEvent(self, e):
  26. painter = QtGui.QPainter(self)
  27. brush = QtGui.QBrush()
  28. brush.setColor(self._background_color)
  29. brush.setStyle(Qt.SolidPattern)
  30. rect = QtCore.QRect(0, 0, painter.device().width(), painter.device().height())
  31. painter.fillRect(rect, brush)
  32. # Get current state.
  33. dial = self.parent()._dial
  34. vmin, vmax = dial.minimum(), dial.maximum()
  35. value = dial.value()
  36. pc = (value - vmin) / (vmax - vmin)
  37. n_steps_to_draw = int(pc * self.n_steps)
  38. # Define our canvas
  39. padding = 5
  40. d_height = painter.device().height() - (padding * 2)
  41. d_width = painter.device().width() - (padding * 2)
  42. # Draw the bars
  43. step_size = d_height / self.n_steps
  44. bar_height = int(step_size * self._bar_solid_parent)
  45. bar_spacer = int(step_size * self._bar_solid_parent / 2)
  46. for n in range(n_steps_to_draw):
  47. brush.setColor(QtGui.QColor(self.steps[n]))
  48. rect = QtCore.QRect(
  49. padding,
  50. int(padding + d_height - ((n + 1) * step_size) + bar_spacer),
  51. d_width,
  52. bar_height
  53. )
  54. painter.fillRect(rect, brush)
  55. def _trigger_refresh(self):
  56. self.update()
  57. def _calculate_clicked_value(self, e):
  58. parent = self.parent()
  59. vmin, vmax = parent.minimum(), parent.maximum()
  60. d_height = self.size().height() - (self._padding * 2)
  61. step_size = d_height / self.n_steps
  62. click_y = e.y() - self._padding - step_size / 2
  63. pc = (d_height - click_y) / d_height
  64. value = vmin + pc * (vmax - vmin)
  65. self.clickedValue.emit(value)
  66. def mouseMoveEvent(self, e: QtGui.QMouseEvent):
  67. self._calculate_clicked_value(e)
  68. def mouseReleaseEvent(self, e: QtGui.QMouseEvent):
  69. self._calculate_clicked_value(e)
  70. class PowerBar(QtWidgets.QWidget):
  71. """
  72. Custom Qt Widget to show a power bar and dial.
  73. Demonstrating compound and custom-drawn widget.
  74. Left-clicking the button shows the color-chooser, while
  75. right-clicking resets the color tho None (no color).
  76. """
  77. colorChanged = QtCore.pyqtSignal()
  78. def __init__(self, steps=5, *args, **kwargs):
  79. super(PowerBar, self).__init__(*args, **kwargs)
  80. layout = QtWidgets.QVBoxLayout()
  81. self._bar = _Bar(steps)
  82. layout.addWidget(self._bar)
  83. # Create the QDial widget and set up defaults.
  84. self._dial = QtWidgets.QDial()
  85. self._dial.setNotchesVisible(True)
  86. self._dial.setWrapping(False)
  87. self._dial.valueChanged.connect(self._bar._trigger_refresh)
  88. self._bar.clickedValue.connect(self._dial.setValue)
  89. layout.addWidget(self._dial)
  90. self.setLayout(layout)
  91. def __getattr__(self, name):
  92. if name in self.__dict__:
  93. return self[name]
  94. return getattr(self._dial, name)
  95. def setColor(self, color):
  96. self._bar.steps = [color] * self._bar.n_steps
  97. self._bar.update()
  98. def setColors(self, colors):
  99. self._bar.n_steps = len(colors)
  100. self._bar.steps = colors
  101. self._bar.update()
  102. def setBarPadding(self, i):
  103. self._bar._padding = int(i)
  104. self._bar.update()
  105. def setBarSolidPercent(self, f):
  106. self._bar._bar_solid_percent = float(f)
  107. self._bar.update()
  108. def setBackgroundColor(self, color):
  109. self._bar._background_color = QtGui.QColor(color)
  110. self._bar.update()
  111. if __name__ == '__main__':
  112. app = QtWidgets.QApplication([])
  113. volume = PowerBar()
  114. volume.show()
  115. app.exec_()