在PyQt中(优雅地)显示代数表达式

7
在我的Python程序中,我创建了一系列数学对象的层次结构来表示数学公式。例如,有一个Collection,它是一系列Equations,这些方程式包含两个SumsProductsQuotientsExponantsLogarithms,这些都建立在Figures之上,这些数字或变量可以是数字或变量。
我需要向用户显示进行某些任务的数学操作步骤,例如获取未知变量等。目前,我以纯文本形式生成这个“指南”,就像...
F = (m)(a)  
m = (F)/(a)  
a = 2, F = 3  
m = (3)/(2) = 1.5

然而,用纯文本表示复杂公式(例如:log[2](n)=(m)((a)^(2)))是不美观的,并且违背了程序的一个目标,即为用户保持最大的清晰度。

我目前正在使用PyQt4编写GUI,并需要制作一个公式(每个步骤)的表示,可以在Qt应用程序中显示。这些公式不需要是文本。由于对象结构,将对象转换为所需的标记文本非常容易。实际显示方法可以是任何形式,只要我可以将其干净地嵌入我的GUI中,例如SVG、图像等。

  • 起初,我考虑使用MathML,但是发现当显示HTML时,PyQt会忽略MathML标签,而一种名为QMmlWidget的工具曾经存在过,专门用于此任务,但已被弃用。
  • 后来我了解到,结合sympysvgmathQSvgWidget的组合可以正常工作,将公式显示为Svgs,但我需要能够分发我的代码,设置svgmath中的字体配置问题。
  • 我发现Display LaTeX Equations in-line with terminal 看起来很有前途,但是视频总长近4个小时,我没有这么耐心。

我几乎想自己编写代码,使用PIL或类似的工具将我的数学对象直接转换为图像,但我不想认为有人已经完成了这项工作并做得更好。

非常感谢任何和所有的帮助!
谢谢!


如果您已安装matplotlib,它具有出色的LaTeX支持(http://matplotlib.org/gallery.html)。 您可以使用它来生成图像,或查看它们是如何实现的。 - tacaswell
https://dev59.com/PGHVa4cB1Zd3GeqPkzsm - tacaswell
但我是否会遇到该页面讨论的所有问题呢?例如需要安装LaTeX等?我希望我的代码易于分发。 - Anti Earth
很好。在我的脑海中,“LaTeX”是一个必须安装的标准工具.... Qt能够处理HTML中的JavaScript吗?http://www.mathjax.org/ - tacaswell
我非常倾向于认为它不可能。 - Anti Earth
1个回答

6

这是来自Gulon.co.uk的博客内容,提供了一个简单而强大的示例,用于在pyQt中呈现LateX方程。我已经从那里复制并粘贴如下:

from PyQt4.QtCore import *

from PyQt4.QtGui import *

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas


class MathTextLabel(QWidget):

    def __init__(self, mathText, parent=None, **kwargs):
        QWidget.__init__(self, parent, **kwargs)

        l=QVBoxLayout(self)
        l.setContentsMargins(0,0,0,0)

        r,g,b,a=self.palette().base().color().getRgbF()

    self._figure=Figure(edgecolor=(r,g,b), facecolor=(r,g,b))
    self._canvas=FigureCanvas(self._figure)
    l.addWidget(self._canvas)

    self._figure.clear()
    text=self._figure.suptitle(
        mathText,
        x=0.0,
        y=1.0,
        horizontalalignment='left',
        verticalalignment='top',
        size=qApp.font().pointSize()*2)
    self._canvas.draw()

    (x0,y0),(x1,y1)=text.get_window_extent().get_points()
    w=x1-x0; h=y1-y0

    self._figure.set_size_inches(w/80, h/80)
    self.setFixedSize(w,h)

if __name__=='__main__':
    from sys import argv, exit

    class Widget(QWidget):
        def __init__(self, parent=None, **kwargs):
            QWidget.__init__(self, parent, **kwargs)

            l=QVBoxLayout(self)
            l.addWidget(QLabel("<h1>Discrete Fourier Transform</h1>"))

            mathText=r'$X_k = \sum_{n=0}^{N-1} x_n . e^{\frac{-i2\pi kn}{N}}$'
            l.addWidget(MathTextLabel(mathText, self),     alignment=Qt.AlignHCenter)

    a=QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())

转换为PyQt5
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtCore import Qt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas


class MathTextLabel(QtWidgets.QWidget):

    def __init__(self, mathText, parent=None, **kwargs):
        super(QtWidgets.QWidget, self).__init__(parent, **kwargs)

        l=QVBoxLayout(self)
        l.setContentsMargins(0,0,0,0)

        r,g,b,a=self.palette().base().color().getRgbF()

        self._figure=Figure(edgecolor=(r,g,b), facecolor=(r,g,b))
        self._canvas=FigureCanvas(self._figure)
        l.addWidget(self._canvas)
        self._figure.clear()
        text=self._figure.suptitle(
            mathText,
            x=0.0,
            y=1.0,
            horizontalalignment='left',
            verticalalignment='top',
            size=QtGui.QFont().pointSize()*2
        )
        self._canvas.draw()

        (x0,y0),(x1,y1)=text.get_window_extent().get_points()
        w=x1-x0; h=y1-y0

        self._figure.set_size_inches(w/80, h/80)
        self.setFixedSize(w,h)

if __name__=='__main__':
    from sys import argv, exit

    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None, **kwargs):
            super(QtWidgets.QWidget, self).__init__(parent, **kwargs)

            l=QVBoxLayout(self)
            mathText=r'$X_k = \sum_{n=0}^{N-1} x_n . e^{\frac{-i2\pi kn}{N}}$'
            l.addWidget(MathTextLabel(mathText, self), alignment=Qt.AlignHCenter)

    a=QtWidgets.QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())

这是我在下面发布的解决方案(4年前)相同的解决方案。 - Anti Earth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接