0

I am currently doing a GUI using PyQt4. My question is the following : how to pass down the QtGui.QSlider's value across different QtGui.QTabWidget? Here is a minimal working example containing 3 tabs :

import numpy as np
from PyQt4 import QtCore, QtGui
import matplotlib.pyplot as plt
#
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
#%%
# some Arbitrary data
nbr_points = 500
my_X_data = np.linspace(-10,10,nbr_points)
#
my_Y_data_tab1 = my_X_data**3 + 100*np.cos(my_X_data*5)
my_Y_data_tab2 = np.tan(my_X_data)
my_Y_data_tab3 = -10*my_X_data *np.sin(my_X_data)

class MyWidget(QtGui.QMainWindow):
    def __init__(self):
        super(MyWidget, self).__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(600,300,1000,600) 
        tabs = QtGui.QTabWidget() 
        # creation of 3 tabs
        self.tab_plot1 = QtGui.QWidget()
        self.tab_plot2 = QtGui.QWidget()
        self.tab_plot3 = QtGui.QWidget()
        # 
        self.setCentralWidget(tabs) 
        #
        self.tab_plot_1()
        self.tab_plot_2()
        self.tab_plot_3()
        tabs.addTab(self.tab_plot1, 'tab1')
        tabs.addTab(self.tab_plot2, 'tab2')
        tabs.addTab(self.tab_plot3, 'tab3')
        self.show()

    def tab_plot_1(self):
        self.figure_1 = plt.figure(figsize=(15,5))
        self.canvas_1 = FigureCanvas(self.figure_1)
        # Slider
        self.slider_1 = QtGui.QSlider(minimum=0, 
            maximum= nbr_points-1, 
            orientation=QtCore.Qt.Horizontal,
            tickInterval=1)
        self.slider_1.valueChanged.connect(self.on_valueChanged_1)
        ax = self.figure_1.add_subplot(111)
        ax.clear()
        ax.plot(my_X_data,my_Y_data_tab1,'b-')        
        ax.set_xlim([-10,10])  
        ax.set_ylim([-1000,1000])  
        X_point, Y_point = [],[]
        self.scat_1 = ax.scatter(X_point, Y_point, s=100,c='k')
        layout = QtGui.QFormLayout()
        layout.addRow(self.canvas_1)
        layout.addRow(self.slider_1)
        self.tab_plot1.setLayout(layout)       

    def tab_plot_2(self):
        self.figure_2 = plt.figure(figsize=(15,5))
        self.canvas_2 = FigureCanvas(self.figure_2)
        # Slider
        self.slider_2 = QtGui.QSlider(minimum=0, 
            maximum= nbr_points-1, 
            orientation=QtCore.Qt.Horizontal,
            tickInterval=1)
        self.slider_2.valueChanged.connect(self.on_valueChanged_2)
        ax = self.figure_2.add_subplot(111)
        ax.clear()
        ax.plot(my_X_data,my_Y_data_tab2,'r-')        
        ax.set_xlim([-10,10])  
        ax.set_ylim([-1000,1000])  
        X_point, Y_point = [],[]
        self.scat_2 = ax.scatter(X_point, Y_point, s=100,c='k')
        layout = QtGui.QFormLayout()
        layout.addRow(self.canvas_2)
        layout.addRow(self.slider_2)
        self.tab_plot2.setLayout(layout)

    def tab_plot_3(self):
        self.figure_3 = plt.figure(figsize=(15,5))
        self.canvas_3 = FigureCanvas(self.figure_3)
        # Slider
        self.slider_3 = QtGui.QSlider(minimum=0, 
            maximum= nbr_points-1, 
            orientation=QtCore.Qt.Horizontal,
            tickInterval=1)
        self.slider_3.valueChanged.connect(self.on_valueChanged_3)
        ax = self.figure_3.add_subplot(111)
        ax.clear()
        ax.plot(my_X_data,my_Y_data_tab3,'g-')        
        ax.set_xlim([-10,10])  
        ax.set_ylim([-1000,1000])  
        X_point, Y_point = [],[]
        self.scat_3 = ax.scatter(X_point, Y_point, s=100,c='k')
        layout = QtGui.QFormLayout()
        layout.addRow(self.canvas_3)
        layout.addRow(self.slider_3)
        self.tab_plot3.setLayout(layout)      

    @QtCore.pyqtSlot(int)
    def on_valueChanged_1(self, value):
        X_point = my_X_data[value,]
        Y_point = my_Y_data_tab1[value,]
        self.scat_1.set_offsets(np.c_[X_point,Y_point])   
        self.canvas_1.draw()

    @QtCore.pyqtSlot(int)
    def on_valueChanged_2(self, value):
        X_point = my_X_data[value,]
        Y_point = my_Y_data_tab2[value,]
        self.scat_2.set_offsets(np.c_[X_point,Y_point])   
        self.canvas_2.draw()

    @QtCore.pyqtSlot(int)
    def on_valueChanged_3(self, value):
        X_point = my_X_data[value,]
        Y_point = my_Y_data_tab3[value,]
        self.scat_3.set_offsets(np.c_[X_point,Y_point])   
        self.canvas_3.draw()

def main():
    import sys
    app = QtGui.QApplication(sys.argv)
    w = MyWidget()
    w.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

In this case, the sliders' values should be pass down across the different tabs when there are locally modified in order to force the same local value to the other ones when browsing across tabs.

Last trials were unsuccessful ... Any help would be greatly appreciated.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Yacola
  • 2,873
  • 1
  • 10
  • 27
  • If the 3 sliders must have the same value, wouldn't it be simpler to have a single slider outside the `QTabWidget` ? – alexisdm Feb 13 '19 at 21:23
  • Yes, the 3 sliders must have the same value, but there are actually more tabs which do not require slider above/beneath them. – Yacola Feb 13 '19 at 21:52
  • @Yacola I do not understand you, that's your own question so you have the privileges to do the editing of that question – eyllanesc Feb 13 '19 at 22:02
  • @eyllanesc Nevermind, I just found out that I am the only one that can see the deleted duplicate answer of the post, sorry for your time :) – Yacola Feb 13 '19 at 22:13

1 Answers1

1

If I understand clearly, if the value on a slider is changed (e.g. slider_1), set that value to the other two sliders (slider_2 and slider_3)

e.g.

self.slider_1.valueChanged.connect(self.on_valueChanged_1)

When value on slider_1 is changed you are calling self.on_valueChanged_1, in that function you can just do:

def on_valueChanged_1(self, value):
    X_point = my_X_data[value,]
    Y_point = my_Y_data_tab1[value,]
    self.scat_1.set_offsets(np.c_[X_point,Y_point])   
    self.canvas_1.draw()

    # Get current value 
    curr_value = self.slider_1.value()
    # Set the value of the slider on which the value has been changed to the other two sliders
    self.slider_2.setValue(curr_value)
    self.slider_3.setValue(curr_value)

and repeat it for the other two sliders in functions on_valueChanged_2 and on_valueChanged_3

ncica
  • 7,015
  • 1
  • 15
  • 37
  • Thanks for your answer @ncica, that's working now, I don't know why I didn't think about this simple solution earlier ! – Yacola Feb 13 '19 at 18:27