I am writing a small GUI with PyQt5 that links two series of values (let\'s call them a, b, c and alpha, beta respectively). All numbers are input via QDoubleSpinBox widgets.
From what I understand you want that if "a", "b" or "c" is modified by the user you should only modify "alpha" and "beta" using f1, and change "alpha" and "beta" it does not change "a", "b" and "c". The same for the case of "alpha" and "beta" with f2. If so, then the solution is to block the emission of signals from the elements that are changed programmatically since this is the reason for the infinite recursion using blockSignals().
from PyQt5 import QtCore, QtGui, QtWidgets
def f1(a, b, c):
return 1 / (1 + a ** 2 + b ** 2 + c ** 2) ** 0.5, a + b + c
def f2(alpha, beta):
return (
alpha + beta,
1 / (alpha ** 2 + beta ** 2 + 1),
(alpha ** 2 + beta ** 2) ** 0.5,
)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
max_f = 1.7976931348623157e308
min_f = -max_f
self.m_a_dsp = QtWidgets.QDoubleSpinBox(
value=0,
valueChanged=self.update_alpha_beta,
minimum=min_f,
maximum=max_f,
)
self.m_b_dsp = QtWidgets.QDoubleSpinBox(
value=0,
valueChanged=self.update_alpha_beta,
minimum=min_f,
maximum=max_f,
)
self.m_c_dsp = QtWidgets.QDoubleSpinBox(
value=0,
valueChanged=self.update_alpha_beta,
minimum=min_f,
maximum=max_f,
)
self.m_alpha_dsp = QtWidgets.QDoubleSpinBox(
value=0,
valueChanged=self.update_a_b_c,
minimum=min_f,
maximum=max_f,
)
self.m_beta_dsp = QtWidgets.QDoubleSpinBox(
value=0,
valueChanged=self.update_a_b_c,
minimum=min_f,
maximum=max_f,
)
lay = QtWidgets.QGridLayout(self)
lay.addWidget(self.m_a_dsp, 0, 0, 1, 2)
lay.addWidget(self.m_b_dsp, 0, 2, 1, 2)
lay.addWidget(self.m_c_dsp, 0, 4, 1, 2)
lay.addWidget(self.m_alpha_dsp, 1, 0, 1, 3)
lay.addWidget(self.m_beta_dsp, 1, 3, 1, 3)
@QtCore.pyqtSlot()
def update_alpha_beta(self):
alpha, beta = f1(
self.m_a_dsp.value(), self.m_b_dsp.value(), self.m_c_dsp.value()
)
for spinbox, value in zip(
(self.m_alpha_dsp, self.m_beta_dsp), (alpha, beta)
):
spinbox.blockSignals(True)
spinbox.setValue(value)
spinbox.blockSignals(False)
@QtCore.pyqtSlot()
def update_a_b_c(self):
a, b, c = f2(self.m_alpha_dsp.value(), self.m_beta_dsp.value())
for spinbox, value in zip(
(self.m_a_dsp, self.m_b_dsp, self.m_c_dsp), (a, b, c)
):
spinbox.blockSignals(True)
spinbox.setValue(value)
spinbox.blockSignals(False)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())