wxPython 4.2.0 x Matplotlib 3.6.0
我正在开发一个 GUI,用户可以在 textctrl 中写下图形标题,然后将这个标题设置在图形上并显示图形。
我目前的问题是,我不明白为什么当标题是错误的数学文本时,try 循环无法捕获发生的 ParseException。
我的问题的简化代码是:
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx
class MyApp(wx.App):
def OnInit(self):
self.frame = MainFrame(parent=None, title="Test")
self.frame.Show()
return True
class MainFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, None, -1, title=title)
fig = plt.figure()
fig.suptitle('$$')
try:
self.canvas = FigureCanvas(self, 0, fig)
except:
self.canvas = FigureCanvas(self, 0, plt.figure())
plt.close()
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(self.canvas)
self.SetSizer(hbox)
if __name__ == "__main__":
app = MyApp()
app.MainLoop()
我收到以下错误:
Traceback (most recent call last):
...
raise exc.with_traceback(None)
pyparsing.exceptions.ParseException: Expected end of text, found '$' (at char 0), (line:1, col:1)
The above exception was the direct cause of the following exception:
...
...
ValueError:
$$
^
Expected end of text, found '$' (at char 0), (line:1, col:1)
try 循环应该捕捉到,我错了吗?
例如,我使用了 set_parse_math(False) 方法,因此不会发生错误,但是,我想了解这段代码有什么问题。
我根据以下讨论找到了解决方案:
这是我的工作代码:
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx
mpl.use('Agg') # important
class MyApp(wx.App):
def OnInit(self):
self.frame = MainFrame(parent=None, title="Test")
self.frame.Show()
return True
class MainFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, None, -1, title=title)
self.Maximize()
self.fig = plt.figure()
self.fig.add_subplot()
self.canvas = FigureCanvas(self, 0, self.fig)
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(self.canvas)
self.txtctrl = wx.TextCtrl(self)
self.txtctrl.Bind(wx.EVT_TEXT, self.on_text)
hbox.Add(self.txtctrl)
self.SetSizer(hbox)
plt.close()
def verif_fig_text(self):
self.Freeze()
self.canvas.figure = plt.figure()
ax = self.canvas.figure.add_subplot() # needed to insert x_label
self.canvas.draw() # needed to get self.canvas.renderer attr
valid_txt = True
try:
txt = ax.set_xlabel(self.txtctrl.GetValue())
# insert x_label is the only mean to verif correct math text
txt._get_layout(self.canvas.renderer)
# indeed _get_layout() doesnt work with lot of stuff - found on Valid Mathtext string at runtime StackOverflow
except:
valid_txt = False # can't do much here, by adding anything else, the exception occurs outside the try loop
plt.close()
self.Thaw()
return valid_txt
def on_text(self, event):
if self.verif_fig_text():
self.fig.suptitle(self.txtctrl.GetValue())
else:
self.fig.suptitle('Wrong math text')
self.canvas.figure = self.fig
self.canvas.draw()
plt.close()
if __name__ == "__main__":
app = MyApp()
app.MainLoop()
事实上,当有一个 wx.EVT_TEXT 时,我将一个新的(临时的)图形设置到 self.canvas。在此图中,我添加了一个子图,然后我将 xlabel 值设置为 textctrl 值,我使用 _get_layout() 方法检查文本是否是正确的数学文本,如果是,我将此文本设置为我的标题初始图形,我在 self.canvas.draw() 之前将其设置回 self.canvas.figure()