具有 "arbitrary" 值的 QSlider(来自 list/array)?

QSlider with "arbitrary" values (from list/array)?

我最终得到了这样的 QSlider 子类:

# via 
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 是否能够以这种方式原生地处理列表(也就是说,我们沿着列表的值滑动,而不仅仅是数字范围)?或者,如果没有,是否有更多 recommended/straightforward 方法来处理具有任意值(即从列表中获取的值)的滑块?

您可以创建一个新信号来发出所选索引及其对应值的信息:

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