【问题标题】:Synchronize two element values in PyQt5在 PyQt5 中同步两个元素值
【发布时间】:2016-07-26 03:46:41
【问题描述】:

我有一个滑块和一个包含整数的文本框(是否有专用的整数框?)在 PyQt5 中并排显示。

我需要同步这两个值,而我现在这样做的方式是使用 QtTimer 和 if 语句检测一个值是否比另一个值最近更改,然后更新相反的元素。有人告诉我这是“hacky”,我想知道是否有合适的方法来做到这一点。

您可以在下图的空白区域看到我需要同步的文本框值和滑块。

【问题讨论】:

    标签: python python-3.x pyqt synchronization pyqt5


    【解决方案1】:

    简单的解决方案是将每个滑块/数字框的valueChanged 连接到同步值的插槽

    self.slider1.valueChanged.connect(self.handleSlider1ValueChange)
    self.numbox1.valueChanged.connect(self.handleNumbox1ValueChange)
    
    @QtCore.pyqtSlot(int)
    def handleSlider1ValueChange(self, value):
        self.numbox1.setValue(value)
    
    @QtCore.pyqtSlot(int)
    def handleNumbox1ValueChange(self.value):
        self.slider1.setValue(value)
    

    更好的解决方案是定义一个自定义滑块类,在内部处理所有内容。这样您只需处理一次同步。

    from PyQt5 import QtCore, QtWidgets
    
    class CustomSlider(QtWidgets.QWidget):
        def __init__(self, *args, **kwargs):
            super(CustomSlider, self).__init__(*args, **kwargs)
            self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
            self.slider.valueChanged.connect(self.handleSliderValueChange)
            self.numbox = QtWidgets.QSpinBox()
            self.numbox.valueChanged.connect(self.handleNumboxValueChange)
            layout = QtWidgets.QHBoxLayout(self)
            layout.addWidget(self.numbox)
            layout.addWidget(self.slider)
    
        @QtCore.pyqtSlot(int)
        def handleSliderValueChange(self, value):
            self.numbox.setValue(value)
    
        @QtCore.pyqtSlot(int)
        def handleNumboxValueChange(self, value):
            # Prevent values outside slider range
            if value < self.slider.minimum():
                self.numbox.setValue(self.slider.minimum())
            elif value > self.slider.maximum():
                self.numbox.setValue(self.slider.maximum())
    
            self.slider.setValue(self.numbox.value())
    
    app = QtWidgets.QApplication([])
    slider1 = CustomSlider()
    slider2 = CustomSlider()
    window = QtWidgets.QWidget()
    layout = QtWidgets.QVBoxLayout(window)
    layout.addWidget(slider1)
    layout.addWidget(slider2)
    window.show()
    app.exec_()
    

    编辑:关于来自ekhumoro的cmets,上面的类可以简化为

    class CustomSlider(QtWidgets.QWidget):
        def __init__(self, *args, **kwargs):
            super(CustomSlider, self).__init__(*args, **kwargs)
            self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
            self.numbox = QtWidgets.QSpinBox()
            self.numbox.setRange(self.slider.minimum(), self.slider.maximum())
            self.slider.valueChanged.connect(self.numbox.setValue)
            self.slider.rangeChanged.connect(self.numbox.setRange)
            self.numbox.valueChanged.connect(self.slider.setValue)
            layout = QtWidgets.QHBoxLayout(self)
            layout.addWidget(self.numbox)
            layout.addWidget(self.slider)
    

    您可能还想模仿一些QSlider 方法来更改范围和值。请注意,我们不需要在 self.numbox 上显式设置任何内容,因为上面建立的信号/插槽连接会处理它。

        @QtCore.pyqtSlot(int)
        def setMinimum(self, minval):
            self.slider.setMinimum(minval)
    
        @QtCore.pyqtSlot(int)
        def setMaximum(self, maxval):
            self.slider.setMaximum(maxval)
    
        @QtCore.pyqtSlot(int, int)
        def setRange(self, minval, maxval):
            self.slider.setRange(minval, maxval)
    
        @QtCore.pyqtSlot(int)
        def setValue(self, value):
            self.slider.setValue(value)
    

    【讨论】:

    • 滑块和旋转框已经有所需的插槽,所以你可以这样做:slider.valueChanged.connect(spinbox.setValue)。也无需进行任何边界检查 - 用户不能输入超出滑块/旋转框上设置的最小/最大范围的值(显然每个值都需要相同)。
    • 我打算将它作为用户定义插槽的更通用示例,但您是对的,这对于这个问题来说太过分了。不过,边界检查的要点。我不认为您可以对旋转框设置限制。我会更新你的建议
    • 您的解决方案比被接受的解决方案更好,因为它使用了旋转框。这确实简化了事情,因为滑块和旋转框的 API 非常相似。不过,您的示例代码并没有真正强调这种简单性。
    【解决方案2】:

    您可以直接将每个滑块连接到另一个滑块。我不知道你想要的滑块之间的确切连接,但它可能看起来像这样。

    max_player_slider.valueChanged.connect(self.slider1_fu)
    npc_stream_slider.valueChanged.conenct(self.slider2_fu)
    
    def slider1_fu(self):
        # do stuff with the npc_stream_slider
    
    def slider2_fu(self):
        # do stuff with the max_player_slider
    

    编辑:这是一个Tutorial on YouTube,可能会有所帮助。

    【讨论】:

    • 我认为@spikespaz 只是想将数值与滑块位置同步
    • @user3419537 糟糕,这完全有可能。我想我有点夸大了这个问题。不过,我发布的教程仍然适用。
    • 是的,两组滑块/文本框是分开的,但我会继续观看您发布的教程。感谢您的帮助。
    • 由于您发布的教程,我接受了您的回答。我最终将文本编辑框更改为带有框架的标签,然后将滑块与标签链接。
    猜你喜欢
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多