Seite 1 von 1

Darstellung von Latexcode mit PyQt

Verfasst: Montag 21. März 2016, 14:10
von Brando
Hallo, ich habe eine Möglichkeit gefunden eine Latexdarstellung eines Vektors zu bilden. Allerdings weiß ich nicht, wie ich das in einem Label von PyQt ausgebe. Folgenden Code habe ich nicht zum Laufen gebracht:

Code: Alles auswählen

from PyQt4 import QtGui, QtCore

import sys
from sympy.matrices import *
from sympy.printing import *
from IPython.display import display, HTML, Math, Latex, clear_output
# from ipywidgets import widgets
from random import randint


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    mw = QtGui.QWidget()
    x = Matrix()
    x = Matrix([randint(-20,20), randint(-20,20), randint(-20,20)])
    a1 = latex(x)
    a1 = a1.replace("left[", "left(")
    a1 = a1.replace("right]", "right)")
    print (a1)
    labelPT = QtGui.QLabel()
    labelPT.setText("$\langle" + a1 + "\\rangle$")
    labelPT.setAlignment(QtCore.Qt.AlignRight)

    labelRT = QtGui.QLabel()
    labelRT.setText('one two three four <b>five</b> six seven eight nine ten')
    labelRT.setAlignment(QtCore.Qt.AlignRight)

    vbox = QtGui.QVBoxLayout()
    vbox.addWidget(labelPT)
    vbox.addWidget(labelRT)

    mw.setLayout(vbox)
    mw.setMinimumWidth(30)
    mw.show()

    sys.exit(app.exec_())
Inbsbesondere die Zeile: labelPT.setText("$\langle" + a1 + "\\rangle$")
funktioniert nicht.

Re: Darstellung von Latexcode mit PyQt

Verfasst: Mittwoch 23. März 2016, 08:57
von Brando
Hallo, jetzt habe ich Code gefunden, der Latex darstellt in PyQt. Allerdings kann ich den nicht so lesen, wie ich es mir wünsche. Wie kann ich meinen Vektor a1 - der jetzt nur leer herumsteht in dem Code und auf Latex formatiert wurde - in Latex mit PyQt darstellen. Was von dem Code brauche ich dazu?

Code: Alles auswählen

# -*- coding: utf-8 -*-
"""
Created on Wed Mar 23 08:30:13 2016

@author: rk480158
"""

import sys
import matplotlib as mpl
from matplotlib.backends.backend_agg import FigureCanvasAgg
from PyQt4  import QtGui, QtCore
import matplotlib.pyplot as plt
from matplotlib import rcParams
from sympy.matrices import *
from sympy.printing import *
from IPython.display import display, HTML, Math, Latex, clear_output
# from ipywidgets import widgets
from random import randint

def mathTex_to_QPixmap(mathTex, fs):

    #---- set up a mpl figure instance ----

    fig = mpl.figure.Figure()
    fig.patch.set_facecolor('none')
    fig.set_canvas(FigureCanvasAgg(fig))
    renderer = fig.canvas.get_renderer()

    #---- plot the mathTex expression ----

    ax = fig.add_axes([0, 0, 1, 1])
    ax.axis('off')
    ax.patch.set_facecolor('none')
    t = ax.text(0, 0, mathTex, ha='left', va='bottom', fontsize=fs)

    #---- fit figure size to text artist ----

    fwidth, fheight = fig.get_size_inches()
    fig_bbox = fig.get_window_extent(renderer)

    text_bbox = t.get_window_extent(renderer)

    tight_fwidth = text_bbox.width * fwidth / fig_bbox.width
    tight_fheight = text_bbox.height * fheight / fig_bbox.height

    fig.set_size_inches(tight_fwidth, tight_fheight)

    #---- convert mpl figure to QPixmap ----

    buf, size = fig.canvas.print_to_buffer()
    qimage = QtGui.QImage.rgbSwapped(QtGui.QImage(buf, size[0], size[1],
                                                  QtGui.QImage.Format_ARGB32))
    qpixmap = QtGui.QPixmap(qimage)

    return qpixmap
    
    
class MyQTableWidget(QtGui.QTableWidget):   
    def __init__(self, parent=None):
        super(MyQTableWidget, self).__init__(parent)

        self.setHorizontalHeader(MyHorizHeader(self))

    def setHorizontalHeaderLabels(self, headerLabels, fontsize):

        qpixmaps = []
        indx = 0
        for labels in headerLabels:
            qpixmaps.append(mathTex_to_QPixmap(labels, fontsize))            
            self.setColumnWidth(indx, qpixmaps[indx].size().width() + 16)
            indx += 1

        self.horizontalHeader().qpixmaps = qpixmaps

        super(MyQTableWidget, self).setHorizontalHeaderLabels(headerLabels)


class MyHorizHeader(QtGui.QHeaderView):
    def __init__(self, parent):
        super(MyHorizHeader, self).__init__(QtCore.Qt.Horizontal, parent)

        self.setClickable(True)
        self.setStretchLastSection(True)

        self.qpixmaps = []

    def paintSection(self, painter, rect, logicalIndex):

        if not rect.isValid():
            return

        #------------------------------ paint section (without the label) ----

        opt = QtGui.QStyleOptionHeader()        
        self.initStyleOption(opt)

        opt.rect = rect
        opt.section = logicalIndex
        opt.text = ""

        #---- mouse over highlight ----

        mouse_pos = self.mapFromGlobal(QtGui.QCursor.pos())               
        if rect.contains(mouse_pos):
            opt.state |= QtGui.QStyle.State_MouseOver

        #---- paint ----

        painter.save()        
        self.style().drawControl(QtGui.QStyle.CE_Header, opt, painter, self)
        painter.restore()

        #------------------------------------------- paint mathText label ----

        qpixmap = self.qpixmaps[logicalIndex]

        #---- centering ----

        xpix = (rect.width() - qpixmap.size().width()) / 2. + rect.x()
        ypix = (rect.height() - qpixmap.size().height()) / 2.

        #---- paint ----

        rect = QtCore.QRect(xpix, ypix, qpixmap.size().width(),
                            qpixmap.size().height())
        painter.drawPixmap(rect, qpixmap)        

    def sizeHint(self):

        baseSize = QtGui.QHeaderView.sizeHint(self)

        baseHeight = baseSize.height()
        if len(self.qpixmaps):
            for pixmap in self.qpixmaps:
               baseHeight = max(pixmap.height() + 8, baseHeight)
        baseSize.setHeight(baseHeight)

        self.parentWidget().repaint()

        return baseSize

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    rcParams['text.usetex'] = True
    rcParams['text.latex.preamble'] = r'\usepackage{amsmath}'

    w = MyQTableWidget()
    w.verticalHeader().hide()
    x = Matrix()
    x = Matrix([randint(-20,20), randint(-20,20), randint(-20,20)])
    a1 = latex(x) 
    
    headerLabels = [
        '$C_{soil}=(1 - n) C_m + \\theta_w C_w$',
        '$k_{soil}=\\frac{\\sum f_j k_j \\theta_j}{\\sum f_j \\theta_j}$',
        '$\\lambda_{soil}=k_{soil} / C_{soil}$']
    
    # headerLabels = [ a1,a1,a1]
    w.setColumnCount(len(headerLabels))
    w.setHorizontalHeaderLabels(headerLabels, 25)        
    w.setRowCount(3)
    w.setAlternatingRowColors(True)

    k = 1
    for j in range(3):
        for i in range(3):
            w.setItem(i, j, QtGui.QTableWidgetItem('Value %i' % (k)))
            k += 1

    w.show() 
    w.resize(700, 200)
    # w.resize(700,700)
    sys.exit(app.exec_())
Wenn ich die Sache mit a1 aktiviere(headerLabels so geändert wie es auskommentiert ist], dann kommt folgende Fehlermeldung:

RuntimeError: LaTeX was not able to process the following string:
'\\\\left[\\\\begin{matrix}8\\\\\\\\3\\\\\\\\8\\\\end{matrix}\\\\right]'

Wo kommen die vielen \ her?

Re: Darstellung von Latexcode mit PyQt

Verfasst: Mittwoch 23. März 2016, 10:13
von BlackJack
@Brando: Das ist der Versuch die \ so zu escapen das sie als Text dargestellt werden. Würde nicht passieren wenn Du nicht versuchen würdest Text zu setzen sondern eine Formel. Lass Dir mal `a1` ausgeben und vergleiche das mit den Formeln die Du manuell als LaTeX geschrieben hast, dann sollte Dir auffallen das `sympy.latex()` etwas weglässt was Du geschrieben hast. Schau Dir mal die Dokumention von der Funktion an, dann weisst Du a) was das ist was fehlt, und b) wie man das ändern kann. :-)

Re: Darstellung von Latexcode mit PyQt

Verfasst: Mittwoch 23. März 2016, 12:51
von Brando
Wenn ich noch einsetze:

headerLabels = ['$%s$'%a1,'$%s$'%a1,'$%s$'%a1]

dann funktioniert das Programm.

Re: Darstellung von Latexcode mit PyQt

Verfasst: Mittwoch 23. März 2016, 14:18
von BlackJack
@Brando: Das löst das Problem aber an der falschen Stelle. Lass die `latex()`-Funktion gleich die richtige Zeichenkette erstellen, dann musst Du hinterher nichts ausbessern.