2016-07-26 4 views
0

Ich habe einen Schieberegler und ein Textfeld, das eine ganze Zahl (gibt es eine dedizierte Integer-Box?) In PyQt5 nebeneinander angezeigt.Synchronisieren Sie zwei Element Werte in PyQt5

Ich brauche diese beiden Werte synchronisiert werden, und die Art, wie ich es gerade mache, ist mit einem QtTimer und if-Anweisungen erkennen, wenn ein Wert in jüngerer Zeit als der andere geändert wurde, und aktualisieren Sie das andere Element. Mir wurde gesagt, dass dies "hacky" sei und ich frage mich, ob es einen richtigen Weg dafür gibt.

Sie können die Textfeldwerte und Schieberegler, die ich synchronisieren muss, in den klaren Bereichen des folgenden Bildes sehen.

Interface example

Antwort

1

Sie können nur jeden des Schiebereglers, um die andere, geradlinig verbinden. Ich weiß nicht die genaue Verbindung, die Sie zwischen den Schiebereglern wünschen, aber es könnte in etwa so aussehen.

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 

Edit: Hier ist ein Tutorial on YouTube die hilfreich sein könnten.

+0

Ich denke @spikespaz will nur den numerischen Wert mit dem Schieberegler Position synchronisieren – user3419537

+0

@ user3419537 Woops, das ist durchaus möglich. Ich schätze, ich habe das Problem ein wenig überstiegen. Das Tutorial, das ich gepostet habe, gilt jedoch immer noch. – Ian

+0

Ja, die beiden Gruppen von Slider/Textboxen sind getrennt, aber ich werde weitermachen und das von Ihnen gepostete Tutorial sehen. Danke für die Hilfe. – spikespaz

2

Die einfache Lösung ist die valueChanged für jeden Schieber/Nummernfeld auf einen Schlitz zu verbinden, die

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) 

Eine bessere Lösung die Werte synchronisiert ist eine benutzerdefinierte Slider-Klasse zu definieren, die alles intern behandelt. Auf diese Weise müssen Sie nur einmal mit der Synchronisation umgehen.

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

bearbeiten: Im Hinblick auf die Stellungnahme von ekhumoro kann die obige Klasse vereinfacht werden, um

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) 

Sie werden wahrscheinlich wollen auch einige der QSlider Methoden nachzuahmen sich ändern die Reichweite und den Wert. Beachten Sie, dass wir nichts explizit auf self.numbox setzen müssen, da die oben genannten Signal/Slot-Verbindungen dafür sorgen.

@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) 
+0

Der Slider und die Spinbox haben bereits die benötigten Slots, Sie können also einfach: 'slider.valueChanged.connect (spinbox.setValue)' '. Es ist auch nicht notwendig, irgendwelche Grenzen zu prüfen - der Benutzer * kann * keine Werte außerhalb des Min/Max-Bereichs eingeben, der auf dem Schieberegler/der Spinbox eingestellt ist (was natürlich für jeden gleich sein muss). – ekhumoro

+0

Ich dachte, es wäre ein generischeres Beispiel für benutzerdefinierte Slots, aber Sie haben recht, es ist zu viel für diese Frage. Guter Punkt bei der Überprüfung der Grenzen. Ich dachte nicht, dass Sie der Spinbox Grenzen setzen könnten. Ich werde mit Ihren Vorschlägen aktualisieren – user3419537

+0

Ihre Lösung ist besser als die, die akzeptiert wurde, weil es Spinboxen verwendet. Das vereinfacht die Dinge wirklich, weil die APIs von Slidern und Spinboxen so ähnlich sind. Ihr Beispielcode betont diese Einfachheit jedoch nicht wirklich. – ekhumoro