Alexander Van Atta
Alexander Van Atta

Reputation: 890

How do you make linked sliders in Qt?

I am trying to build a GUI that has three horizontal sliders that control some probability. Each slider can range between 0 - 1.0 but all three together must equal 1.0 at all times. Here is a link I found that does what I want but with jQuery.

Is there any good way of doing this in Qt? PyQt more specifically but I think pseudo code will suffice.

Upvotes: 3

Views: 3524

Answers (2)

Oleh Prypin
Oleh Prypin

Reputation: 34116

class MainWindow(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        layout = QGridLayout()
        self.sliders = []
        slider_amount = 3
        slider_precision = 10000 # sliders work only with ints, so large ints are used and mapped to floats
        for i in range(slider_amount):
            slider = QSlider(Qt.Horizontal)
            slider.setRange(0, slider_amount*slider_precision)
            slider.setSingleStep(slider.maximum()/100.0)
            slider.setPageStep(slider.maximum()/20.0)
            slider.valueChanged.connect(self.on_slider_value_changed)
            slider.float_value = (i+1)/((1+slider_amount)/2.0*slider_amount) # provide your own default values
            slider.label = QLabel()
            self.sliders.append(slider)
            layout.addWidget(slider, i, 0)
            layout.addWidget(slider.label, i, 1)
        self.update_slider_values()
        self.setLayout(layout)
        self.show()

    def on_slider_value_changed(self, value):
        changed_slider = self.sender()
        changed_slider.float_value = float(value)/changed_slider.maximum()
        delta = sum(slider.float_value for slider in self.sliders)-1
        while abs(delta)>0.00001:
            d = len(self.sliders)-1
            for slider in self.sliders:
                if slider is changed_slider:
                    continue
                old_value = slider.float_value
                slider.float_value = min(max(0, old_value-delta/d), 1)
                delta -= old_value-slider.float_value
                d -= 1
        self.update_slider_values()

    def update_slider_values(self):
        for slider in self.sliders:
            slider_signals_blocked = slider.blockSignals(True)
            slider.setValue(round(slider.float_value*slider.maximum()))
            slider.blockSignals(slider_signals_blocked)
            slider.label.setText('{:.2f}'.format(slider.float_value))

app = QApplication(sys.argv)
mw = MainWindow()
app.exec_()

Upvotes: 3

Herr von Wurst
Herr von Wurst

Reputation: 2621

You would have to connect the valueChanged signal of the sliders to a slot you define yourself. In this slot (function) you can implement the calculation of the new values of all sliders and use the setValue slot to apply the new values.

Upvotes: 0

Related Questions