在pyqt浏览器中尝试产生等宽输出

2 投票
2 回答
2221 浏览
提问于 2025-04-16 06:31

我修改了一段简短的pyqt代码,用来实时显示用户的表情。我使用了sympy的漂亮打印功能来实现这个,不过输出的效果不太对,因为QTextBrowser使用的是比例字体,而不是等宽字体。

作为一个初学者,我也很欢迎你们对这段代码的其他看法。

非常感谢,祝好,

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_()

2 个回答

1

QTextBrowser是QTextEdit的一个子类,所以你可以使用setCurrentFont(QFont)这个方法来设置等宽字体。

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

关于样式的一般建议,可能有办法把你在updateUi()里做的文本替换改成正则表达式,但我不能确定,因为我需要看到一些示例数据来理解你想做什么。

另外,你可能需要重构一下

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()

成更像下面这样的:

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

不过可能要捕获你预期的具体异常。

编辑 这里有一些关于你想做的方程标准化的内容,它适用于小写字母a-z和实数:

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

第一个模式是寻找一个或多个数字\d+后面跟着一个左括号,或者一个单独的字母a-z[\(]|[a-z]。它使用括号来捕获数字部分和变量部分,并在它们之间插入一个*号。\1*\2

第二个模式是寻找一个变量a-z或一个右括号[a-z]|[\)],后面跟着一个或多个数字\d+。它同样使用分组括号来捕获数字和变量,并在它们之间插入一个^号\1^\2

这个方法并不是完美的(不能处理xy --> x*y),但更接近了。如果你想做一个完整的计算机代数系统,你可能需要构建一个专门的解析器 :)

3

你可以通过 setFontFamily 来改变字体。

关于你的代码:我其实还没怎么用过PyQt(只做过一些小改动,比如在qbzr中更改字体),所以不能确定你的代码是否完全没问题。不过,下面的做法就不太好:

    except:
        if text=='': self.browser.clear()
  1. 不要用 except: 来捕获所有异常。这会把像 BaseException 这样的异常也捕获到,比如 SystemExit,除非你有特别的理由,否则不应该捕获这些。最好是捕获具体的异常,如果你是在最上层(在未处理异常处理器执行之前)想记录错误,应该用 except Exception:,这样只会处理基于 Exception 的异常。
  2. if text=='' - 我觉得 if not text 更符合Python的风格。

撰写回答