QSlider с «произвольными» значениями (из списка / массива)? - PullRequest
1 голос
/ 10 октября 2019

В итоге у меня появился подкласс QSlider:

# via https://stackoverflow.com/a/49744383/6197439
class ListSlider(QSlider):
  def __init__(self, vallist, *args, **kwargs):
    QSlider.__init__(self, *args, **kwargs)
    self.valuelist = vallist
    self.listvalue = None # reserved for actual values of list (.value() will be index)
    self.setMaximum(len(self.valuelist)-1)
    self.valueChanged.connect(self.on_change_value)
    self.on_change_value(0)

  @pyqtSlot(int)
  def on_change_value(self, value):
    self.listvalue = self.valuelist[value]

... и затем что-то вроде:

self.my_list_slider = ListSlider([1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048], Qt.Horizontal)
...
self.my_list_slider.valueChanged.connect(self.self.my_list_slider_valuechange)

...

def my_list_slider_valuechange(self):
  curval = self.my_list_slider.value()
  print("my_list_slider {} {}".format(curval, self.my_list_slider.listvalue))

... и это работает, яугадайте - потому что когда я перетаскиваю ползунок, я получаю распечатку:

my_list_slider 0 1
my_list_slider 1 2
my_list_slider 2 4
my_list_slider 3 8
my_list_slider 4 16
my_list_slider 5 32
my_list_slider 6 64
my_list_slider 7 128
...

... за исключением того, что я немного нервничаю из-за необходимости управлять двумя переменными в ползунке - исходное значение теперь становитсяиндекс;и фактическое значение, которое мне нужно, теперь выводится из списка на основе индекса.

Итак, мне было интересно - способен ли QSlider обрабатывать списки (то есть мы скользим по значениям списка,не просто диапазон номеров) таким образом изначально? Или, если нет, есть ли более рекомендуемый / простой метод для обработки ползунка с произвольными значениями (то есть значениями, взятыми из списка)?

1 Ответ

1 голос
/ 10 октября 2019

Вы можете создать новый сигнал, который излучает информацию о выбранном индексе и соответствующее ему значение:

from PyQt5 import QtCore, QtGui, QtWidgets


class ListSlider(QtWidgets.QSlider):
    elementChanged = QtCore.pyqtSignal(int, int)

    def __init__(self, values=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setMinimum(0)
        self._values = []
        self.valueChanged.connect(self._on_value_changed)
        self.values = values or []

    @property
    def values(self):
        return self._values

    @values.setter
    def values(self, values):
        self._values = values
        maximum = max(0, len(self._values) - 1)
        self.setMaximum(maximum)
        self.setValue(0)

    @QtCore.pyqtSlot(int)
    def _on_value_changed(self, index):
        value = self.values[index]
        self.elementChanged.emit(index, value)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = ListSlider(orientation=QtCore.Qt.Horizontal)
    w.values = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]

    def my_list_slider_valuechange(index, value):
        print("my_list_slider {} {}".format(index, value))

    w.elementChanged.connect(my_list_slider_valuechange)

    w.show()
    sys.exit(app.exec_())
...