#!/usr/bin/env python3 import importlib.machinery import logging from threading import Thread import wx from CoreLibrary.Param_Model import Param_Model from plotView import PlotPanel LOGGER = logging.getLogger("my_logger") class MainFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, wx.ID_ANY, "MESS MICH") self.configure_window() self.green = wx.Bitmap("./GUI/img/green.bmp") self.red = wx.Bitmap("./GUI/img/red.bmp") self.model, self.pd = self.init_api() # MENU BAR self.menu_bar() # self.status_bar() # self.tool_bar() self.panel = wx.Panel(self, wx.ID_ANY) grid_sizer_main = wx.GridBagSizer(0, 0) self.status = self.status_init(grid_sizer_main) self.tabs = self.plot_init(grid_sizer_main) grid_group = wx.GridBagSizer(10, 0) grid_sizer_main.Add(grid_group, (0, 2), (2, 1), wx.EXPAND, 0) self.b_run, self.b_start, self.b_stop = self.init_measurement_buttons(grid_group) self.plot_buttons(grid_sizer_main) self.panel.SetSizer(grid_sizer_main) self.Layout() # end wxGlade self.timer = wx.Timer(self, wx.ID_ANY) self.Bind(wx.EVT_CLOSE, self.on_close_window) self.Bind(wx.EVT_TIMER, self.update, self.timer) self.timer.Start(100, False) self.runner_thread = None def configure_window(self): self.SetSize((1920, 1080)) self.SetTitle("My Fancy Measurements :D") def init_api(self): model = Param_Model() pd = model.get_plot_data() return model, pd def menu_bar(self): frame_menubar = wx.MenuBar() tmp_menu = wx.Menu() item = tmp_menu.Append(wx.ID_ANY, "Quit", "") self.Bind(wx.EVT_MENU, self.on_close_window, item) frame_menubar.Append(tmp_menu, "File") self.SetMenuBar(frame_menubar) def status_bar(self): frame_statusbar = self.CreateStatusBar(1) frame_statusbar.SetStatusWidths([-1]) # statusbar fields frame_statusbar_fields = ["frame_statusbar"] for count, field in enumerate(frame_statusbar_fields): frame_statusbar.SetStatusText(field, count) def tool_bar(self): frame_toolbar = wx.ToolBar(self, -1) self.SetToolBar(frame_toolbar) frame_toolbar.Realize() def status_init(self, grid_sizer_main): sizer_status = wx.GridBagSizer(vgap=5, hgap=5) grid_sizer_main.Add(sizer_status, (0, 0), (2, 1), wx.EXPAND, 0) # STATUS data = {"over1": False, "over2": True, "motor": 123} status_dict = {} for row, (key, val) in enumerate(data.items()): label = wx.StaticText(self.panel, wx.ID_ANY, key) sizer_status.Add(label, (row, 0)) if isinstance(val, bool): if val: icon = wx.StaticBitmap(self.panel, bitmap=self.green) status_dict[key] = icon sizer_status.Add(icon, (row, 1)) else: icon = wx.StaticBitmap(self.panel, bitmap=self.red) status_dict[key] = icon sizer_status.Add(icon, (row, 1)) else: label = wx.StaticText(self.panel, wx.ID_ANY, str(val)) status_dict[key] = label sizer_status.Add(label, (row, 1)) return status_dict def plot_init(self, grid_sizer_main): tabs = wx.Notebook(self.panel, wx.ID_ANY) grid_sizer_main.Add(tabs, (0, 1), (1, 1), wx.EXPAND, 0) plot = lambda ax, dat: ax.plot(dat["time"], dat["mess1"]) update = lambda im, dat: im.set_data(dat["time"], dat["mess1"]) plot_1 = PlotPanel(tabs, self.pd, plot, update) tabs.AddPage(plot_1, "Temp") plot = lambda ax, dat: ax.plot(dat["mess1"], dat["mess1"]) update = lambda im, dat: im.set_data(dat["mess1"], dat["mess1"]) plot_2 = PlotPanel(tabs, self.pd, plot, update) tabs.AddPage(plot_2, "Multi") return tabs def init_measurement_buttons(self, grid_upper): grid_sizer_measurement = wx.GridBagSizer(0, 0) grid_upper.Add(grid_sizer_measurement, (0, 0), (1, 1), wx.EXPAND, 0) b_start = wx.Button(self.panel, wx.ID_ANY, "Start") grid_sizer_measurement.Add(b_start, (0, 0), (1, 1), 0, 0) b_stop = wx.Button(self.panel, wx.ID_ANY, "Stop") grid_sizer_measurement.Add(b_stop, (1, 0), (1, 1), 0, 0) b_run = wx.Button(self.panel, wx.ID_ANY, "Run") grid_sizer_measurement.Add(b_run, (2, 0), (1, 1), 0, 0) self.Bind(wx.EVT_BUTTON, self.on_b_start, b_start) self.Bind(wx.EVT_BUTTON, self.on_b_stop, b_stop) self.Bind(wx.EVT_BUTTON, self.on_b_run, b_run) return b_run, b_start, b_stop def plot_buttons(self, grid_sizer_main): grid_sizer_ctrl_plot = wx.GridBagSizer(0, 0) grid_sizer_main.Add(grid_sizer_ctrl_plot, (1, 1), (1, 1), wx.EXPAND, 0) b_clear = wx.Button(self.panel, wx.ID_ANY, "Clear") grid_sizer_ctrl_plot.Add(b_clear, (0, 0), (1, 1), 0, 0) b_save = wx.Button(self.panel, wx.ID_ANY, "Save") grid_sizer_ctrl_plot.Add(b_save, (0, 1), (1, 1), 0, 0) self.Bind(wx.EVT_BUTTON, self.on_b_clear, b_clear) self.Bind(wx.EVT_BUTTON, self.on_b_save, b_save) def on_close_window(self, _): self.model.exit() LOGGER.info("Closing") wx.Exit() def update(self, _): # Repaint gui self.tabs.Refresh() self.model.refresh() # Unlock if script is finished if self.runner_thread is not None: if not self.runner_thread.is_alive(): self.unlock() self.runner_thread = None # update Stuff data = {"over1": True, "over2": True, "motor": 12} for key, val in data.items(): if type(val) is bool: if val: self.status[key].SetBitmap(self.green) else: self.status[key].SetBitmap(self.red) else: self.status[key].SetLabel(str(val)) def lock(self): self.b_run.Disable() self.b_start.Disable() def unlock(self): self.b_run.Enable() self.b_start.Enable() def on_b_start(self, event): # wxGlade: MyFrame. LOGGER.info("Event handler 'on_b_start'") self.model.start_measuring() event.Skip() def on_b_save(self, event): # wxGlade: MyFrame. LOGGER.info("Event handler 'on_b_save'") with wx.FileDialog( self, "Save csv file", wildcard="CSV files (*.csv)|*.csv", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, ) as fileDialog: if fileDialog.ShowModal() == wx.ID_CANCEL: return # the user changed their mind # save the current contents in the file pathname = fileDialog.GetPath() self.model.save_measuring(path=pathname) event.Skip() def on_b_run(self, event): # wxGlade: MyFrame. LOGGER.info("Event handler 'on_b_run'") with wx.FileDialog( self, "Open PY file", wildcard="PY files (*.py)|*.py", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST, ) as fileDialog: if fileDialog.ShowModal() == wx.ID_CANCEL: return # the user changed their mind # Proceed loading the file chosen by the user pathname = fileDialog.GetPath() script = importlib.machinery.SourceFileLoader("ghf", pathname).load_module() self.runner_thread = Thread(target=script.main, args=(self.model,)) self.lock() self.runner_thread.start() event.Skip() def on_b_stop(self, event): # wxGlade: MyFrame. self.model.stop_measuring() LOGGER.info("Event handler 'on_b_stop'") event.Skip() def on_b_clear(self, event): # wxGlade: MyFrame. self.model.clear() LOGGER.info("Event handler 'on_b_clear'") event.Skip() # end of class MyFrame