Hello !
I have the following problem :
Main.py:
import threading
import FilePlot
while True:
word = input()
if word == "plot":
threading.Thread(target=FilePlot.runPlot).start()
FilePlot.py:
import wx
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar
import threading
from time import sleep
class PlotWindow(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((657, 548))
# Menu Bar
self.PlotMenuBar = wx.MenuBar()
wxglade_tmp_menu = wx.Menu()
self.PlotMenuBar.loadDataMenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Load data to plot", "")
self.PlotMenuBar.saveImageMenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Save plot image to file", "")
self.PlotMenuBar.Append(wxglade_tmp_menu, "File")
wxglade_tmp_menu = wx.Menu()
self.PlotMenuBar.logXmenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Log(x)", "", wx.ITEM_CHECK)
self.PlotMenuBar.logYmenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Log(y)", "", wx.ITEM_CHECK)
self.PlotMenuBar.absXmenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Abs(x)", "", wx.ITEM_CHECK)
self.PlotMenuBar.absYmenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Abs(y)", "", wx.ITEM_CHECK)
wxglade_tmp_menu.AppendSeparator()
self.PlotMenuBar.keepPlotMenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Keep last measurement on plot", "", wx.ITEM_CHECK)
self.PlotMenuBar.clearLastMenu = wxglade_tmp_menu.Append(wx.ID_ANY, "Clear last loaded plot", "")
self.PlotMenuBar.Append(wxglade_tmp_menu, "Plot")
self.SetMenuBar(self.PlotMenuBar)
# Menu Bar end
self.__set_properties()
self.__do_layout()
def __set_properties(self):
self.SetTitle("PlotWindow")
self.SetBackgroundColour(wx.Colour(104, 104, 104))
self.Bind(wx.EVT_CLOSE, self.OnExit)
def __do_layout(self):
mainSizer = wx.BoxSizer(wx.VERTICAL)
secondSizer = wx.BoxSizer(wx.VERTICAL)
labelSizer = wx.BoxSizer(wx.HORIZONTAL)
self.plot_panel = MatplotPanel(self)
secondSizer.Add(self.plot_panel, 8, wx.ALL | wx.EXPAND, 0)
self.cursorCoordLabel = wx.StaticText(self, wx.ID_ANY, "x: None, y: None")
#self.cursorCoordLabel.SetBackgroundColour(wx.Colour(221, 221, 221))
self.cursorCoordLabel.SetForegroundColour(wx.Colour(255, 255, 255))
self.cursorCoordLabel.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, 0, ""))
self.cursorCoordLabel.SetToolTip("Cursor coordinates")
labelSizer.Add(self.cursorCoordLabel, 1, 0, 0)
self.distPlotLabel = wx.StaticText(self, wx.ID_ANY, "dx: None, dy: None")
#self.distPlotLabel.SetBackgroundColour(wx.Colour(50, 153, 204))
self.distPlotLabel.SetForegroundColour(wx.Colour(255, 255, 255))
self.distPlotLabel.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, 0, ""))
self.distPlotLabel.SetToolTip("Distances for x and y. Left click on plot for the first point and Right click on plot for the second point")
labelSizer.Add(self.distPlotLabel, 1, 0, 0)
secondSizer.Add(labelSizer, 0, wx.ALL | wx.EXPAND, 0)
fileNameLabel = wx.StaticText(self, wx.ID_ANY, "File name: None")
fileNameLabel.SetBackgroundColour(wx.Colour(94, 94, 94))
fileNameLabel.SetForegroundColour(wx.Colour(254, 254, 254))
fileNameLabel.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, 0, ""))
fileNameLabel.SetToolTip("This represent the name of the file used to store measurement data")
secondSizer.Add(fileNameLabel, 0, wx.EXPAND, 0)
mainSizer.Add(secondSizer, 1, wx.EXPAND, 0)
self.SetSizer(mainSizer)
self.Layout()
self.Centre()
#animate plot
self.xi = []
self.yi = []
threading.Thread(target=self.startPlot).start()
self.plot_panel.canvas.draw()
self.redraw_timer = wx.Timer(self) # foloseste timer pentru a updata plot-ul
self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)# executa functia on_redraw_timer
self.redraw_timer.Start(100) # 100 ms
def on_redraw_timer(self,event):
self.plot_panel
self.plot_panel.plot_data.set_xdata(self.xi)
self.plot_panel.plot_data.set_ydata(self.yi)
self.plot_panel.axes.relim()
self.plot_panel.axes.autoscale_view()
self.plot_panel.canvas.draw()
def startPlot(self):
for i in range(20):
self.xi.append(i)
self.yi.append(i*i)
sleep(1)
def OnExit(self, event):
warning = wx.MessageBox("Are you sure you want to exit ?", \
'Atention', wx.YES_NO | wx.ICON_WARNING)
if warning == wx.YES:
self.redraw_timer.Stop()
self.Destroy()
class MatplotPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent,-1,size=(657, 548))
self.figure = Figure(facecolor='white',dpi = 95)
self.axes = self.figure.add_subplot(111,facecolor='white')
self.figure.subplots_adjust(left=0.08, right=0.95, top=0.96, bottom=0.1)
self.canvas = FigureCanvas(self,-1,self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, -1, wx.EXPAND| wx.ALL)
self.SetSizer(self.sizer)
self.plot_data, = self.axes.plot([],[],"-o",color="coral",markersize=4, markeredgecolor='olive')
class MyApp(wx.App):
def OnInit(self):
self.frame = PlotWindow(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
def runPlot():
app = MyApp(0)
app.MainLoop()
If I run the Main.py and I write “plot” in the console it will open the plot window and works very well, but if I close the plot window and write again “plot” in the console the following error will print in the console:
Traceback (most recent call last):
File "./Lib\plot.py", line 172, in OnInit
self.frame = PlotWindow(None, wx.ID_ANY, "")
File "./Lib\plot.py", line 33, in __init__
self.__do_layout()
File "./Lib\plot.py", line 89, in __do_layout
self.redraw_timer.Start(100) # 100 ms
wx._core.wxAssertionError: C++ assertion "wxThread::IsMain()" failed at ..\..\src\common\timerimpl.cpp(60) in wxTimerImpl::Start(): timer can only be started from the main thread
I don’t understand what is the problem. Is there a solution for this problem? Thank you!