diff --git a/src/gui.py b/src/gui/__init__.py copy from src/gui.py copy to src/gui/__init__.py --- a/src/gui.py +++ b/src/gui/__init__.py @@ -1,30 +1,48 @@ -import tkinter as tk +import threading +import tkinter as tk from PIL import ImageTk import PIL import config -from corners import * -from grid import * -from image_analyzer import * -from go import * +from corners import Corners +import image_analyzer +from go import Go -class Application(tk.Frame): - def __init__(self, master=None): +class MainWindow(tk.Frame): + def __init__(self,parent,master=None): + self.parent=parent self.corners=Corners() + + self.currentFrame=None self.boardGrid=None + self.gameState=None + + self.img=None tk.Frame.__init__(self, master) self.grid(column=0,row=0) - self.createWidgets() + self._createWidgets() + + def setCurrentFrame(self,frame,grid): + self.currentFrame=frame + self.boardGrid=grid - def createWidgets(self): + w=int(self.imgView['width']) + h=int(self.imgView['height']) + self.img=ImageTk.PhotoImage(frame.resize((w,h),resample=PIL.Image.BILINEAR)) + + def setGameState(self,gameState): + pass + + def setCallbacks(self,setCorners,setTresholds): + self.cornersCallback=setCorners + self.tresholdsCallback=setTresholds + + def _createWidgets(self): # a captured frame with overlay graphics self.imgView=tk.Canvas(self) self.imgView.configure(width=480,height=360) - self.imgOrig=PIL.Image.open("../images/7.jpg") - - self.img=ImageTk.PhotoImage(self.imgOrig.resize((int(self.imgView['width']),int(self.imgView['height'])),resample=PIL.Image.BILINEAR)) self.imgView.bind('<1>',lambda e: self.addCorner(e.x,e.y)) @@ -35,12 +53,9 @@ class Application(tk.Frame): self.boardView.grid(column=1,row=0) # more controls below the board - def _refreshTresholds(_): - self.refreshTresholds() - self.redrawImgView() - self.scaleTresB=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=_refreshTresholds) - self.scaleTresW=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=_refreshTresholds) - self.scaleTresB.set(30.0) + self.scaleTresB=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds) + self.scaleTresW=tk.Scale(self, orient=tk.HORIZONTAL, length=200, from_=0.0, to=100.0, command=self.refreshTresholds) + self.scaleTresB.set(30.0) # !! proper defaults self.scaleTresW.set(60.0) self.scaleTresB.grid(column=0,row=1,columnspan=2) self.scaleTresW.grid(column=0,row=2,columnspan=2) @@ -52,21 +67,23 @@ class Application(tk.Frame): def addCorner(self,x,y): self.corners.add(x,y) if self.corners.canonizeOrder(): - self.boardGrid=Grid(self.corners) - self.boardView.setBoardGrid(self.boardGrid) - + self.parent.sendMsg("setCorners",(self.corners,)) + # self.boardGrid=Grid(self.corners) + # self.boardView.setBoardGrid(self.boardGrid) + # self.redrawImgView() ## Redraws the current image and its overlay. def redrawImgView(self): - self.imgView.create_image(2,2,anchor="nw",image=self.img) + if self.currentFrame and self.img: + self.imgView.create_image(2,2,anchor="nw",image=self.img) - origWidth,origHeight=self.imgOrig.size - widthRatio=origWidth/self.img.width() - heightRatio=origHeight/self.img.height() - sizeCoef=max(widthRatio,heightRatio) - tresB=self.scaleTresB.get() - tresW=self.scaleTresW.get() + origWidth,origHeight=self.currentFrame.size + widthRatio=origWidth/self.img.width() + heightRatio=origHeight/self.img.height() + sizeCoef=max(widthRatio,heightRatio) + + # shift=EPoint(origWidth-self.img.width()*sizeCoef,origHeight-self.img.height()*sizeCoef)/2 for corner in self.corners.corners: self.markPoint(corner.x,corner.y) @@ -84,15 +101,11 @@ class Application(tk.Frame): if self.boardGrid!=None and config.gui.showBigPoints: for r in range(19): for c in range(19): - ((r1,c1),(r2,c2))=self.boardView.detector.relevantRect(self.boardGrid.intersections[r][c],*(self.boardGrid.stoneSizeAt(r,c,sizeCoef))) + ((r1,c1),(r2,c2))=image_analyzer.relevantRect(self.boardGrid.intersections[r][c],*(self.boardGrid.stoneSizeAt(r,c,sizeCoef))) self.imgView.create_rectangle(r1,c1,r2,c2,outline="#00ffff") self.imgView.grid() - shift=EPoint(origWidth-self.img.width()*sizeCoef,origHeight-self.img.height()*sizeCoef)/2 - - self.boardView.redrawState(self.imgOrig,sizeCoef,shift) - ## Marks a point at the image with a green cross. Used for corners. def markPoint(self,x,y): self.imgView.create_line(x-3,y-3,x+4,y+4,fill="#00ff00") @@ -100,15 +113,14 @@ class Application(tk.Frame): self.imgView.grid() - def refreshTresholds(self): - self.boardView.detector.tresB=self.scaleTresB.get() - self.boardView.detector.tresW=self.scaleTresW.get() + def refreshTresholds(self,_): + self.parent.sendMsg("setTresholds",tuple(),{"tresB":self.scaleTresB.get(), "tresW":self.scaleTresW.get()}) ## Handles and presents the game state as detected by the program. class BoardView(tk.Canvas): def __init__(self, master=None): - self.detector=ImageAnalyzer() + # self.detector=ImageAnalyzer() self.boardGrid=None tk.Canvas.__init__(self, master) @@ -118,19 +130,26 @@ class BoardView(tk.Canvas): self.grid() - ## Redraws and reananalyzes the board view. - def redrawState(self,img,sizeCoef,shift): - self.create_rectangle(0,0,360,360,fill="#ffcc00") - self.drawGrid() - - self.detector.analyze(img,sizeCoef,shift) - - for r,row in enumerate(self.detector.board): + def redrawState(self,gameState): + for r,row in enumerate(gameState): for c,point in enumerate(row): self.drawStone(r,c,point) self.grid() + ## Redraws and reananalyzes the board view. + # def redrawState(self,img,sizeCoef,shift): + # self.create_rectangle(0,0,360,360,fill="#ffcc00") + # self.drawGrid() + # + # self.detector.analyze(img,sizeCoef,shift) + # + # for r,row in enumerate(self.detector.board): + # for c,point in enumerate(row): + # self.drawStone(r,c,point) + # + # self.grid() + def drawGrid(self): for i in range(19): self.create_line(18,18*(i+1),360-18,18*(i+1),fill="#000000") # rows @@ -158,12 +177,53 @@ class BoardView(tk.Canvas): c+=1 self.create_oval(c*18-9,r*18-9,c*18+9,r*18+9,fill=hexCode) - def setBoardGrid(self,boardGrid): - self.boardGrid=boardGrid - self.detector.setGrid(boardGrid) + +class GUI: + def __init__(self): + self.root = tk.Tk() + self.root.title("OneEye {0}.{1}.{2}".format(*config.misc.version)) + + self.outcomingQueue=None + self.outcomingEvent=None + + self.mainWindow = MainWindow(self,master=self.root) + self.root.bind("<>", lambda e: self.mainWindow.redrawImgView()) + self.root.bind("<>", lambda e: print("fired receiveState")) + + def __call__(self,incomingQueue,incomingEvent,outcomingQueue,outcomingEvent): + self.outcomingQueue=outcomingQueue + self.outcomingEvent=outcomingEvent + + self.listenerThread=threading.Thread(target=lambda: self._listen(incomingQueue,incomingEvent)) + self.listenerThread.start() + + self.mainWindow.mainloop() -root = tk.Tk() -root.title("OneEye {0}.{1}".format(*config.misc.version)) -app = Application(master=root) -app.mainloop() + def sendMsg(self,actionName,args=tuple(),kwargs=dict()): + self.outcomingQueue.put((actionName,args,kwargs)) + self.outcomingEvent.set() + + def _listen(self,incomingQueue,incomingEvent): + while True: + incomingEvent.wait() + msg=incomingQueue.get() + if incomingQueue.empty(): + incomingEvent.clear() + print(msg) + self._handleEvent(msg) + + def _handleEvent(self,e): + actions={"setCurrentFrame": self._frameHandler} + (actionName,args,kwargs)=e + + return actions[actionName](*args,**kwargs) + + def _frameHandler(self,newFrame,grid): + self.mainWindow.setCurrentFrame(newFrame,grid) + self.root.event_generate("<>") + + def _stateHandler(self,e): + pass + +gui=GUI()