Skip to main content

PyQt5 widgets for rendering and editing mathematical formulas

Project description

pyqt5-math-widget

A PyQt5 library for rendering and interactively editing mathematical formulas. No LaTeX engine required — everything is rendered natively via QPainter.


Installation

pip install pyqt5-math-widget

Widgets

Class Purpose
MathView Read-only formula renderer
MathEditor Interactive formula editor with toolbar
MathDialog Modal dialog wrapping MathEditor

MathView — read-only renderer

Basic usage

from pyqt5_math_widget import MathView, FracNode, TextNode, SqrtNode

view = MathView()
view.set_node(FracNode(TextNode("1"), SqrtNode(TextNode("x"))))
layout.addWidget(view)

From a FormulaModel

from pyqt5_math_widget import MathView, FormulaModel

model = FormulaModel()
model.insert_frac()
model.insert_greek("pi")

view = MathView.from_model(model)

API

view.set_node(node)           # Set formula from a FormulaNode
view.set_model(model)         # Attach a FormulaModel
view.set_text("sin(x)")       # Set from plain text
view.set_zoom(1.5)            # Scale factor (default 1.0)
view.zoom()                   # -> float
view.set_background(color)    # QColor fill
view.set_transparent(True)    # Transparent background
view.set_padding(16, 12)      # Horizontal, vertical padding in px
view.set_foreground(color)    # Global text colour
view.to_pixmap(scale=2.0)     # -> QPixmap (for export/saving)
view.to_latex()               # -> str
view.to_sympy()               # -> str
view.to_text()                # -> str
view.model()                  # -> FormulaModel

MathEditor — interactive editor

Basic usage

from pyqt5_math_widget import MathEditor

editor = MathEditor()
editor.formula_changed.connect(lambda s: print("sympy:", s))
editor.latex_changed.connect(lambda s: print("latex:", s))
layout.addWidget(editor)

Constructor parameters

MathEditor(
    parent=None,
    show_toolbar=True,          # Show button toolbar below canvas
    toolbar_groups=None,        # List of group names to show (see below)
    zoom=1.0,                   # Initial zoom level
    readonly=False,             # Disable editing
)

Toolbar groups

Pass a subset of these strings to toolbar_groups:

Group Contents
"struct" fraction, sqrt, power, subscript, integral, sum, product, limit, matrix, ...
"operators" +, -, ·, ×, =, ≠, ≤, ≥, ±, ≈, ∂, ∇, ∈, ∀, →, ...
"greek" α β γ δ ε θ λ μ ν π ρ σ τ φ ψ ω Σ Π Γ Δ Θ Ω ∞ ...
"functions" sin cos tan arcsin log ln exp max min det tr ...
"edit" Delete, Clear, ← →, Undo, Redo
editor.set_toolbar_groups(["struct", "greek", "edit"])

Programmatic insertion API

editor.insert_frac()                   # Fraction a/b
editor.insert_sqrt(nth=False)          # Square root
editor.insert_sqrt(nth=True)           # Nth root
editor.insert_power(wrap_current=True) # Superscript
editor.insert_subscript()              # Subscript
editor.insert_power_sub()              # Combined x^n_m
editor.insert_parens("(", ")")         # Parentheses (any bracket pair)
editor.insert_parens("[", "]")         # Square brackets
editor.insert_abs()                    # |x|
editor.insert_integral(definite=True)  # Definite integral
editor.insert_integral(definite=False) # Indefinite integral
editor.insert_sum(with_limits=True)    # Sum Σ
editor.insert_product(with_limits=True)# Product Π
editor.insert_limit()                  # lim
editor.insert_matrix(2, 2, "(")        # 2x2 matrix with round brackets
editor.insert_matrix(3, 3, "[")        # 3x3 matrix with square brackets
editor.insert_overline()               # Overline
editor.insert_underline()              # Underline
editor.insert_func("sin")             # sin(...) function
editor.insert_greek("alpha")          # α
editor.insert_operator("->")          # →
editor.insert_text("x", italic=True)  # Plain character
editor.insert_node(my_node)           # Raw FormulaNode

Editing control

editor.delete_at_cursor()    # Delete at cursor (Backspace)
editor.clear()               # Clear entire formula
editor.undo()                # Ctrl+Z
editor.redo()                # Ctrl+Y
editor.can_undo()            # -> bool
editor.can_redo()            # -> bool
editor.cursor_left()         # Move cursor left
editor.cursor_right()        # Move cursor right

Output

editor.to_sympy()    # "integrate(sin(x), x)"
editor.to_latex()    # r"\int \sin(x)\,dx"
editor.to_text()     # "integrate(sin(x), x)"
editor.to_pixmap(scale=2.0)   # -> QPixmap

Display control

editor.set_zoom(1.5)
editor.set_readonly(True)
editor.set_toolbar_visible(False)
editor.model()                # -> FormulaModel for direct access
editor.set_model(model)       # Replace model

MathDialog — modal dialog

from pyqt5_math_widget import MathDialog
from PyQt5.QtWidgets import QDialog

dlg = MathDialog(
    parent=self,
    title="Insert Formula",
    initial_text="sin(x)",
    toolbar_groups=["struct", "greek", "edit"],
    show_output=True,
    zoom=1.1,
)
if dlg.exec_() == QDialog.Accepted:
    print(dlg.result_sympy())
    print(dlg.result_latex())
    print(dlg.result_text())

Connect the signal without blocking:

dlg = MathDialog(parent=self)
dlg.accepted_formula.connect(lambda s: print("inserted:", s))
dlg.show()

FormulaModel — programmatic tree manipulation

from pyqt5_math_widget import FormulaModel

model = FormulaModel()
model.insert_frac()
model.insert_text("x")
model.move_right()
model.insert_text("2")

print(model.to_sympy())  # (x) / (2)
print(model.to_latex())  # \frac{x}{2}

model.undo()
model.redo()
model.clear()

Formula node tree

Build a formula tree and display it statically:

from pyqt5_math_widget import (
    MathView, SeqNode, TextNode, FracNode, SqrtNode,
    PowerNode, IntegralNode, SumProdNode, MatrixNode,
    ParenNode, AbsNode,
)

root = SeqNode([
    TextNode("E"),
    TextNode("="),
    FracNode(
        TextNode("m"),
        SqrtNode(SeqNode([TextNode("1"), TextNode("-"), PowerNode(TextNode("v"), TextNode("2"))])),
    ),
])

view = MathView()
view.set_node(root)

Available node types

Class Description
TextNode(text, size, italic, bold, color) Text / symbol
PlaceholderNode(size) Editable placeholder
SeqNode(children) Horizontal sequence
FracNode(num, den) Fraction
SqrtNode(body, index=None) Square / nth root
PowerNode(base, exp) Superscript
SubNode(base, sub) Subscript
PowerSubNode(base, exp, sub) Combined sup+sub
ParenNode(body, left, right) Scalable brackets
AbsNode(body) Absolute value
IntegralNode(body, var, lower, upper) Integral
SumProdNode(kind, body, var, lower, upper) Sum / Product
LimitNode(body, var, approach, direction) Limit
MatrixNode(rows, left, right) Matrix
OverlineNode(body) Overline
UnderlineNode(body) Underline

Each node implements:

node.to_sympy()   # SymPy expression string
node.to_latex()   # LaTeX string
node.to_text()    # Plain text
node.measure(painter)  # -> RenderMetrics
node.draw(painter, x, y, hits, selected, cursor_id)
node.collect_ids()     # -> List[int]
node.clone()           # deep copy

Constants and maps

from pyqt5_math_widget import GREEK_MAP, OPERATOR_MAP

GREEK_MAP["alpha"]   # -> "α"
OPERATOR_MAP["->"]   # -> "→"

Integration

from pyqt5_math_widget import MathDialog
from PyQt5.QtWidgets import QPushButton

btn = QPushButton("\u03A3")
btn.clicked.connect(lambda: self._open_formula_editor())

def _open_formula_editor(self):
    dlg = MathDialog(initial_text=self._input.text(), parent=self.window())
    if dlg.exec_():
        self._input.setText(dlg.result_sympy())

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyqt5_math_widget-1.2.0.tar.gz (38.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyqt5_math_widget-1.2.0-py3-none-any.whl (38.5 kB view details)

Uploaded Python 3

File details

Details for the file pyqt5_math_widget-1.2.0.tar.gz.

File metadata

  • Download URL: pyqt5_math_widget-1.2.0.tar.gz
  • Upload date:
  • Size: 38.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.10

File hashes

Hashes for pyqt5_math_widget-1.2.0.tar.gz
Algorithm Hash digest
SHA256 891f941c868ef66ada6e83d6f8be9cfa80c579d1b29289cdd6fb22fe6f270196
MD5 3420e4d7ee39f707a9713ba299546685
BLAKE2b-256 69884127bf3519512c852b18dc8810ead2aa8609fcc63f5371dacd8e277938aa

See more details on using hashes here.

File details

Details for the file pyqt5_math_widget-1.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pyqt5_math_widget-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8705c101fd548d3db3f1410aa2306db2a2fe216ee65c9c56f9daffc74a06cc45
MD5 551cadff5ced6ea7b75a6f7ac40e61b4
BLAKE2b-256 7382c6be68548cacf6d92cd3ad124415ac4108d12acf60c2c5e9ea7f02b8b63a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page