一个简单的"弹簧力值计算器"

有意思的是把数据model独立出来的写法


  • txt_syc可以绑定多个lineedit,其中一个文字发生更改后,其它的会同时改动。
  • txt_syc可以connect信号接收器,当自己的值发生改变后,接收器会执行一此操作。
  • txt_syc可以更改自己的值,相当的ui和函数可以自动触发。

from PySide6.QtWidgets import (
    QApplication,
    QGroupBox,
    QFormLayout,
    QLineEdit,
)
from PySide6.QtCore import Signal
import qdarktheme
from typing import Any, Callable, ClassVar, Protocol, TypeVar, runtime_checkable

T = TypeVar("T")

# region model


@runtime_checkable
class txt_holder(Protocol):
    textChanged: ClassVar[Signal]

    def setText(self, s: str): ...
    def text(self) -> str: ...


class txt_syc:
    """文字同步修改器"""

    def __init__(self, s: str = "", name=""):
        self._value: str = s
        self._old_value: str = s
        self.name = name
        self._ents: list[txt_holder] = []
        self._fns: list[Callable[[str], Any]] = []

    @property
    def txt(self):
        return self._value

    @txt.setter
    def txt(self, v: str):
        vv = str(v)
        if vv != self._old_value:
            self._old_value = self._value
            self._value = vv
            for fn in self._fns:
                try:
                    fn(self._value)
                except Exception as e:
                    print(e)
            for i in self._ents:
                if i.text() != vv:
                    i.setText(vv)
    # 重载了运算符 +
    def __radd__(self, tt: T) -> T:
        if isinstance(tt, txt_holder):

            self._ents.append(tt)
            tt.textChanged.connect(self.set_text)  # type: ignore
            tt.setText(self.txt)
            return tt
        else:
            raise NotImplemented

    def set_text(self, v: str):
        self.txt = v

    def connect(self, fn: Callable[[str], Any]):
        self._fns.append(fn)
    # 重载了运算符 >>
    def __rshift__(self, fn: Callable[[str], Any]):
        self.connect(fn)
        return self


# endregion


class spring:
    """弹簧K值和压缩量计算"""

    def __init__(self) -> None:
        self.g = txt_syc("79800", "G N/mm\u00b2") >> self.on_change_g1 # 重载了运算符 >>
        self.d1 = txt_syc("3", "线径 mm") >> self.on_change_g1
        self.d2 = txt_syc("15", "中径 mm") >> self.on_change_g1
        self.n = txt_syc("2", "圈数   ") >> self.on_change_g1
        self.k = txt_syc("119.7", "K  N/mm")
        self.f = txt_syc("210", "F  N   ") >> self.on_change_g1
        self.ll = txt_syc("1.75", "压缩行程 mm")

        self.edit = [self.g, self.d1, self.d2, self.n, self.f]
        self.readonly = [self.k, self.ll]

    def on_change_g1(self, s):
        try:
            g = float(self.g.txt)
            d2 = float(self.d2.txt)
            d1 = float(self.d1.txt)
            n = float(self.n.txt)
            f = float(self.f.txt)

            k = g / 8 * d1**4 / d2**3 / n
            l1 = f / k
            print(g, d1, d2, n, f, k, l1)
            self.k.txt = f"{k:.4f}"
            self.ll.txt = f"{l1:.4f}"

        except:
            pass


class gp(QGroupBox):
    def __init__(self):
        super().__init__()
        self.setStyleSheet(
            """
            [level="groupbox"] {border:2px solid #FF7E72;margin-top:5px;margin:20px;}
            [level="groupbox"]::title{subcontrol-origin:margin;  padding:0.3px;margin-top:10px;}

            """
        )
        self.setTitle("弹簧K值")
        self.setProperty("level", "groupbox")
        # 初始化模型
        self.ss = spring()

        # 布局
        ly = QFormLayout()
        self.setLayout(ly)

        # 添加行
        for i in self.ss.edit:
            ly.addRow(i.name, QLineEdit() + i) # 重载了运算符
        for i in self.ss.readonly:
            ly.addRow(i.name, g := QLineEdit() + i)# 重载了运算符
            g.setReadOnly(True)


if __name__ == "__main__":

    app = QApplication()
    qdarktheme.setup_theme("light")
    window = gp()
    window.show()
    app.exec()

posted @ 2025-04-02 12:02  方头狮  阅读(87)  评论(0)    收藏  举报