我正在用PyQt5编写一个小的GUI,它链接两个系列的值(我们分别称它们为a,b,c和alpha,beta)。所有数字都是通过QDoubleSpinBox小部件输入的。
这些数字可以通过两个函数相互计算:
alpha, beta = f1(a,b,c)
a,b,c = f2(alpha, beta)
问题在于,由于a,b,c的信号触发了修改alpha,beta的槽,反之亦然,因此,一旦我更改了某个东西的值,我就陷入了不断更新小部件的无限循环中,直到UI崩溃为止。在沿一个方向或另一个方向注释掉更新时,一切正常。
没有GUI布局的详细信息,这基本上就是我正在做的事情:
from PyQt5.QtWidgets import (QApplication, QWidget, QDoubleSpinBox)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
# initialize UI and widgets (not shown)
self.initUI()
# update alpha beta
self.a.valueChanged.connect(self.update_alphabeta)
self.b.valueChanged.connect(self.update_alphabeta)
self.c.valueChanged.connect(self.update_alphabeta)
# update abc
self.alpha.valueChanged.connect(self.update_abc)
self.beta.valueChanged.connect(self.update_abc)
def update_alphabeta(self):
alpha,beta = f1(self.a, self.b, self.c)
self.alpha.setValue(alpha)
self.beta.setValue(beta)
def update_abc(self):
a,b,c = f2(self.alpha, self.beta)
self.a.setValue(a)
self.b.setValue(b)
self.c.setValue(c)
到目前为止,我找不到合适的解决方案。我尝试执行此操作的方式可能存在根本缺陷。
答案 0 :(得分:1)
据我了解,您希望如果用户修改了“ a”,“ b”或“ c”,则只能使用f1修改“ alpha”和“ beta”,并更改“ alpha”和“ beta”它不会更改“ a”,“ b”和“ c”。对于带有f2的“ alpha”和“ beta”,情况相同。如果是这样,那么解决方案是阻止以编程方式更改的元素发出信号,因为这是使用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_())