如何解除循环的互相更新微件?

2024-09-24 22:23:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用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)

到目前为止,我还没有找到一个合适的解决办法。也许在我尝试这样做的方式中有一些根本的缺陷。你知道吗


Tags: selfalpha部件defconnectupdategui数字
1条回答
网友
1楼 · 发布于 2024-09-24 22:23:34

据我所知,如果用户修改了“a”、“b”或“c”,则只应使用f1修改“alpha”和“beta”,更改“alpha”和“beta”,而不更改“a”、“b”和“c”。对于带有f2的“alpha”和“beta”的情况也是如此。如果是这样,那么解决方案是阻止以编程方式更改的元素发出信号,因为这是使用^{}进行无限递归的原因。你知道吗

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

相关问题 更多 >