Используйте float для QSlider

У меня есть QLineEdit и QSlider, в которых они взаимодействуют друг с другом.

Например. Если я установлю значение в QLineEdit, ползунок будет обновлен, или если я передвину ползунок, он обновит значение в QLineEdit.

# If user change value on the slider
self.timer_slider.valueChanged.connect(self.set_value)
# If user sets a value in the text box instead
self.timer_value.textChanged.connect(self.set_slider)

def set_slider(self, value):
    self.timer_slider.setValue(int(value))

def set_value(self, value):
    self.timer_value.setText(str(value))

Могу ли я в любом случае использовать значения float вместо значений int?


person dissidia    schedule 15.03.2017    source источник
comment
QDoubleSpinBox.   -  person ekhumoro    schedule 16.03.2017


Ответы (3)


Ответ @dissidia хорош. Но если в вашем приложении много ползунков или вам нужно несколько различных коэффициентов масштабирования, стоит создать подкласс QSlider, чтобы создать свой собственный QDoubleSlider.

Приведенный ниже класс основан на работе других, но имеет дополнительную функцию, которая вам понадобится, если вы ссылаетесь на QLineEdit или QDoubleSpinBox: новый сигнал для valueChanged, называемый doubleValueChanged.

class DoubleSlider(QSlider):

    # create our our signal that we can connect to if necessary
    doubleValueChanged = pyqtSignal(float)

    def __init__(self, decimals=3, *args, **kargs):
        super(DoubleSlider, self).__init__( *args, **kargs)
        self._multi = 10 ** decimals

        self.valueChanged.connect(self.emitDoubleValueChanged)

    def emitDoubleValueChanged(self):
        value = float(super(DoubleSlider, self).value())/self._multi
        self.doubleValueChanged.emit(value)

    def value(self):
        return float(super(DoubleSlider, self).value()) / self._multi

    def setMinimum(self, value):
        return super(DoubleSlider, self).setMinimum(value * self._multi)

    def setMaximum(self, value):
        return super(DoubleSlider, self).setMaximum(value * self._multi)

    def setSingleStep(self, value):
        return super(DoubleSlider, self).setSingleStep(value * self._multi)

    def singleStep(self):
        return float(super(DoubleSlider, self).singleStep()) / self._multi

    def setValue(self, value):
        super(DoubleSlider, self).setValue(int(value * self._multi))
person bfris    schedule 11.05.2018

После многих выводов это работает для меня:

# Connection Signals

# When user tweaks using the slider
self.slider.valueChanged[int].connect(self.update_spinbox)
# When user modify via the spinbox
self.spinbox_value.editingFinished.connect(self.update_slider)


# Functions for each modication made towards slider and spinbox
def update_slider(self):
    # spinbox_value uses float/ doubles type
    # '*100' is used to convert it into integer as QSlider
    # only register integer type
    spinbox_value = self.spinbox_value.value() * 100
    self.slider.setSliderPosition(spinbox_value)

def update_spinbox(self, value):
    # QSlider only uses integer type
    # Need to convert the value from integer into float
    # and divides it by 100
    self.spinbox_value.setValue(float(value) / 100)
person dissidia    schedule 17.03.2017

Я изменил ответ bfris, чтобы пользователь не мог отслеживать ползунок между шагами, как показано ниже. Класс использует другой метод для реализации использования чисел с плавающей запятой, что означает, что количество десятичных разрядов указывать не нужно.

Метод SetInterval эквивалентен сочетанию методов setTickInterval и setSingleStep, но также останавливает положение ползунка между значениями деления.

Класс также позволяет устанавливать и считывать индекс точки, выбранной на ползунке.

class DoubleSlider(qw.QSlider):

    def __init__(self, *args, **kargs):
        super(DoubleSlider, self).__init__( *args, **kargs)
        self._min = 0
        self._max = 99
        self.interval = 1

    def setValue(self, value):
        index = round((value - self._min) / self.interval)
        return super(DoubleSlider, self).setValue(index)

    def value(self):
        return self.index * self.interval + self._min

    @property
    def index(self):
        return super(DoubleSlider, self).value()

    def setIndex(self, index):
        return super(DoubleSlider, self).setValue(index)

    def setMinimum(self, value):
        self._min = value
        self._range_adjusted()

    def setMaximum(self, value):
        self._max = value
        self._range_adjusted()

    def setInterval(self, value):
        # To avoid division by zero
        if not value:
            raise ValueError('Interval of zero specified')
        self.interval = value
        self._range_adjusted()

    def _range_adjusted(self):
        number_of_steps = int((self._max - self._min) / self.interval)
        super(DoubleSlider, self).setMaximum(number_of_steps)
person Siyh    schedule 26.04.2020