import logging import threading import tkinter as tk import config from analyzer import ImageAnalyzer from .mainwindow import MainWindow from .boardview import BoardView from .settings import Settings log=logging.getLogger(__name__) class GUI: SETUP=PREVIEW=0 RECORDING=REAL=1 def __init__(self): self.root = tk.Tk() self.root.title("OneEye {0}.{1}.{2}".format(*config.misc.version)) self.root.option_add('*tearOff',False) # for menu self.detector=ImageAnalyzer() self._frame=None self._frameKey=0 self._ownMessages=None self._coreMessages=None self._state=GUI.RECORDING self.mainWindow = MainWindow(self) self.settings=None self.root.columnconfigure(0,weight=1) self.root.rowconfigure(0,weight=1) self.root.bind("<>", lambda e: self.mainWindow.redrawImgView()) self.root.bind("<>", lambda e: self.setUp()) self.root.bind("<>", lambda e: self.setRecording()) self.root.bind("",lambda e: Settings(self)) self.mainWindow.bind("",lambda e: self._shutDown()) self.setRecording() def __call__(self,ownMessages,coreMessages): self._ownMessages=ownMessages self._coreMessages=coreMessages self._listenerThread=threading.Thread(target=lambda: ownMessages.listen(self._handleEvent)) self._listenerThread.start() self.mainWindow.mainloop() def sendMsg(self,actionName,args=tuple(),kwargs=None): self._coreMessages.send(actionName,args,kwargs) def setUp(self): self.mainWindow.setUp() self.root.bind("",lambda e: self.sendMsg("prevFrame")) self.root.bind("",lambda e: self.sendMsg("nextFrame")) self._state=GUI.SETUP def setRecording(self): self.mainWindow.setRecording() self.root.bind("",lambda e: None) self.root.bind("",lambda e: None) if self.settings: self.settings.destroy() self.settings=None if self._coreMessages: self.sendParams() self._state=GUI.RECORDING def sendParams(self): self.sendMsg("setParams",(self.detector.params.copy(),)) def preview(self): if self.detector.analyze(self._frame): self.mainWindow.boardView.redrawState(self.detector.board) def _shutDown(self): log.info("GUI proc exiting.") self._ownMessages.send("!kill",("gui",)) self._listenerThread.join() def _handleEvent(self,e): actions={ "setFrame": self._frameHandler, "setGameState": self._stateHandler, "setParams": self._paramsHandler } (actionName,args,kwargs)=e return actions[actionName](*args,**kwargs) def _frameHandler(self,frame,type,key): if self._state!=type and self.mainWindow.imgView.isSet(): log.info("ignored setFrame event, wrong type") return self._frame=frame self._frameKey=key self.mainWindow.setFrame(frame) self.root.event_generate("<>") def _stateHandler(self,gameState,moves): if self._state==GUI.SETUP: log.info("ignored incoming gameState") return labels={(row,col):(i+1) for (i,(c,row,col)) in enumerate(moves)} self.mainWindow.boardView.redrawState(gameState,labels) def _paramsHandler(self,params): if not self.settings: log.warning("received 'setParams' message while settings is '%s'",str(self.settings)) return self.detector.setParams(params) self.settings.setParams(params) gui=GUI() """ # setup # * we can click around the ImgView * we can walk through the frames back and forth * BoardView is showing what the reading of ImgView _would_ be * core is reading and analyzing frames, pushing results to StateBag, but not showing them # recording # * ImgView is showing the current picture, is not clickable * BoardView is showing last detected position * on switch to recording (if parameters have changed): * feed analyzer new parameters and start using them * in the background reanalyze cached frames with the new parameters and merge them into StateBag """