Source code for gui.main

'''The main window and main page which links to the others'''
import tkinter.ttk as ttk
import tkinter as tk
from tkinter.font import Font

from config import GUIConfig, SimulatorConfig
from gui.sim import Simulator
from gui.conf import ConfigFrame

conf = GUIConfig()
visConf = SimulatorConfig()

[docs]class MainWindow(tk.Tk): '''The main Tkinter window of the application Encapsulates :class:`~gui.sim.Simulator` and :class:`~gui.conf.ConfigFrame` ''' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.tk_setPalette(background='white') self.wm_title(conf.Title) self.style = ttk.Style() self.style.theme_use(conf.Theme) self.geometry('%dx%d' % (conf.VisualiserWidth + conf.PanelWidth, conf.Height)) self.resizable(width=True, height=False) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.font = Font(**conf.Font) self.fontBold = Font(**conf.FontBold) self.fontHeading = Font(**conf.FontHeading) self.fontMonospace = Font(**conf.FontMonospace) self._focusSim = False # is focus on the simulator? self._cont = tk.Frame(self) self._cont.grid(row=0, column=0, sticky='nesw') self._cont.rowconfigure(0, weight=1) self._cont.columnconfigure(0, weight=1) self._frames = {} for frameClass in (MainFrame, Simulator, ConfigFrame): frame = frameClass(self._cont, self) frame.grid(row=0, column=0, sticky='nesw') self._frames[frameClass.__name__] = frame self.focus('MainFrame') self.bind_all('<KeyPress>', self._keyPress) self.after(0, self._tick) @property def _simulator(self): '''The encapsulated :class:`~gui.sim.Simulator` :getter: Get the simulator :type: :class:`~tkinter.Widget` ''' return self._frames['Simulator']
[docs] def _tick(self): '''Run :py:meth:`~gui.sim.Simulator.tick` on the :class:`~gui.sim.Simulator` Repeatedly calls itself in intervals of :py:attr:`~config.SimulatorConfig.TickRate` milliseconds while the Simulator window remains focused ''' if not self._focusSim: return self._simulator.tick() self.after(visConf.TickRate, self._tick)
[docs] def _keyPress(self, event): '''Tkinter key press callback method, sends events to the :class:`~gui.sim.Simulator` if it is currently focused ''' if not self._focusSim: return self._simulator.keyPress(event)
[docs] def focus(self, name): '''Focus on a specified contained frame. Starts the tick cycle by calling :py:meth:`_tick` if focusing on the :class:`~gui.sim.Simulator` :param name: (:class:`str`) Class name of the encapsulated frame that should be focused One of 'MainFrame', 'ConfigFrame' ''' for frame in self._frames.values(): frame.grid_remove() frame = self._frames[name] frame.grid() if getattr(frame, 'focus'): frame.focus() self._focusSim = name == 'Simulator' # resize main window if necessary width = conf.VisualiserWidth \ *(1 if not self._focusSim or frame.mode < 2 else 2) +conf.PanelWidth if self.winfo_width() != width: self.geometry('%dx%d' % (width, conf.Height)) self.after(0, self._tick)
[docs] def back(self): '''Return to the main menu by raising the :class:`~gui.main.MainFrame` to the top''' self.focus('MainFrame')
[docs]class MainFrame(tk.Frame): '''Main 'page' of the application, linking to the :class:`~gui.sim.Simulator` and :class:`~gui.conf.ConfigFrame` using :class:`~tkinter.ttk.Button` widgets. These cause the :class:`~gui.main.MainWindow` to focus on the desired frame :param root: :class:`~tkinter.Widget` parent :param main: :class:`MainWindow` ''' def __init__(self, root, main): super().__init__(root, background='white') self._main = main self.grid(padx=10, pady=30) self.columnconfigure(0, weight=1, uniform='a') self.columnconfigure(1, weight=1, uniform='a') self.rowconfigure(2, weight=1, uniform='a') self.rowconfigure(3, weight=1, uniform='a') self._title = tk.Label(self, text=conf.Title, font=main.fontHeading, anchor='center',background='white') self._title.grid(row=0, column=0, sticky='ew', columnspan=2, pady=(0, 4)) self._subtitle = tk.Label(self, text=conf.Subtitle, font=main.font, anchor='center',background='white') self._subtitle.grid(row=1, column=0, sticky='ew', columnspan=2, pady=(0, 30)) self._compare = ttk.Button(self, text=conf.CompareText, command=lambda: self.startSim(2)) self._compare.grid(row=2, column=0, sticky='nesw', padx=(0, conf.MainButtonXPad/2)) self._test = ttk.Button(self, text=conf.TestText, command=lambda: self.startSim(1)) self._test.grid(row=2, column=1, sticky='nesw', padx=(conf.MainButtonXPad/2, 0)) self._data = ttk.Button(self, text=conf.DataText, command=lambda: main.focus('Simulator')) self._data.grid(row=3, column=0, sticky='nesw', padx=(0, conf.MainButtonXPad/2), pady=(conf.MainButtonYPad, 0)) self._config = ttk.Button(self, text=conf.ConfText, command=lambda: main.focus('ConfigFrame')) self._config.grid(row=3, column=1, sticky='nesw', padx=(conf.MainButtonXPad/2, 0), pady=(conf.MainButtonYPad, 0))
[docs] def startSim(self, mode): self._main._simulator.mode = mode self._main.focus('Simulator')