Coverage for graphica/gui/widgets/slider_spin.py: 97.5%

38 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-12 16:38 +0000

1"""スライダー+今のスピンボックス。値の持ち主はスピンボックスのまま(バインディングはそちらを見る)。""" 

2from PySide6.QtCore import Qt 

3from PySide6.QtWidgets import QAbstractSpinBox, QHBoxLayout, QSlider, QWidget 

4 

5SPIN_WIDTH = 56 

6 

7 

8class SliderSpin(QWidget): 

9 """spinbox を中に取り込み、左にスライダーを付ける。 

10 

11 スライダーの範囲(slider_min〜slider_max)はよく使う範囲で、スピンボックスはそれより外の値も受け付ける 

12 (そのときスライダーは端に止まる)。スピンボックスがシグナルを止めて書き換えられた(バインディングの 

13 「戻す」)後は、refresh() でスライダーを合わせる。 

14 """ 

15 

16 def __init__(self, spinbox, slider_min, slider_max, step=None, parent=None): 

17 super().__init__(parent) 

18 self.spinbox = spinbox 

19 self._scale = 10 ** spinbox.decimals() 

20 self.slider = QSlider(Qt.Orientation.Horizontal, self) 

21 self.slider.setObjectName("slider_spin_slider") 

22 self.slider.setRange(round(slider_min * self._scale), round(slider_max * self._scale)) 

23 self.slider.setSingleStep(max(1, round((step or spinbox.singleStep()) * self._scale))) 

24 self.slider.setCursor(Qt.CursorShape.PointingHandCursor) 

25 layout = QHBoxLayout(self) 

26 layout.setContentsMargins(0, 0, 0, 0) 

27 layout.setSpacing(10) 

28 layout.addWidget(self.slider, 1) 

29 layout.addWidget(spinbox) 

30 # 見本どおり、上下の矢印を消した数値だけの小さな欄にする(矢印の分の余白は QSS の sliderValue で外す) 

31 spinbox.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons) 

32 spinbox.setAlignment(Qt.AlignmentFlag.AlignCenter) 

33 spinbox.setProperty("sliderValue", True) 

34 # 既に表示に使われた部品は、プロパティを変えても QSS を当て直さないと見た目が変わらない 

35 spinbox.style().unpolish(spinbox) 

36 spinbox.style().polish(spinbox) 

37 spinbox.setFixedWidth(SPIN_WIDTH) 

38 self.slider.valueChanged.connect(self._on_slider_moved) 

39 spinbox.valueChanged.connect(lambda _value: self.refresh()) 

40 self.refresh() 

41 

42 def refresh(self): 

43 blocked = self.slider.blockSignals(True) 

44 self.slider.setValue(round(self.spinbox.value() * self._scale)) 

45 self.slider.blockSignals(blocked) 

46 

47 def _on_slider_moved(self, position): 

48 value = position / self._scale 

49 if abs(value - self.spinbox.value()) >= 0.5 / self._scale: 49 ↛ exitline 49 didn't return from function '_on_slider_moved' because the condition on line 49 was always true

50 self.spinbox.setValue(value) 

51 

52 def setEnabled(self, enabled): 

53 super().setEnabled(enabled) 

54 self.spinbox.setEnabled(enabled)