2010-11-03 26 views
2

J'ai modifié un court morceau de code pyqt pour produire un rendu en temps réel de l'expression d'un utilisateur. J'ai utilisé la fonction pretty-printing de sympy pour cela, mais la sortie n'apparaît pas correctement car QTextBrowser utilise une police proportionnelle plutôt qu'une police à espacement fixe.Essayer de produire une sortie monospace dans le navigateur pyqt

En tant que débutant, j'apprécierais également toute autre idée que vous avez eue sur le code.

Un grand merci et meilleurs voeux, Geddes

from __future__ import division 
import sys 
import sympy 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

class Form(QDialog): 
    def __init__(self, parent=None): 
     super(Form, self).__init__(parent) 
     self.browser = QTextBrowser() 
     self.lineedit = QLineEdit("please type an expression") 
     self.lineedit.selectAll() 
     layout = QVBoxLayout() 
     layout.addWidget(self.browser) 
     layout.addWidget(self.lineedit) 
     self.setLayout(layout) 
     self.lineedit.setFocus() 
     self.connect(self.lineedit, SIGNAL("textChanged (const QString&)"),self.updateUi) 

    def updateUi(self): 
     text = unicode(self.lineedit.text()) 
     for z in range(0,9): 
      text = text.replace('x'+str(z),'x^'+str(z)) 
      text = text.replace(')'+str(z),')^'+str(z)) 
      text = text.replace(str(z)+'x',str(z)+'*x') 
      text = text.replace(str(z)+'(',str(z)+'*(') 
     try: 
      self.browser.append(sympy.printing.pretty(sympy.sympify(text))) 
      self.browser.clear() 
      self.browser.append(sympy.printing.pretty(sympy.sympify(text))) 
     except: 
      if text=='': self.browser.clear() 

app = QApplication(sys.argv) 
form = Form() 
form.show() 
app.exec_() 

Répondre

3

Vous devriez pouvoir changer la police avec setFontFamily. En ce qui concerne votre code: Je n'ai pas encore vraiment travaillé avec PyQt (seulement quelques bidouillages comme la famille de police en qbzr ...), donc je ne peux pas vous dire si tout va bien. Mais ce qui suit est pas une bonne idée:

except: 
     if text=='': self.browser.clear() 
  1. jamais attraper toutes les exceptions avec except:. Cela prendra également BaseException s comme SystemExit, qui ne devrait pas être attrapé, sauf si vous avez une raison de le faire.Toujours attraper des exceptions spécifiques, ou si vous êtes au plus haut niveau (avant que le gestionnaire d'exceptions non gérées est exécuté) et que vous voulez enregistrer les erreurs, utilisez plutôt except Exception: qui gérera uniquement les exceptions basées sur Exception. Je pense que if not text est plus "pythonique".
+0

Bonne prise sur 'setFontFamily', j'allais éditer ma réponse à cela depuis que j'ai couru à côté de cela dans les docs après 'setCurrentFont' Je vais laisser le mien comme' setCurrentFont' pour varier les opinions, et aussi au cas où il veut définir la taille de la police ou autre chose :) – Benn

+0

@Benn: 'setCurrentFont' a du sens si vous vouloir définir le même objet de police sur plusieurs widgets. Pour les widgets simples, 'setFontFamily' est une bonne option. Les deux sont corrects;) – AndiDog

+0

Bon conseil sur l'exception - Je me demandais comment enregistrer les erreurs! Merci beaucoup pour votre aide. – Geddes

1

QTextBrowser hérite QTextEdit, de sorte que vous pouvez utiliser la méthode setCurrentFont(QFont) pour définir une police proportionnelle.

self.browser = QTextBrowser() 
self.browser.setCurrentFont(QFont("Courier New")) #Or whatever monospace font family you want... 

Quant aux commentaires généraux sur le style, il y a probablement une façon ne changez vos trucs de remplacement de texte dans updateUi() à regex, mais je ne peux pas être sûr sans voir les données d'échantillon pour savoir ce que vous essayez de faire .

En outre, vous devriez probablement factoriser

try: 
    self.browser.append(sympy.printing.pretty(sympy.sympify(text))) 
    self.browser.clear() 
    self.browser.append(sympy.printing.pretty(sympy.sympify(text))) 
except: 
    if text=='': self.browser.clear() 

Dans quelque chose comme:

self.browser.clear() 
try: 
    self.browser.append(sympy.printing.pretty(sympy.sympify(text))) 
except: 
    if text=='': self.browser.clear() 

Sauf attrapant probablement exception réelle que vous vous attendez.

EDIT Voici quelque chose pour l'équation normalisant il semble que vous essayez de faire, cela fonctionne avec les minuscules az et des nombres réels:

def updateUi(self): 
    text = unicode(self.lineedit.text()) 
    text = re.sub(r'(\d+)([\(]|[a-z])',r'\1*\2',text) #for multiplication 
    text = re.sub(r'([a-z]|[\)])(\d+)',r'\1^\2',text) #for exponentiation 

Le premier motif cherche 1 ou plusieurs chiffres \d+ suivi d'une parenthèse ouvrante ou d'une seule lettre az [\(]|[a-z]. Il utilise des parenthèses pour capturer la partie digit du motif et la partie variable du motif, et insère un * entre eux. \1*\2.

Le deuxième motif recherche une variable a-z ou une parenthèse fermante [a-z]|[\)], suivie d'un ou de plusieurs chiffres \d+. Il utilise les parenthèses de regroupement pour capturer à nouveau le chiffre et la variable, et insère un^entre eux \1^\2.

Ce n'est pas tout à fait parfait (ne gère pas xy --> x*y) mais c'est plus proche. Si vous voulez faire un système d'algèbre informatique complet, vous aurez probablement besoin de construire un analyseur dédié :)

+0

Le setCurrentFont fonctionne parfaitement! Mon remplacement de texte est de changer 3x en 3 * x ou x2 en x^2 etc. Un grand merci pour votre aide! – Geddes

+0

@Geddes - voir ma modification pour certains regex pour la normalisation de l'équation. Cela fonctionne pour les quelques entrées complexes que je lui ai lancées (le plus effrayant étant '3 (a2 + b) 2 + 2x5 + 4 (c + d) 3' ->' 3 * (a^2 + b)^2 + 2 * x^5 + 4 * (c + d)^3' – Benn

+0

Merci encore, je n'aurais jamais pensé à le faire de cette façon! – Geddes