# HG changeset patch # User Laman # Date 2018-12-13 18:02:07 # Node ID 2b850618ba883a80fca62879dfc0110ec79b670f # Parent dc1ed8ff56ef3d22f3928efdd5b894a1bbf45b76 refactoring and debugging GUI diff --git a/src/core.py b/src/core.py --- a/src/core.py +++ b/src/core.py @@ -49,7 +49,7 @@ class Core: def putFrame(self,frame): self._frame=PIL.Image.fromarray(frame) k=self._cache.put(self._frame) - self._guiMessages.send("setFrame", (self._frame, gui.RECORDING, k)) + self._guiMessages.send("setFrame", (self._frame, gui.REAL, k)) self.analyze() def sendParams(self): diff --git a/src/gui/__init__.py b/src/gui/__init__.py --- a/src/gui/__init__.py +++ b/src/gui/__init__.py @@ -21,14 +21,15 @@ class GUI: 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.SETUP + self._state=GUI.RECORDING - self.mainWindow = MainWindow(self, master=self.root) + self.mainWindow = MainWindow(self) self.settings=None self.root.columnconfigure(0,weight=1) self.root.rowconfigure(0,weight=1) @@ -39,7 +40,7 @@ class GUI: self.root.bind("",lambda e: Settings(self)) self.mainWindow.bind("",lambda e: self._shutDown()) - self.setUp() + self.setRecording() def __call__(self,ownMessages,coreMessages): self._ownMessages=ownMessages @@ -57,6 +58,7 @@ class GUI: 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() @@ -65,11 +67,16 @@ class GUI: if self.settings: self.settings.destroy() self.settings=None - self.sendParams() + 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",)) @@ -89,11 +96,15 @@ class GUI: 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) diff --git a/src/gui/imgview.py b/src/gui/imgview.py --- a/src/gui/imgview.py +++ b/src/gui/imgview.py @@ -13,10 +13,10 @@ log=logging.getLogger(__name__) class ImgView(ResizableCanvas): - def __init__(self,master=None,parent=None): + def __init__(self,gui,master=None): super().__init__(master) - self._parent=parent + self._gui=gui self._corners=Corners() self._boardGrid=None @@ -31,7 +31,9 @@ class ImgView(ResizableCanvas): self.delete("all") if self._img: - img=self._img.resize((int(self._width),int(self._height))) + w,h=self._img.size + ratio=min(self._width/w, self._height/h) + img=self._img.resize((int(w*ratio),int(h*ratio))) self._tkImg=ImageTk.PhotoImage(img) # just to save the image from garbage collector self.create_image(self._width//2, self._height//2, anchor="center", image=self._tkImg) @@ -66,7 +68,8 @@ class ImgView(ResizableCanvas): log.debug(self._corners.corners) self._boardGrid=Grid(self._corners.corners) corners=[self._transformPoint(c) for c in self._corners.corners] - self._parent.detector.setCorners(corners) + self._gui.detector.setCorners(corners) + self._gui.preview() self.redraw() @@ -96,9 +99,10 @@ class ImgView(ResizableCanvas): w=int(self._width) h=int(self._height) wo,ho=self._img.size # o for original + log.debug("image: %sx%s, view: %sx%s",wo,ho,w,h) widthRatio=wo/w heightRatio=ho/h - self._imgSizeCoef=max(widthRatio,heightRatio) + imgSizeCoef=max(widthRatio,heightRatio) # shift compensates possible horizontal or vertical empty margins from unmatching aspect ratios - self._imgShift=EPoint(wo-w*self._imgSizeCoef,ho-h*self._imgSizeCoef)/2 - return EPoint(self.canvasx(point.x),self.canvasy(point.y)) * self._imgSizeCoef + self._imgShift + imgShift=EPoint(wo-w*imgSizeCoef,ho-h*imgSizeCoef)/2 + return EPoint(self.canvasx(point.x),self.canvasy(point.y)) * imgSizeCoef + imgShift diff --git a/src/gui/mainwindow.py b/src/gui/mainwindow.py --- a/src/gui/mainwindow.py +++ b/src/gui/mainwindow.py @@ -1,18 +1,17 @@ import tkinter as tk from tkinter import N,S,E,W -from .util import MsgMixin from .menu import MainMenu from .boardview import BoardView from .imgview import ImgView from .statusbar import StatusBar -class MainWindow(tk.Frame,MsgMixin): - def __init__(self,parent,master=None): +class MainWindow(tk.Frame): + def __init__(self,parent): self.parent=parent - tk.Frame.__init__(self, master) + tk.Frame.__init__(self, parent.root) self.grid(column=0,row=0,sticky=(N,S,E,W)) self._createWidgets() @@ -22,11 +21,11 @@ class MainWindow(tk.Frame,MsgMixin): def _createWidgets(self): # menu self.parent.root.option_add('*tearOff',False) - self._menu=MainMenu(self.parent,self.parent.root) + self._menu=MainMenu(self.parent) # a captured frame with overlay graphics self._imgWrapper=tk.Frame(self,width=480,height=360) - self.imgView=ImgView(self._imgWrapper,self) + self.imgView=ImgView(self.parent,self._imgWrapper) self._imgWrapper.grid(column=0,row=0,sticky=(N,S,E,W)) diff --git a/src/gui/menu.py b/src/gui/menu.py --- a/src/gui/menu.py +++ b/src/gui/menu.py @@ -1,13 +1,12 @@ import tkinter as tk -from .util import MsgMixin from .settings import Settings -class MainMenu(MsgMixin): - def __init__(self,parent,root): - self.root=root - self.parent=parent +class MainMenu: + def __init__(self,gui): + self.gui=gui + self.root=gui.root self._createWidgets() def _createWidgets(self): @@ -18,7 +17,7 @@ class MainMenu(MsgMixin): bar.add_cascade(menu=file, label='File') bar.add_cascade(menu=help_, label='Help') - file.add_command(label="Settings",command=lambda: Settings(self.parent)) + file.add_command(label="Settings",command=lambda: Settings(self.gui)) help_.add_command(label="About") diff --git a/src/gui/settings.py b/src/gui/settings.py --- a/src/gui/settings.py +++ b/src/gui/settings.py @@ -1,14 +1,12 @@ import tkinter as tk from tkinter import N,S,E,W,LEFT -from .util import MsgMixin - -class Settings(tk.Toplevel,MsgMixin): - def __init__(self,parent): - self.parent=parent +class Settings(tk.Toplevel): + def __init__(self,gui): + self._gui=gui - tk.Toplevel.__init__(self, parent.root) + tk.Toplevel.__init__(self, gui.root) self.title("Settings | OneEye") @@ -17,9 +15,9 @@ class Settings(tk.Toplevel,MsgMixin): self.content.grid(column=0,row=0,sticky=(N,S,E,W)) self.content.columnconfigure(0,weight=1) self._create() - self.parent.settings=self - self.parent.root.event_generate("<>") - self.parent.sendMsg("fetchParams") + self._gui.settings=self + self._gui.root.event_generate("<>") + self._gui.sendMsg("fetchParams") def _create(self): self.scaleTresB=tk.Scale(self.content, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds) @@ -40,14 +38,15 @@ class Settings(tk.Toplevel,MsgMixin): self.cancelButton.pack(side=LEFT) def refreshTresholds(self,_): - params=self.parent.detector.params + params=self._gui.detector.params params.tresB=self.scaleTresB.get() params.tresW=self.scaleTresW.get() + self._gui.preview() def setParams(self,params): self.scaleTresB.set(params.tresB) self.scaleTresW.set(params.tresW) def sendParams(self): - self.parent.sendParams() + self._gui.sendParams() self.destroy() diff --git a/src/gui/util.py b/src/gui/util.py deleted file mode 100644 --- a/src/gui/util.py +++ /dev/null @@ -1,3 +0,0 @@ -class MsgMixin: - def sendMsg(self,actionName,args=tuple(),kwargs=None): - self.parent.sendMsg(actionName,args,kwargs) diff --git a/src/util.py b/src/util.py --- a/src/util.py +++ b/src/util.py @@ -31,7 +31,7 @@ class MsgQueue: msg=self._queue.get() if self._queue.empty(): self._event.clear() - log.info(msg if msg[0]!="putFrame" else "('putFrame', ..., {})") + log.info("%s <- %s", self.name, msg if msg[0]!="putFrame" else "('putFrame', ..., {})") if msg[0]=="!kill": break self._handleEvent(msg) log.info("%s MsgQueue exiting.",self.name)