Pages

Thursday, March 12, 2026

Python Qt6 : schemdraw - 001.

Today, simple example with PyQt6 and schemdraw :
# -*- coding: utf-8 -*-
import sys
import schemdraw
import schemdraw.elements as elm
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout, QScrollArea
from PyQt6.QtGui import QPixmap
def draw_bistabil_grid(state):
    """
    state = 0 -> switch spre R3, LED1 aprins
    state = 1 -> switch spre R4, LED2 aprins
    """
    with schemdraw.Drawing(file='bistabil_grid.png', show=False) as d:
        d.config(unit=2.0)

        # Y COORDINATES
        y_led = 0.0
        y_r1  = -2.0
        y_rfb = -4.0
        y_swT = -7.0
        y_gnd = -10.0

        # X COORDINATES
        x_left   = -6.0
        x_right  = 6.0
        x_t1     = -3.0
        x_t2     = 3.0
        x_sw     = 0.0

        # COLORS
        col_T1 = 'green'
        col_T2 = 'orange'

        # LED-uri colorate în funcție de state
        led1_color = 'red' if state == 0 else 'gray'
        led2_color = 'red' if state == 1 else 'gray'

        # 1. LED1 and LED2
        led1 = d.add(elm.LED().down().at((x_left, y_led)).color(led1_color).label('LED1'))
        led2 = d.add(elm.LED().down().at((x_right, y_led)).color(led2_color).label('LED2'))

        # 2. R1 and R2
        r1 = d.add(elm.Resistor().down().at(led1.end).label('R1'))
        r2 = d.add(elm.Resistor().down().at(led2.end).label('R2'))

        n_r1 = d.add(elm.Dot().at(r1.end))
        n_r2 = d.add(elm.Dot().at(r2.end))

        # 3. R3 and R4 (feedback)
        d.add(elm.Line().at(n_r1.center).to((x_t1, y_rfb)))
        r3 = d.add(elm.Resistor().right().at((x_t1, y_rfb)).label('R3'))
        n_r3 = d.add(elm.Dot().at(r3.end))

        d.add(elm.Line().at(n_r2.center).to((x_t2, y_rfb)))
        r4 = d.add(elm.Resistor().left().at((x_t2, y_rfb)).label('R4'))
        n_r4 = d.add(elm.Dot().at(r4.end))

        # 4. Transistors
        t1 = d.add(
            elm.BjtNpn()
            .left()
            .flip()
            .at((x_t1, y_swT))
            .anchor('base')
            .label('T1')
        )

        t2 = d.add(
            elm.BjtNpn()
            .right()
            .at((x_t2, y_swT))
            .anchor('base')
            .label('T2')
        )

        # BASE CONNECTIONS
        d.add(elm.Line().at(n_r4.center).to(t1.base).color(col_T1))
        d.add(elm.Line().at(n_r3.center).to(t2.base).color(col_T2))

        # COLLECTOR CONNECTIONS
        d.add(elm.Line().at(t1.collector).to(n_r1.center).color(col_T1))
        d.add(elm.Line().at(t2.collector).to(n_r2.center).color(col_T2))

        # -------------------------------
        # 5. SWITCH SPDT DESENAT MANUAL
        # -------------------------------

        # Punctele a, b, c
        a = d.add(elm.Dot().at((x_sw - 1, y_swT)))
        b = d.add(elm.Dot().at((x_sw,     y_swT)))
        c = d.add(elm.Dot().at((x_sw + 1, y_swT)))

        # Linii FIXE către R3 și R4
        d.add(elm.Line().at(n_r3.center).to(a.center))
        d.add(elm.Line().at(n_r4.center).to(c.center))

        # Linia FIXĂ către GND
        d.add(elm.Line().at(b.center).to((b.center[0], y_gnd)))

        # Brațul mobil (UNICA linie care se mișcă)
        if state == 0:
            d.add(elm.Line().at(b.center).to(a.center))
        else:
            d.add(elm.Line().at(b.center).to(c.center))

        # 6. Ground bus
        d.add(
            elm.Line()
            .at((x_left - 2, y_gnd))
            .to((x_right + 2, y_gnd))
            .label('0V', loc='bottom')
        )
        d.add(elm.Ground().at((x_left - 2, y_gnd)))

        # EMITTERS TO GND
        d.add(elm.Line().at(t1.emitter).to((t1.emitter[0], y_gnd)).color(col_T1))
        d.add(elm.Line().at(t2.emitter).to((t2.emitter[0], y_gnd)).color(col_T2))


class BistabilGUI(QWidget):
    def __init__(self):
        super().__init__()

        self.state = 0

        self.setWindowTitle("Bistabil Animat – Schema completă")

        # Scroll area
        self.scroll = QScrollArea()
        self.label = QLabel()
        self.scroll.setWidget(self.label)
        self.scroll.setWidgetResizable(True)

        self.button = QPushButton("Comută switch-ul")
        self.button.clicked.connect(self.toggle_switch)

        layout = QVBoxLayout()
        layout.addWidget(self.scroll)
        layout.addWidget(self.button)
        self.setLayout(layout)

        self.update_image()

    def toggle_switch(self):
        self.state = 1 - self.state
        self.update_image()

    def update_image(self):
        draw_bistabil_grid(self.state)
        pix = QPixmap("bistabil_grid.png")
        self.label.setPixmap(pix)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    gui = BistabilGUI()
    gui.show()
    sys.exit(app.exec())