如何在Qt中创建联动滑块?

3
我想创建一个GUI,其中有三个水平滑块来控制一些概率。每个滑块的范围都可以在0-1.0之间,但所有三个滑块在任何时候都必须加起来等于1.0。这里是我发现的一个链接,它使用jQuery实现了我想要的功能:链接
有没有在Qt中实现这个功能的好方法?具体而言,PyQt是否可行,但我认为伪代码也足够了。

你提供的插件可在MIT和GPL许可下使用- 你可以自由地使用源代码以任何目的。如果它已经满足你的需求,为什么不直接将其翻译成PyQt呢? - David Cain
2个回答

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

@KubaOber 我将实际值单独存储为浮点数(滑块使用整数,不够精确),但我认为最好将这些值存储在现有对象内部...我会编辑答案。 - Oleh Prypin
@KubaOber 你错了。例如,想象一下这种情况:滑块1变化了1,那么滑块2将变化1,滑块3将变化0。任何奇数次更改都会发生类似的错误。重复多次,就会得到完全错误的结果。我尝试过不使用浮点数来解决这个问题,但是类似于我的解释发生了一些问题。此外,Python中的float实际上有64位...而int则是无限制的。 - Oleh Prypin
这不是错误。怎么可能是错误呢?总和仍然相同。此外,祝你好运,用鼠标将它们更改一个以上,范围设置为大于2倍水平屏幕分辨率的东西。除非你希望每个人都按箭头键数千次。你的“错误”是完全捏造出来的问题。同样,64位浮点数的有效数字比64位整数少。而且不存在“无限”的整数。你可以选择使用多少位,但它并不是无限的。嗯,直到你得到那台有无限内存的神奇电脑。 - Kuba hasn't forgotten Monica
Python中的整数实现方式并不重要。Qt会像C和C++编译器一样看待它们。通常是32位。Python如何将多精度整数转换为平台整数,我不清楚 -- 希望它会饱和它们而不是做模运算。无论哪种方式都没用。 - Kuba hasn't forgotten Monica
1
@BlaXpirit 我该如何接受它?我想感谢你提供答案,而不是Kuba。 - Alexander Van Atta
显示剩余4条评论

0

您需要将滑块的valueChanged信号连接到自己定义的槽函数。在这个槽函数中,您可以实现所有滑块新值的计算,并使用setValue槽函数来应用这些新值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接