在 PyQt5 中同步两个元素值
Synchronize two element values in PyQt5
我在 PyQt5 中并排显示了一个滑块和一个包含整数的文本框(是否有专用的整数框?)。
我需要同步这两个值,我现在的做法是使用 QtTimer 和 if 语句检测一个值是否比另一个值最近更改,然后更新相反的元素。有人告诉我这是 "hacky",我想知道是否有合适的方法来做到这一点。
您可以在下图中的清晰区域看到我需要同步的文本框值和滑块。
您可以直接将每个滑块连接到另一个滑块。我不知道你想要的滑块之间的确切连接,但它可能看起来像这样。
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。
简单的解决方案是将每个 slider/number 框的 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)
更好的解决方案是定义一个自定义滑块 class 在内部处理所有内容。这样你只需要处理一次同步。
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可以简化为
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
上显式设置任何内容,因为上面建立的 signal/slot 连接会处理它。
@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)
我在 PyQt5 中并排显示了一个滑块和一个包含整数的文本框(是否有专用的整数框?)。
我需要同步这两个值,我现在的做法是使用 QtTimer 和 if 语句检测一个值是否比另一个值最近更改,然后更新相反的元素。有人告诉我这是 "hacky",我想知道是否有合适的方法来做到这一点。
您可以在下图中的清晰区域看到我需要同步的文本框值和滑块。
您可以直接将每个滑块连接到另一个滑块。我不知道你想要的滑块之间的确切连接,但它可能看起来像这样。
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。
简单的解决方案是将每个 slider/number 框的 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)
更好的解决方案是定义一个自定义滑块 class 在内部处理所有内容。这样你只需要处理一次同步。
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可以简化为
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
上显式设置任何内容,因为上面建立的 signal/slot 连接会处理它。
@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)