在PyQt5中同步两个元素值

时间:2016-07-26 03:46:41

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

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

我需要同步这两个值,我现在正在使用的方法是使用QtTimer和if语句检测一个值是否比另一个更新,然后更新相反的元素。我被告知这是" hacky"并且想知道是否有适当的方法来做到这一点。

您可以在下面图片的清晰区域中看到我需要同步的文本框值和滑块。

Interface example

2 个答案:

答案 0 :(得分:3)

简单的解决方案是将每个滑块/数字框的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的评论,上述课程可以简化为

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)

答案 1 :(得分:1)

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

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,可能会有所帮助。