class bootWindow: def __init__(self, parent): logging.info("Host IP: " +get_ip()) self.screen = Canvas(parent, bg=black, height=480, width=320) self.screen.place(x=0,y=0) Testline = self.screen.create_line(160, 0, 160, 480, fill=red) Testline2 = self.screen.create_line(0, 240, 320, 240, fill=red) self.img = ImageTk.PhotoImage(Image.open("images/logo.PNG")) self.imglabel = Label(self.screen, image=self.img).place(x=160, y=150, anchor="center") self.text = self.screen.create_text(160,270 , text="Loading, Please wait...", fill=white, font=(textFont, 13)) self.p = ttk.Progressbar(self.screen, orient="horizontal", length=200, mode='determinate') self.p.place(x=160, y=300, anchor="center") # LOAD ALL THE STUFF!! parent.update() self.p.step(10) parent.update() #time.sleep(1) self.p.step(10) parent.update() #time.sleep(1) self.p.step(30) parent.update() time.sleep(1) self.screen.destroy() self.p.destroy() def hide(self): pass def show(self): pass def update(self): pass def __del__(self): pass
class ImageView(BaseView): def __init__(self, manager): self.viewname = 'imageview' BaseView.__init__(self, manager) def pack_view(self, *args, **kwargs): layout = kwargs.get('layout', 2) image_object = kwargs['image_object'] image_no = kwargs.get('image_no', None) left_frame = self.display_left(flexible=True) _display_idx = self.manager.get_display_index() _display_size = (self.config.DISPLAY_SIZE[_display_idx][0], self.config.DISPLAY_SIZE[_display_idx][1]) self.manager.log('display size', _display_size) self._imgtk = ImageTk.PhotoImage(image_object.resize(_display_size)) # # self.frame = Frame(self.master) # self.frame = Frame(self.master, bg='white', width=_display_size[0], height=_display_size[1]) # self.frame.grid_propagate(0) left_frame.config(bg='white', width=_display_size[0], height=_display_size[1]) self.canvas = Canvas(left_frame, width=_display_size[0], height=_display_size[1], bg='red') # self.canvas.grid_propagate(0) self.canvas.place(relx=0.5, rely=0.5, anchor=CENTER) self.canvas.create_image(2, 2, image=self._imgtk, anchor='nw') if image_no is not None: self.canvas.create_text(self._imgtk.width() * 0.9, self._imgtk.height() * 0.9, text="Image No: " + str(image_no), fill="white") if layout == 2: bottom_frame = self.display_bottom(True) self.add_next_action_btn(lambda: self.done()) self.display()
class bootWindow: def __init__(self, parent): logging.info("Host IP: " + get_ip()) self.screen = Canvas(parent, bg=black, height=480, width=320) self.screen.place(x=0, y=0) Testline = self.screen.create_line(160, 0, 160, 480, fill=red) Testline2 = self.screen.create_line(0, 240, 320, 240, fill=red) self.img = ImageTk.PhotoImage(Image.open("images/logo.PNG")) self.imglabel = Label(self.screen, image=self.img).place(x=160, y=150, anchor="center") self.text = self.screen.create_text(160, 270, text="Loading, Please wait...", fill=white, font=(textFont, 13)) self.p = ttk.Progressbar(self.screen, orient="horizontal", length=200, mode='determinate') self.p.place(x=160, y=300, anchor="center") # LOAD ALL THE STUFF!! parent.update() self.p.step(10) parent.update() #time.sleep(1) self.p.step(10) parent.update() #time.sleep(1) self.p.step(30) parent.update() time.sleep(1) self.screen.destroy() self.p.destroy() def hide(self): pass def show(self): pass def update(self): pass def __del__(self): pass
def show_word(word): t = time() select = [0] root = Tk() root.title('CrazyEnglish') try: root.call('wm', 'iconphoto', root._w, PhotoImage(file='english.png')) except Exception: print 'Error loading icon' root.geometry( str(root.winfo_screenwidth()) + 'x' + str(root.winfo_screenheight()) + '+0+0') #root.winfo_screenheight() root.resizable(False, False) root.protocol('WM_DELETE_WINDOW', lambda: exit(root, select)) canvas = Canvas(root) #,bg='green') canvas.place(x=100, y=100, width=800, height=50) canvas.create_text(0, 0, text=word[0], anchor='nw', font=('', 14), fill='red') canvas.create_text(0, 30, text='(' + word[1] + ')', anchor='nw') entry = Entry(root, font=('', 10)) entry.place(x=100, y=200, width=800, height=30) Button(root, text='OK', command=lambda: press_btn(root, entry, word[0])).place(x=100, y=250, height=30, width=80) root.after(0, lambda: close_window(root, t)) entry.focus_force() root.mainloop() return select[0]
def display(self, frame_obj): canvas_popup = Canvas(frame_obj, background=conf.left_nav_background) # canvas_popup.config(x=0, y=0) canvas_popup.place(x=(frame_obj.sw/2), y=(frame_obj.sh/2)-100) if self.title != "": title_label = Label(canvas_popup, text=self.title, fg=conf.main_text_color) title_label.config(highlightbackground=conf.left_nav_background, background=conf.left_nav_background) title_label.grid(row=0, sticky='e,w', padx=10, pady=10) if self.content != "": content_label = Label(canvas_popup, text=self.content, fg=conf.main_text_color) content_label.config(highlightbackground=conf.left_nav_background, background=conf.left_nav_background) content_label.grid(row=1, sticky='e,w', padx=10, pady=10) if self.content != "": action_button = Button(canvas_popup, text="Ok", fg=conf.main_text_color) action_button.config(highlightbackground=conf.left_nav_background, background=conf.left_nav_background) action_button.bind("<Button-1>", self.dismiss) action_button.grid(row=2, sticky='e,w', padx=10, pady=10)
class LD_GUI(Frame): def __init__(self, parent): Frame.__init__(self, master=parent) parent.title('Liar\'s Dice') self.canvas = Canvas(self, width=550, height=500) self.canvas.pack(fill='both', expand=True) self.canvas.place(x=0, y=0) self.bid_logs = ScrolledText(self, undo=True, width=100, height=100) self.bid_logs.pack(fill='both', expand=True) self.bid_logs['font'] = ('consolas', '12') self.bid_logs.place(x=350, y=0) self.input_box = Text(self, undo=True, width=100, height=100) self.input_box.pack(fill='both', expand=True) self.input_box['font'] = ('consolas', '12') self.input_box.place(x=350, y=450) self.pack(fill='both', expand=True) self.insert_to_log() def insert_to_log(self): self.bid_logs.insert(tki.INSERT, 'HI!') self.input_box.insert(tki.INSERT, 'OK') def initGame(self): try: self.idot = Image.open("dot.png") self.dot = ImageTk.PhotoImage(self.idot) self.ihead = Image.open("head.png") self.head = ImageTk.PhotoImage(self.ihead) self.iapple = Image.open("apple.png") self.apple = ImageTk.PhotoImage(self.iapple) except IOError, e: print e sys.exit(1) self.createObjects() self.locateApple() self.bind_all("<Key>", self.onKeyPressed) self.after(DELAY, self.onTimer)
class LD_GUI(Frame): def __init__(self, parent): Frame.__init__(self, master=parent) parent.title('Liar\'s Dice') self.canvas = Canvas(self, width=550, height=500) self.canvas.pack(fill='both', expand = True) self.canvas.place(x=0, y=0) self.bid_logs = ScrolledText(self, undo=True, width=100, height = 100) self.bid_logs.pack(fill='both', expand = True) self.bid_logs['font'] = ('consolas', '12') self.bid_logs.place(x=350, y=0) self.input_box = Text(self, undo=True, width=100, height=100) self.input_box.pack(fill='both', expand = True) self.input_box['font'] = ('consolas', '12') self.input_box.place(x=350, y=450) self.pack(fill='both', expand = True) self.insert_to_log() def insert_to_log(self): self.bid_logs.insert(tki.INSERT, 'HI!') self.input_box.insert(tki.INSERT, 'OK') def initGame(self): try: self.idot = Image.open("dot.png") self.dot = ImageTk.PhotoImage(self.idot) self.ihead = Image.open("head.png") self.head = ImageTk.PhotoImage(self.ihead) self.iapple = Image.open("apple.png") self.apple = ImageTk.PhotoImage(self.iapple) except IOError, e: print e sys.exit(1) self.createObjects() self.locateApple() self.bind_all("<Key>", self.onKeyPressed) self.after(DELAY, self.onTimer)
class calculadora(object): def __init__(self, master): ######### VARIABLES ADMIN ############# # SCREEN fullscreen = 0 ultrawidescreen = 0 # Velocidad (lista de velocidades en milisegundos) self.velist = [3000,2000,1500,1000,750,500,300,200,150,100,80,60,40,20,10] # Debug self.debuguear = 1 self.porcionlen = 70 # Porcion a mostrar # Display out to Arduino (on/off) self.sendToDisplay = 0 #Arduino COMM (Display) if self.sendToDisplay>0: arduino = serial.Serial('COM3', 9600, timeout=.1) # debe coincidir con los baudios y el puerto arduino time.sleep(0.1) ####################################### ######### VARIABLES GENERALES ######### # nsp class self.nsp = NumericStringParser() # Vel sets self.velmax = len(self.velist)-1 self.vel = -1 # Contador de envio a Arduino self.resultadoAduino = '' self.contador = -1 ####################################### self.master = master if fullscreen>0: # Full screen master.overrideredirect(True) master.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight())) master.focus_set() # <-- move focus to this widget # Otra opción # master.attributes('-fullscreen', True) else: # master.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth()-16, root.winfo_screenheight()-80)) master.geometry("%dx%d+0+0" % (master.winfo_screenwidth()-16, master.winfo_screenheight()-80)) master.title("Calculadora") master.bind("<Escape>", lambda e: e.widget.quit()) # Python 2 master.bind("<Key>", self.recibeChar) self.dondestoy = 'p' # Dividendo p self.dividendostr = "" self.dividendo = StringVar() self.dividendo.set(self.dividendostr) if ultrawidescreen>0: # UltraWide Screen self.labelp = Label(master, textvariable=self.dividendo, bg="#fd0", width=18, justify="center", font=("Roboto", 192)) else: # 16:9 Screen self.labelp = Label(master, textvariable=self.dividendo, bg="#fd0", width=21, justify="center", font=("Roboto", 96)) self.line = Canvas(master, width=master.winfo_screenwidth(), height=50) # self.line.create_rectangle(0, 0, master.winfo_screenwidth(), 20, outline="#000", fill="#000") self.line.create_line(0, 0, master.winfo_screenwidth(), 0, fill="#000",width=50) # Divisor q self.divisorstr = "1" self.divisor = StringVar() self.divisor.set(self.divisorstr) if ultrawidescreen>0: # UltraWide Screen self.labelq = Label(master, textvariable=self.divisor, bg="#eee", fg="#aaa", width=18, justify="center", font=("Roboto", 192)) else: # 16:9 Screen self.labelq = Label(master, textvariable=self.divisor, bg="#eee", fg="#aaa", width=21, justify="center", font=("Roboto", 96)) # Resultado res self.resultastr = "" self.resulta = StringVar() self.resulta.set(self.resultastr) if ultrawidescreen>0: # UltraWide Screen self.labelr = Label(master, textvariable=self.resulta, bg="#eee", width=213, justify="left", font=("Roboto", 16)) else: # 16:9 Screen self.labelr = Label(master, textvariable=self.resulta, bg="#eee", width=120, justify="left", font=("Roboto", 16)) # Posiciona self.line.place(relx=0, rely=.495) self.labelp.place(relx=0, rely=.22) self.labelq.place(relx=0, rely=.545) self.labelr.place(relx=0, rely=.80) # init timer de envio a arduino # self.onUpdate() ####################################### # self.operacion(p='',q=1) # self.calculadora() ####################################### def filtrar(self,s): if '.' in s: r = { '1':'A', '2': 'B', '3': 'C', '4': 'D', '5': 'E', '6': 'F', '7': 'G', '8': 'H', '9': 'I', '0': 'J' } s = s.split('.') c = s[0][-1:] s[0] = s[0][0:-1] return s[0]+r[c]+s[1] else: return s def modcad(self,cad,c): cad = cad.decode('utf-8') p = cad[-1:] if isinstance(c, int): # if p==')': # if (len(cad)>=c+1): # cad = cad[:-(c+1)]+')' # else: if (len(cad)>=c): cad = cad[:-c] else: c = c.decode('utf-8') # if p==')': # cad = cad[:-1]+c+')' # else: cad = cad+c cad = cad.encode('utf-8') return cad def recibeChar(self,event): # Color gris en divisor cuando es 1 k = event.keycode c = event.char p = str(self.dividendostr) q = str(self.divisorstr) # self.resultastr = c+': ',str(k)+': '+str(event.state) # self.resulta.set(self.resultastr) # return numrs = ['0','1','2','3','4','5','6','7','8','9'] if (self.dondestoy=='q'): cadena = q # if cadena=='1': # cadena = '' else: cadena = p # SALIDAS if c=='c': # c # reiniciar programa self.calculadora('REINICIAR', '', p, q) return # return '','REINICIAR' elif c=='k': # k # salir del programa self.calculadora('SALIR', '', p, q) return # return '','SALIR' # AVANZAR Y STOP if c=='a': # Avanza/Acelera if self.vel<0 and self.resultadoAduino!='': self.vel=0 self.onUpdate() elif self.vel<self.velmax: self.vel = self.vel+1 return # return '','REINICIAR' elif c=='s': # Stop if self.vel>=0: self.vel = self.vel-1 return # IGUAL A elif k==10 or k==13 or c=='=':# or k==61: # [ENTER] o [=] > Salto de línea o igual: '\n' ó '\r' ó '=' # imprimir cadena RESULTADO self.calculadora('RESULTADO', cadena, p, q) return # return cadena,'RESULTADO' # ESCRITURA NORMAL elif k == 8: # BACKSPACE # recortar cadena un digito cadena = self.modcad(cadena,1) elif c in numrs: # NUMEROS 0-9 # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) # elif c==',' or c=='.': # COMA o PUNTO # c='.' # Siempre usa punto # # incrementa la cadena con c # cadena = self.modcad(cadena,str(c)) # NUMEROS ESPECIALES e y pi elif c=='e': # e => 101 # Euler's number => 'e' c = 'e' # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) elif c=='h': # h => 104 # PI => 'h' c = 'π' # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) elif c=='f': # f => 104 # PI => 'h' c = 'φ' # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) # OPERACIONES SIMPLES: * + - / elif c=='*': # * => 42 # Multiplicación => Reemplaza asterisco con signo de multiplicacion × c = '×' # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) elif c=='+': # + => 43 # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) elif c=='-': # - => 45 # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) elif c=='r': # r # SQRT => 'r' if '(' in cadena: if ')' in cadena: c='' else: c=')' else: c = '√(' # incrementa la cadena con c cadena = self.modcad(cadena,str(c)) elif c=='p': # p => 112 # Debe enviar al valor p sólo si no estamos ahí if (self.dondestoy!='p'): self.calculadora('SETP', cadena, p, q) return # return cadena, 'SETP' elif c=='q': # q => 113 # Debe enviar al valor q sólo si no estamos ahí if (self.dondestoy!='q'): self.calculadora('SETQ', cadena, p, q) return # return cadena, 'SETQ' if (self.dondestoy=='p'): p = cadena if (self.dondestoy=='q'): q = cadena # if (q==''): # q = '1' self.operacion(p,q) def pausa(self, ): while 1: c = readchar.readchar() if c!='': break def calculadora(self, estado, cadena='', p='', q=''): if (estado=='RESULTADO'): self.vel = -1 # Stop timer self.contador = -1 # Reset timer if (self.dondestoy=='p'): p = cadena if (self.dondestoy=='q'): q = cadena if p=='': p='0' if (q==''): q='1' if '(' in p and ')' not in p: p=p+')' if '(' in q and ')' not in q: q=q+')' res = self.nsp.eval(p+'/'+q) res = str(res) if (res[-2:]=='.0'): res=res[:-2] # res = p+'/'+q self.resultado(p,q, res) # self.pausa() # self.calculadora(cadena,p,q,dondestoy) if (estado=='REINICIAR'): self.vel = -1 # Stop timer self.contador = -1 # Reset timer self.operacion(p='',q=1) self.resultastr = '' self.resulta.set(self.resultastr) self.dondestoy = 'p' self.labelp.config(bg="#fd0") self.labelq.config(bg="#eee") # self.calculadora() if (estado=='SALIR'): self.vel = -1 # Stop timer self.master.quit() # return if (estado=='SETP'): q = cadena if '(' in q and ')' not in q: q=q+')' if q=='0' or q=='': self.divisorstr = str('1') self.divisor.set(self.divisorstr) self.labelq.config(fg="#aaa") self.dondestoy = 'p' self.labelp.config(bg="#fd0") self.labelq.config(bg="#eee") # self.calculadora(p,p,q,dondestoy) if (estado=='SETQ'): p = cadena if '(' in p and ')' not in p: p=p+')' if q=='1': self.divisorstr = str('') self.divisor.set(self.divisorstr) self.labelq.config(fg="#aaa") self.dondestoy = 'q' self.labelp.config(bg="#eee") self.labelq.config(bg="#fd0") # self.calculadora(q,p,q,dondestoy) def maxlen(self, p,q): maxlen = len(str(p)) if (len(str(q))>maxlen): maxlen = len(str(q)) lp = len(str(p)) lq = len(str(q)) return maxlen,lp,lq def operacion(self, p='',q=1): ml,lp,lq = self.maxlen(p,q) self.dividendostr = str(p) self.dividendo.set(self.dividendostr) self.divisorstr = str(q) self.divisor.set(self.divisorstr) # Color gris en divisor cuando es 1 if self.divisorstr != "1": self.labelq.config(fg="#000") else: self.labelq.config(fg="#aaa") def resultado(self, p,q, res): ml,lp,lq = self.maxlen(p,q) self.dividendostr = str(p) self.dividendo.set(self.dividendostr) self.divisorstr = str(q) self.divisor.set(self.divisorstr) # Color gris en divisor cuando es 1 if self.divisorstr != "1": self.labelq.config(fg="#000") else: self.labelq.config(fg="#aaa") ################################################ # Calcula p y q numericamente a floats res = self.nsp.eval('('+p+')/('+q+')') # nspep = self.nsp.eval(p) # nspeq = self.nsp.eval(q) # print("p:", nspep) # print("q:", nspeq) # if isinstance(nspep, float)==False: # nspep = nspep[1] # if isinstance(nspeq, float)==False: # nspeq = nspeq[1] # print("p:", nspep) # print("q:", nspeq) # res = self.nsp.eval(p+'/'+q) # print("p:", nspep) # print("q:", nspeq) # fp = float(nspep) # fq = float(nspeq) # fp = Decimal(p) # fq = Decimal(q) # print fp,fq ################################################ ####### AQUÍ VAN LOS CALCULOS DE PERIODO ####### # PL = self.Periodo(fq) # prec = (PL[0]+2)*(PL[1]+5) # self.resultastr = str(",".join([str(x) for x in PL])) # self.resulta.set(self.resultastr) # return # prec = (PL[0]+2)*(PL[1]+5) # prec = 1000 # getcontext().prec = prec # res = fp/fq # res = Decimal(fp)/Decimal(fq) # nrp, pl = PL[0], PL[1] # if not '.' in str(res): # precad = str(res)+'.' # res = str(res)+'.0' # cad = '0' # repite = '0' # longperiodo = '1' # else: # res = str(res) # cad = res.split('.') # precad = str(cad[0])+'.'+str(cad[0:nrp-1]) # cad = str(res.split('.')[1]) # repite = cad[nrp-1:pl+nrp-1] # longperiodo = str(PL[1]) # RESULTADO COMO CADENA nres = '' sres = str(res) # Set start envio Arduino self.resultadoAduino = self.filtrar(sres) self.contador = -1 self.vel = 0 # # IMPRIME LOS DETALLES DEL RESULTADO # salida = '' # for i in range(len(sres)): # r = sres[i] # if i/100==int(i/100): # r=r+"\n" # nres=nres+r # salida = salida+ 'LONGITUD DEL RESULTADO: '+str(len(sres)) # salida = salida+ '\nRESULTADO: '+nres # self.resultastr = salida # self.resulta.set(self.resultastr) self.onUpdate() def onUpdate(self): # Actualiza el caracter enviado, la posición y el estado actual (pausa/play) self.contador = self.contador+1 if self.contador>len(self.resultadoAduino)-2: enviar = '0' else: enviar = self.resultadoAduino[self.contador] if self.debuguear>0: salida = "Velocidad: "+str(self.velist[self.vel])+" ms" salida = salida+u"\nPosición: "+str(self.contador) salida = salida+u"\nDígito: "+enviar inicio = self.contador-self.porcionlen if inicio<0: inicio=0 salida = salida+u"\nPorción: "+self.resultadoAduino[inicio:self.contador+1].rjust(self.porcionlen, ' ').replace(' ',' ') self.resultastr = salida self.resulta.set(self.resultastr) # ENVIO A DISPLAY if self.sendToDisplay>0: arduino.write(enviar) # Envia digito actual a DISPLAY, la pausa la genera el unUpdate mismo # DEBUG EN CONSOLA if self.debuguear>0: print(current_iso8601(),self.contador,self.vel,self.velist[self.vel],enviar) # schedule timer para ayutollamarse cada segundo if self.vel>=0: self.master.after(self.velist[self.vel], self.onUpdate)
def __init__(self, master): def center(win): win.update_idletasks() width = win.winfo_width() height = win.winfo_height() x = (win.winfo_screenwidth() // 4) - (width // 2) + 40 y = (win.winfo_screenheight() // 4) - (height // 2) + 40 win.geometry('{}x{}+{}+{}'.format(width, height, x, y)) def callback(event): event.widget.focus_set() print "clicked at", event.x, event.y if self.add_tasks_flg.get() == 1: # Select number of robots # Define elements of pop up window self.top = Toplevel() self.num_robots = StringVar(self.top) self.num_robots.set("1") # default value w = OptionMenu(self.top, self.num_robots, '1', '2', '3', '4').grid(row=0, column=1) text1 = Message(self.top, text="Number of robots:", width=150).grid(row=0, column=0) self.e = Entry(self.top, width=10) self.e.grid(row=1, column=1) text2 = Message(self.top, text="Task duration:", width=150).grid(row=1, column=0) text3 = Message(self.top, text="(s)", width=60).grid(row=1, column=2) newline = Message(self.top, text=" ").grid(row=2) button = Button(self.top, text='Enter', command=lambda: self.enter_task(event)).grid( row=3, column=1) button_cancel = Button(self.top, text='Cancel', command=self.cancel_task).grid(row=3, column=2) center(self.top) master.title("Map Interface") master.minsize(width=1000, height=750) master.maxsize(width=1000, height=750) master.config(bg=BKG_COLOUR) self.master = master # Canvas for overlaying map self.map_canvas = Canvas(master, width=CANVAS_W, height=CANVAS_H, bg='gray85', highlightthickness=0) self.map_canvas.pack(side='right', padx=50) self.map_canvas.bind("<Button-1>", callback) global CANVAS_PTR CANVAS_PTR = self.map_canvas self.master.update() w = self.map_canvas.winfo_width() h = self.map_canvas.winfo_height() # Overlay a grid for i in range(0, w, SQ_SIZE): if i != 0: self.map_canvas.create_line(i, 0, i, h, dash=1) for i in range(0, h, SQ_SIZE): if i != 0: self.map_canvas.create_line(0, i, w, i, dash=1) # Load in flame icon from flame.gif self.flame_icon = PhotoImage(file="flame.gif") # Load in the drone icon from drone.gif global DRONE_ICON DRONE_ICON = PhotoImage(file="drone.gif") buttons_frame = Canvas(master, width=163, height=230, bg=BUTTONS_BKG_COLOUR, highlightthickness=1, highlightbackground='dim grey') buttons_frame.place(x=40, y=200) # Define UI buttons self.add_tasks_flg = IntVar() self.add_tasks_b = Checkbutton(master, text="Add Tasks", variable=self.add_tasks_flg, highlightbackground=BUTTONS_BKG_COLOUR, background=BUTTONS_BKG_COLOUR) self.add_tasks_b.place(x=77, y=240) self.clear_wp_b = Button(master, text='Clear Tasks', command=self.clear_wp, highlightbackground=BUTTONS_BKG_COLOUR) self.clear_wp_b.config(width=10) self.clear_wp_b.place(x=65, y=270) ''' self.gen_wp_file_b = Button(master, text='Generate Waypoints File', command=self.gen_wp_file, highlightbackground=BKG_COLOUR) self.gen_wp_file_b.config(width=20) self.gen_wp_file_b.place(x=20, y=250) ''' self.land_b = Button(master, text='Land', command=self.land, highlightbackground=BUTTONS_BKG_COLOUR) self.land_b.config(width=10) self.land_b.place(x=65, y=350) # Set up coordinate system conversion and display corners of room: file_obj = open('antenna_locations.txt', 'r') anchors = [] for line in file_obj: cur_anchors = map(float, line.split()) anchors.append(cur_anchors) file_obj.close() anchors = (np.array(anchors)).T # Find largest (abs) x and y values to use a reference for conversion ratio x_vals = anchors[0] largest_x_val = x_vals[np.argmax(abs(x_vals))] y_vals = anchors[1] largest_y_val = y_vals[np.argmax(abs(y_vals))] if largest_x_val > largest_y_val: largest_y_val = largest_x_val else: largest_x_val = largest_y_val global m_per_pixel_x m_per_pixel_x = float(largest_x_val / (CANVAS_W / 2)) global m_per_pixel_y m_per_pixel_y = float(largest_y_val / (CANVAS_H / 2)) # Place antenna (anchors) on UI anchors = anchors.T for cur_anchor in anchors: x_pixel_loc = cur_anchor[0] / m_per_pixel_x + CANVAS_W / 2 y_pixel_loc = -1 * (cur_anchor[1] / m_per_pixel_y) + CANVAS_H / 2 # Draw antenna @ location global ANTENNA_LIST antenna_id = self.map_canvas.create_oval(x_pixel_loc - 15, y_pixel_loc - 15, x_pixel_loc + 15, y_pixel_loc + 15, fill='red') self.master.update()
class PiPresents(object): def __init__(self): gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_INSTANCES|gc.DEBUG_OBJECTS|gc.DEBUG_SAVEALL) self.pipresents_issue="1.3" self.pipresents_minorissue = '1.3.1g' # position and size of window without -f command line option self.nonfull_window_width = 0.45 # proportion of width self.nonfull_window_height= 0.7 # proportion of height self.nonfull_window_x = 0 # position of top left corner self.nonfull_window_y=0 # position of top left corner self.pp_background='black' StopWatch.global_enable=False # set up the handler for SIGTERM signal.signal(signal.SIGTERM,self.handle_sigterm) # **************************************** # Initialisation # *************************************** # get command line options self.options=command_options() # get Pi Presents code directory pp_dir=sys.path[0] self.pp_dir=pp_dir if not os.path.exists(pp_dir+"/pipresents.py"): if self.options['manager'] is False: tkMessageBox.showwarning("Pi Presents","Bad Application Directory:\n{0}".format(pp_dir)) exit(103) # Initialise logging and tracing Monitor.log_path=pp_dir self.mon=Monitor() # Init in PiPresents only self.mon.init() # uncomment to enable control of logging from within a class # Monitor.enable_in_code = True # enables control of log level in the code for a class - self.mon.set_log_level() # make a shorter list to log/trace only some classes without using enable_in_code. Monitor.classes = ['PiPresents', 'pp_paths', 'HyperlinkShow','RadioButtonShow','ArtLiveShow','ArtMediaShow','MediaShow','LiveShow','MenuShow', 'PathManager','ControlsManager','ShowManager','PluginManager', 'MplayerDriver','OMXDriver','UZBLDriver', 'KbdDriver','GPIODriver','TimeOfDay','ScreenDriver','Animate','OSCDriver' ] # Monitor.classes=['PiPresents','ArtMediaShow','VideoPlayer','OMXDriver'] # get global log level from command line Monitor.log_level = int(self.options['debug']) Monitor.manager = self.options['manager'] # print self.options['manager'] self.mon.newline(3) self.mon.log (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue) # self.mon.log (self," OS and separator:" + os.name +' ' + os.sep) self.mon.log(self,"sys.path[0] - location of code: "+sys.path[0]) if os.geteuid() !=0: user=os.getenv('USER') else: user = os.getenv('SUDO_USER') self.mon.log(self,'User is: '+ user) # self.mon.log(self,"os.getenv('HOME') - user home directory (not used): " + os.getenv('HOME')) # does not work # self.mon.log(self,"os.path.expanduser('~') - user home directory: " + os.path.expanduser('~')) # does not work # optional other classes used self.root=None self.ppio=None self.tod=None self.animate=None self.gpiodriver=None self.oscdriver=None self.osc_enabled=False self.gpio_enabled=False self.tod_enabled=False # get home path from -o option self.pp_home = pp_paths.get_home(self.options['home']) if self.pp_home is None: self.end('error','Failed to find pp_home') # get profile path from -p option # pp_profile is the full path to the directory that contains # pp_showlist.json and other files for the profile self.pp_profile = pp_paths.get_profile_dir(self.pp_home, self.options['profile']) if self.pp_profile is None: self.end('error','Failed to find profile') # check profile exists if os.path.exists(self.pp_profile): self.mon.log(self,"Found Requested profile - pp_profile directory is: " + self.pp_profile) else: self.mon.err(self,"Failed to find requested profile: "+ self.pp_profile) self.end('error','Failed to find profile') self.mon.start_stats(self.options['profile']) # check 'verify' option if self.options['verify'] is True: val =Validator() if val.validate_profile(None,pp_dir,self.pp_home,self.pp_profile,self.pipresents_issue,False) is False: self.mon.err(self,"Validation Failed") self.end('error','Validation Failed') # initialise and read the showlist in the profile self.showlist=ShowList() self.showlist_file= self.pp_profile+ "/pp_showlist.json" if os.path.exists(self.showlist_file): self.showlist.open_json(self.showlist_file) else: self.mon.err(self,"showlist not found at "+self.showlist_file) self.end('error','showlist not found') # check profile and Pi Presents issues are compatible if float(self.showlist.sissue()) != float(self.pipresents_issue): self.mon.err(self,"Version of profile " + self.showlist.sissue() + " is not same as Pi Presents, must exit") self.end('error','wrong version of profile') # get the 'start' show from the showlist index = self.showlist.index_of_show('start') if index >=0: self.showlist.select(index) self.starter_show=self.showlist.selected_show() else: self.mon.err(self,"Show [start] not found in showlist") self.end('error','start show not found') if self.starter_show['start-show']=='': self.mon.warn(self,"No Start Shows in Start Show") # ******************** # SET UP THE GUI # ******************** # turn off the screenblanking and saver if self.options['noblank'] is True: call(["xset","s", "off"]) call(["xset","s", "-dpms"]) self.root=Tk() self.title='Pi Presents - '+ self.pp_profile self.icon_text= 'Pi Presents' self.root.title(self.title) self.root.iconname(self.icon_text) self.root.config(bg=self.pp_background) self.mon.log(self, 'native screen dimensions are ' + str(self.root.winfo_screenwidth()) + ' x ' + str(self.root.winfo_screenheight()) + ' pixcels') if self.options['screensize'] =='': self.screen_width = self.root.winfo_screenwidth() self.screen_height = self.root.winfo_screenheight() else: reason,message,self.screen_width,self.screen_height=self.parse_screen(self.options['screensize']) if reason =='error': self.mon.err(self,message) self.end('error',message) self.mon.log(self, 'commanded screen dimensions are ' + str(self.screen_width) + ' x ' + str(self.screen_height) + ' pixcels') # set window dimensions and decorations if self.options['fullscreen'] is False: self.window_width=int(self.root.winfo_screenwidth()*self.nonfull_window_width) self.window_height=int(self.root.winfo_screenheight()*self.nonfull_window_height) self.window_x=self.nonfull_window_x self.window_y=self.nonfull_window_y self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y)) else: self.window_width=self.screen_width self.window_height=self.screen_height self.root.attributes('-fullscreen', True) os.system('unclutter 1>&- 2>&- &') # Suppress 'someone created a subwindow' complaints from unclutter self.window_x=0 self.window_y=0 self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y)) self.root.attributes('-zoomed','1') # canvs cover the whole screen whatever the size of the window. self.canvas_height=self.screen_height self.canvas_width=self.screen_width # make sure focus is set. self.root.focus_set() # define response to main window closing. self.root.protocol ("WM_DELETE_WINDOW", self.handle_user_abort) # setup a canvas onto which will be drawn the images or text self.canvas = Canvas(self.root, bg=self.pp_background) if self.options['fullscreen'] is True: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=0) else: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=1, highlightcolor='yellow') self.canvas.place(x=0,y=0) # self.canvas.config(bg='black') self.canvas.focus_set() # **************************************** # INITIALISE THE INPUT DRIVERS # **************************************** # each driver takes a set of inputs, binds them to symboic names # and sets up a callback which returns the symbolic name when an input event occurs/ # use keyboard driver to bind keys to symbolic names and to set up callback kbd=KbdDriver() if kbd.read(pp_dir,self.pp_home,self.pp_profile) is False: self.end('error','cannot find or error in keys.cfg') kbd.bind_keys(self.root,self.handle_input_event) self.sr=ScreenDriver() # read the screen click area config file reason,message = self.sr.read(pp_dir,self.pp_home,self.pp_profile) if reason == 'error': self.end('error','cannot find screen.cfg') # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes # click areas are made on the Pi Presents canvas not the show canvases. reason,message = self.sr.make_click_areas(self.canvas,self.handle_input_event) if reason == 'error': self.mon.err(self,message) self.end('error',message) # **************************************** # INITIALISE THE APPLICATION AND START # **************************************** self.shutdown_required=False self.exitpipresents_required=False # kick off GPIO if enabled by command line option self.gpio_enabled=False if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+os.sep+ 'gpio.cfg'): # initialise the GPIO self.gpiodriver=GPIODriver() reason,message=self.gpiodriver.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,50,self.handle_input_event) if reason == 'error': self.end('error',message) else: self.gpio_enabled=True # and start polling gpio self.gpiodriver.poll() # kick off animation sequencer self.animate = Animate() self.animate.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,200,self.handle_output_event) self.animate.poll() #create a showmanager ready for time of day scheduler and osc server show_id=-1 self.show_manager=ShowManager(show_id,self.showlist,self.starter_show,self.root,self.canvas,self.pp_dir,self.pp_profile,self.pp_home) # first time through set callback to terminate Pi Presents if all shows have ended. self.show_manager.init(self.canvas,self.all_shows_ended_callback,self.handle_command,self.showlist) # Register all the shows in the showlist reason,message=self.show_manager.register_shows() if reason == 'error': self.mon.err(self,message) self.end('error',message) # Init OSCDriver, read config and start OSC server self.osc_enabled=False if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+ os.sep + 'osc.cfg'): self.oscdriver=OSCDriver() reason,message=self.oscdriver.init(self.pp_profile,self.handle_command,self.handle_input_event,self.e_osc_handle_output_event) if reason == 'error': self.end('error',message) else: self.osc_enabled=True self.root.after(1000,self.oscdriver.start_server()) # and run the start shows self.run_start_shows() # set up the time of day scheduler including catchup self.tod_enabled=False if os.path.exists(self.pp_profile + os.sep + 'schedule.json'): # kick off the time of day scheduler which may run additional shows self.tod=TimeOfDay() self.tod.init(pp_dir,self.pp_home,self.pp_profile,self.root,self.handle_command) self.tod_enabled = True # then start the time of day scheduler if self.tod_enabled is True: self.tod.poll() # start Tkinters event loop self.root.mainloop( ) def parse_screen(self,size_text): fields=size_text.split('*') if len(fields)!=2: return 'error','do not understand --fullscreen comand option',0,0 elif fields[0].isdigit() is False or fields[1].isdigit() is False: return 'error','dimensions are not positive integers in ---fullscreen',0,0 else: return 'normal','',int(fields[0]),int(fields[1]) # ********************* # RUN START SHOWS # ******************** def run_start_shows(self): self.mon.trace(self,'run start shows') # parse the start shows field and start the initial shows show_refs=self.starter_show['start-show'].split() for show_ref in show_refs: reason,message=self.show_manager.control_a_show(show_ref,'open') if reason == 'error': self.mon.err(self,message) # ********************* # User inputs # ******************** # handles one command provided as a line of text def handle_command(self,command_text): self.mon.log(self,"command received: " + command_text) if command_text.strip()=="": return if command_text[0]=='/': if self.osc_enabled is True: self.oscdriver.send_command(command_text) return fields= command_text.split() show_command=fields[0] if len(fields)>1: show_ref=fields[1] else: show_ref='' if show_command in ('open','close'): if self.shutdown_required is False: reason,message=self.show_manager.control_a_show(show_ref,show_command) else: return elif show_command == 'exitpipresents': self.exitpipresents_required=True if self.show_manager.all_shows_exited() is True: # need root.after to get out of st thread self.root.after(1,self.e_all_shows_ended_callback) return else: reason,message= self.show_manager.exit_all_shows() elif show_command == 'shutdownnow': # need root.after to get out of st thread self.root.after(1,self.e_shutdown_pressed) return else: reason='error' message = 'command not recognised: '+ show_command if reason=='error': self.mon.err(self,message) return def e_all_shows_ended_callback(self): self.all_shows_ended_callback('normal','no shows running') def e_shutdown_pressed(self): self.shutdown_pressed('now') def e_osc_handle_output_event(self,line): #jump out of server thread self.root.after(1, lambda arg=line: self.osc_handle_output_event(arg)) def osc_handle_output_event(self,line): self.mon.log(self,"output event received: "+ line) #osc sends output events as a string reason,message,delay,name,param_type,param_values=self.animate.parse_animate_fields(line) if reason == 'error': self.mon.err(self,message) self.end(reason,message) self.handle_output_event(name,param_type,param_values,0) def handle_output_event(self,symbol,param_type,param_values,req_time): if self.gpio_enabled is True: reason,message=self.gpiodriver.handle_output_event(symbol,param_type,param_values,req_time) if reason =='error': self.mon.err(self,message) self.end(reason,message) else: self.mon.warn(self,'GPIO not enabled') # all input events call this callback with a symbolic name. # handle events that affect PP overall, otherwise pass to all active shows def handle_input_event(self,symbol,source): self.mon.log(self,"event received: "+symbol + ' from '+ source) if symbol == 'pp-terminate': self.handle_user_abort() elif symbol == 'pp-shutdown': self.shutdown_pressed('delay') elif symbol == 'pp-shutdownnow': # need root.after to grt out of st thread self.root.after(1,self.e_shutdown_pressed) return elif symbol == 'pp-exitpipresents': self.exitpipresents_required=True if self.show_manager.all_shows_exited() is True: # need root.after to grt out of st thread self.root.after(1,self.e_all_shows_ended_callback) return reason,message= self.show_manager.exit_all_shows() else: # events for shows affect the show and could cause it to exit. for show in self.show_manager.shows: show_obj=show[ShowManager.SHOW_OBJ] if show_obj is not None: show_obj.handle_input_event(symbol) def shutdown_pressed(self, when): if when == 'delay': self.root.after(5000,self.on_shutdown_delay) else: self.shutdown_required=True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal','no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def on_shutdown_delay(self): # 5 second delay is up, if shutdown button still pressed then shutdown if self.gpiodriver.shutdown_pressed() is True: self.shutdown_required=True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal','no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def handle_sigterm(self,signum,frame): self.mon.log(self,'SIGTERM received - '+ str(signum)) self.terminate() def handle_user_abort(self): self.mon.log(self,'User abort received') self.terminate() def terminate(self): self.mon.log(self, "terminate received") needs_termination=False for show in self.show_manager.shows: # print show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF] if show[ShowManager.SHOW_OBJ] is not None: needs_termination=True self.mon.log(self,"Sent terminate to show "+ show[ShowManager.SHOW_REF]) # call shows terminate method # eventually the show will exit and after all shows have exited all_shows_callback will be executed. show[ShowManager.SHOW_OBJ].terminate() if needs_termination is False: self.end('killed','killed - no termination of shows required') # ****************************** # Ending Pi Presents after all the showers and players are closed # ************************** # callback from ShowManager when all shows have ended def all_shows_ended_callback(self,reason,message): self.canvas.config(bg=self.pp_background) if reason in ('killed','error') or self.shutdown_required is True or self.exitpipresents_required is True: self.end(reason,message) def end(self,reason,message): self.mon.log(self,"Pi Presents ending with reason: " + reason) if self.root is not None: self.root.destroy() self.tidy_up() # gc.collect() # print gc.garbage if reason == 'killed': self.mon.log(self, "Pi Presents Aborted, au revoir") # close logging files self.mon.finish() sys.exit(101) elif reason == 'error': self.mon.log(self, "Pi Presents closing because of error, sorry") # close logging files self.mon.finish() sys.exit(102) else: self.mon.log(self,"Pi Presents exiting normally, bye") # close logging files self.mon.finish() if self.shutdown_required is True: # print 'SHUTDOWN' call(['sudo', 'shutdown', '-h', '-t 5','now']) sys.exit(100) else: sys.exit(100) # tidy up all the peripheral bits of Pi Presents def tidy_up(self): self.mon.log(self, "Tidying Up") # turn screen blanking back on if self.options['noblank'] is True: call(["xset","s", "on"]) call(["xset","s", "+dpms"]) # tidy up animation and gpio if self.animate is not None: self.animate.terminate() if self.gpio_enabled==True: self.gpiodriver.terminate() if self.osc_enabled is True: self.oscdriver.terminate() # tidy up time of day scheduler if self.tod_enabled is True: self.tod.terminate()
# plot a point # import mathplotlib.pyplot as plt from Tkinter import Tk, Canvas, PhotoImage, Label if __name__ == '__main__': root = Tk() w = Label(root, text="Draw a Point on Canvas in Python") canvas = Canvas(root, width=250, height=250, bg='#E2E2E2') canvas.place(x=20, y=26, height=250, width=250) #img= PhotoImage(width=200, height=200) # img.putpixel(1,2) w.pack() canvas.pack() root.mainloop()
imgobj2 = query_image_canv.create_image(0, 0) # Расположение всех выше указанных компонентов на форме # (в относиельных координатах) f_1.pack() model_path_label.place(relx=0.01, rely=0.003) model_path_entry.place(relx=0.01, rely=0.053) open_model_button.place(relx=0.36, rely=0.051) sensitivity_label.place(relx=0.02, rely=0.113) sensitivity_entry.place(relx=0.01, rely=0.193) num_of_parts_label.place(relx=0.25, rely=0.113) num_of_parts_X_entry.place(relx=0.255, rely=0.193) num_of_parts_Y_entry.place(relx=0.357, rely=0.193) def_finding_button.place(relx=0.443, rely=0.5) model_image_label.place(relx=0.12, rely=0.28) model_image_canv.place(relx=0.01, rely=0.33) query_image_label.place(relx=0.65, rely=0.28) query_image_canv.place(relx=0.57, rely=0.33) query_path_label.place(relx=0.55, rely=0.003) query_path_entry.place(relx=0.55, rely=0.053) open_query_button.place(relx=0.9, rely=0.051) color_model_label.place(relx=0.55, rely=0.119) hist_dim_label.place(relx=0.55, rely=0.169) metric_label.place(relx=0.55, rely=0.219) color_model_entry.place(relx=0.85, rely=0.119) hist_dimension_entry.place(relx=0.85, rely=0.169) metric_entry.place(relx=0.85, rely=0.219) # Отображение формы root.mainloop()
class gui(Frame): """ Class for the GUI drawing """ __conf = globalConfig def __init__(self, parent): self.lbl_schlagwort = "" self.lbl_txt_wo = "" self.lbl_ekreuz = "" self.arrow_right = "" self.lbl_bem = "" self.arrow_left = "" self.lbl_version = "" self.cv_arrow_left = "" self.cv_arrow_right = "" self.lbl_estrasse = "" self.lbl_eobjekt = "" self.lbl_stichwort = "" self.einsatz = "" self.lbl_eort = "" Frame.__init__(self, parent) self.parent = parent self.initUI() self.update_clock() def initUI(self): """ Initial setup the GUI """ ### Font settings fnt = self.__conf.get_font_name() fntsize1 = self.__conf.get_font_size_1() fntsize2 = self.__conf.get_font_size_2() ### Window title self.parent.title("EDIS") self.pack(fill=BOTH, expand=1) # pylint: disable=W0201 self.var = IntVar() ### GUI sections # pylint: disable=W0201 self.canvas = Canvas(self, width =1024, height=768) self.canvas.create_rectangle(+5, +40, 1019, +180, outline='white', fill='gray80') # Einsatzgrund self.canvas.create_rectangle(+5, +190, 1019, +500, outline='gray80', fill='white') # Einsatzort self.canvas.create_rectangle(+5, +510, 1019, +760, outline='white', fill='gray80') # Bemerkung self.canvas.place(x=0, y=0) #### GUI text objects # Version self.lbl_version = Label(self, text=self.__conf.get_version(), font=(fnt, fntsize1)) self.lbl_version.place(x=420, y=0) # Strichwort self.lbl_stichwort = Label(self, text='<STICHWORT>', font=(fnt, fntsize2, "bold"), width=33, height=1, bg='gray80') self.lbl_stichwort.place(x=+10, y=+50) # Schlagwort self.lbl_schlagwort = Label(self, text='<SCHLAGWORT>', font=(fnt, fntsize2), width=34, height=1, bg='gray80') self.lbl_schlagwort.place(x=+10, y=+105) # Wo self.lbl_txt_wo = Label(self, text='Wo:', font=(fnt, fntsize2, "bold"), bg='white', anchor='nw') self.lbl_txt_wo.place(x=+10, y=+200) # Strasse self.lbl_estrasse = Label(self, text='<STRASSE>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw') self.lbl_estrasse.place(x=+90, y=+255) # Ort self.lbl_eort = Label(self, text='<ORT>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw') self.lbl_eort.place(x=+90, y=+310) # Objekt self.lbl_eobjekt = Label(self, text='<OBJEKT>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw') self.lbl_eobjekt.place(x=+90, y=+365) # Kreuzung self.lbl_ekreuz = Label(self, text='<KREUZUNG>', font=(fnt, fntsize2), bg='white', width=34, anchor='nw') self.lbl_ekreuz.place(x=+90, y=+420) # Bemerkung self.lbl_bem = Label(self, text='<BEMERKUNG>', font=(fnt, fntsize2), bg='gray80', width=37, height=4, anchor='nw', justify='left', wraplength=1000) self.lbl_bem.place(x=+10, y=+520) # Arrows imgpath = os.path.dirname(os.path.abspath(__file__))+"/../images/" self.arrow_left = ImageTk.PhotoImage(file=imgpath + "arrow_left.png") self.arrow_right = ImageTk.PhotoImage(file=imgpath + "arrow_right.png") self.cv_arrow_left = Canvas(self, width=46, height=46, bg='gray80', bd=0) self.cv_arrow_right = Canvas(self, width=46, height=46, bg='gray80', bd=0) self.cv_arrow_left.place(x=+6, y=+110) self.cv_arrow_right.place(x=970, y=+110) self.cv_arrow_left.create_image(25, 23, image=self.arrow_left) self.cv_arrow_right.create_image(23, 23, image=self.arrow_right) # pylint: disable=W0221 def update(self, efile): self.einsatz = opp.opp(efile) # Clear all fields self.lbl_stichwort['text'] = "" self.lbl_schlagwort['text'] = "" self.lbl_txt_wo['text'] = "" self.lbl_estrasse['text'] = "" self.lbl_eort['text'] = "" self.lbl_eobjekt['text'] = "" self.lbl_ekreuz['text'] = "" self.lbl_bem['text'] = "" if self.einsatz.load(): # Update with new data self.lbl_stichwort['text'] = self.einsatz.get_fld_egnd_stichw() if (self.einsatz.get_fld_egnd_stichw().find("THL") != -1): self.lbl_stichwort['bg'] = '#7777FF' elif (self.einsatz.get_fld_egnd_stichw().find("B") != -1): self.lbl_stichwort['bg'] = '#FF9999' elif (self.einsatz.get_fld_egnd_stichw().find("Unwetter") != -1): self.lbl_stichwort['bg'] = '#7777FF' else: self.lbl_stichwort['bg'] = 'gray50' self.lbl_schlagwort['text'] = self.einsatz.get_fld_egnd_schlagw() self.lbl_estrasse['text'] = self.einsatz.get_fld_eort_strasse() + ' ' + self.einsatz.get_fld_eort_hnummer() self.lbl_eort['text'] = self.einsatz.get_fld_eort_ort() self.lbl_eobjekt['text'] = self.einsatz.get_fld_eort_objekt() self.lbl_ekreuz['text'] = self.einsatz.get_fld_eort_kreuzung() self.lbl_bem['text'] = self.einsatz.get_fld_bem() # Show arrows fz_right = False fz_left = False for f in self.einsatz.get_lst_emittel(): if get_close_matches(f, [self.__conf.get_vehicle_0()], 1, 0.9): fz_right = True if get_close_matches(f, [self.__conf.get_vehicle_1()], 1, 0.9): fz_left = True if (fz_left): self.cv_arrow_left.place(x=+6, y=+110) else: self.cv_arrow_left.place(x=-100, y=-100) if (fz_right): self.cv_arrow_right.place(x=970, y=+110) else: self.cv_arrow_right.place(x=-100, y=-100) def update_clock(self): """ Update the clock timer """ try: ocr_file = self.__conf.get_ocrpath() fd = open(ocr_file, "r") except: pass else: fd.close() self.update(ocr_file) ######## Archive if not os.path.exists(self.__conf.get_archive_path()): try: log.debug("Archive does not exist! Try to create...") os.mkdir(self.__conf.get_archive_path()) log.debug("Archive created") except: log.error("Unable to operate with archive!") try: log.debug("Copy file to archive...") os.rename(ocr_file, self.__conf.get_archive_path() + '/' + strftime("%Y%m%d%H%M%S", gmtime()) + '.txt') log.debug("Copy to archive done!") except: log.error("Unable to write to archive!") ######### ######### Activate screen xsrv = xhandler.xhandle() xret = 0 xret += xsrv.test() xret += xsrv.unblank() xret += xsrv.set_timeout(self.__conf.get_scr_standby(), self.__conf.get_scr_suspend(), self.__conf.get_scr_off()) if xret != 0: log.warn("Unblank of XServer failed!") ######### self.after(1000, self.update_clock)
class PiPresents(object): def pipresents_version(self): vitems=self.pipresents_issue.split('.') if len(vitems)==2: # cope with 2 digit version numbers before 1.3.2 return 1000*int(vitems[0])+100*int(vitems[1]) else: return 1000*int(vitems[0])+100*int(vitems[1])+int(vitems[2]) def __init__(self): gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_INSTANCES|gc.DEBUG_OBJECTS|gc.DEBUG_SAVEALL) self.pipresents_issue="1.3.2" self.pipresents_minorissue = '1.3.2a' # position and size of window without -f command line option self.nonfull_window_width = 0.45 # proportion of width self.nonfull_window_height= 0.7 # proportion of height self.nonfull_window_x = 0 # position of top left corner self.nonfull_window_y=0 # position of top left corner StopWatch.global_enable=False # set up the handler for SIGTERM signal.signal(signal.SIGTERM,self.handle_sigterm) # **************************************** # Initialisation # *************************************** # get command line options self.options=command_options() # get Pi Presents code directory pp_dir=sys.path[0] self.pp_dir=pp_dir if not os.path.exists(pp_dir+"/pipresents.py"): if self.options['manager'] is False: tkMessageBox.showwarning("Pi Presents","Bad Application Directory") exit(102) # Initialise logging and tracing Monitor.log_path=pp_dir self.mon=Monitor() # Init in PiPresents only self.mon.init() # uncomment to enable control of logging from within a class # Monitor.enable_in_code = True # enables control of log level in the code for a class - self.mon.set_log_level() # make a shorter list to log/trace only some classes without using enable_in_code. Monitor.classes = ['PiPresents', 'HyperlinkShow','RadioButtonShow','ArtLiveShow','ArtMediaShow','MediaShow','LiveShow','MenuShow', 'GapShow','Show','ArtShow', 'AudioPlayer','BrowserPlayer','ImagePlayer','MenuPlayer','MessagePlayer','VideoPlayer','Player', 'MediaList','LiveList','ShowList', 'PathManager','ControlsManager','ShowManager','PluginManager', 'MplayerDriver','OMXDriver','UZBLDriver', 'KbdDriver','GPIODriver','TimeOfDay','ScreenDriver','Animate','OSCDriver', 'Network','Mailer' ] # Monitor.classes=['PiPresents','MediaShow','GapShow','Show','VideoPlayer','Player','OMXDriver'] # get global log level from command line Monitor.log_level = int(self.options['debug']) Monitor.manager = self.options['manager'] # print self.options['manager'] self.mon.newline(3) self.mon.sched (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue + ' at '+time.strftime("%Y-%m-%d %H:%M.%S")) self.mon.log (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue+ ' at '+time.strftime("%Y-%m-%d %H:%M.%S")) # self.mon.log (self," OS and separator:" + os.name +' ' + os.sep) self.mon.log(self,"sys.path[0] - location of code: "+sys.path[0]) # log versions of Raspbian and omxplayer, and GPU Memory with open("/boot/issue.txt") as file: self.mon.log(self,'\nRaspbian: '+file.read()) self.mon.log(self,'\n'+check_output(["omxplayer", "-v"])) self.mon.log(self,'\nGPU Memory: '+check_output(["vcgencmd", "get_mem", "gpu"])) if "DESKTOP_SESSION" not in os.environ: print 'Pi Presents must be run from the Desktop' self.mon.log(self,'Pi Presents must be run from the Desktop') self.mon.finish() sys.exit(102) else: self.mon.log(self,'Desktop is '+ os.environ['DESKTOP_SESSION']) # optional other classes used self.root=None self.ppio=None self.tod=None self.animate=None self.gpiodriver=None self.oscdriver=None self.osc_enabled=False self.gpio_enabled=False self.tod_enabled=False self.email_enabled=False if os.geteuid() == 0: self.mon.err(self,'Do not run Pi Presents with sudo') self.end('error','Do not run Pi Presents with sudo') user=os.getenv('USER') self.mon.log(self,'User is: '+ user) # self.mon.log(self,"os.getenv('HOME') - user home directory (not used): " + os.getenv('HOME')) # does not work # self.mon.log(self,"os.path.expanduser('~') - user home directory: " + os.path.expanduser('~')) # does not work # check network is available self.network_connected=False self.network_details=False self.interface='' self.ip='' self.unit='' # sets self.network_connected and self.network_details self.init_network() # start the mailer and send email when PP starts self.email_enabled=False if self.network_connected is True: self.init_mailer() if self.email_enabled is True and self.mailer.email_at_start is True: subject= '[Pi Presents] ' + self.unit + ': PP Started on ' + time.strftime("%Y-%m-%d %H:%M") message = time.strftime("%Y-%m-%d %H:%M") + '\nUnit: ' + self.unit + ' Profile: '+ self.options['profile']+ '\n ' + self.interface + '\n ' + self.ip self.send_email('start',subject,message) # get profile path from -p option if self.options['profile'] != '': self.pp_profile_path="/pp_profiles/"+self.options['profile'] else: self.mon.err(self,"Profile not specified in command ") self.end('error','Profile not specified with the commands -p option') # get directory containing pp_home from the command, if self.options['home'] == "": home = os.sep+ 'home' + os.sep + user + os.sep+"pp_home" else: home = self.options['home'] + os.sep+ "pp_home" self.mon.log(self,"pp_home directory is: " + home) # check if pp_home exists. # try for 10 seconds to allow usb stick to automount found=False for i in range (1, 10): self.mon.log(self,"Trying pp_home at: " + home + " (" + str(i)+')') if os.path.exists(home): found=True self.pp_home=home break time.sleep (1) if found is True: self.mon.log(self,"Found Requested Home Directory, using pp_home at: " + home) else: self.mon.err(self,"Failed to find pp_home directory at " + home) self.end('error',"Failed to find pp_home directory at " + home) # check profile exists self.pp_profile=self.pp_home+self.pp_profile_path if os.path.exists(self.pp_profile): self.mon.sched(self,"Running profile: " + self.pp_profile_path) self.mon.log(self,"Found Requested profile - pp_profile directory is: " + self.pp_profile) else: self.mon.err(self,"Failed to find requested profile: "+ self.pp_profile) self.end('error',"Failed to find requested profile: "+ self.pp_profile) self.mon.start_stats(self.options['profile']) if self.options['verify'] is True: val =Validator() if val.validate_profile(None,pp_dir,self.pp_home,self.pp_profile,self.pipresents_issue,False) is False: self.mon.err(self,"Validation Failed") self.end('error','Validation Failed') # initialise and read the showlist in the profile self.showlist=ShowList() self.showlist_file= self.pp_profile+ "/pp_showlist.json" if os.path.exists(self.showlist_file): self.showlist.open_json(self.showlist_file) else: self.mon.err(self,"showlist not found at "+self.showlist_file) self.end('error',"showlist not found at "+self.showlist_file) # check profile and Pi Presents issues are compatible if self.showlist.profile_version() != self.pipresents_version(): self.mon.err(self,"Version of showlist " + self.showlist.profile_version_string + " is not same as Pi Presents") self.end('error',"Version of showlist " + self.showlist.profile_version_string + " is not same as Pi Presents") # get the 'start' show from the showlist index = self.showlist.index_of_show('start') if index >=0: self.showlist.select(index) self.starter_show=self.showlist.selected_show() else: self.mon.err(self,"Show [start] not found in showlist") self.end('error',"Show [start] not found in showlist") # ******************** # SET UP THE GUI # ******************** # turn off the screenblanking and saver if self.options['noblank'] is True: call(["xset","s", "off"]) call(["xset","s", "-dpms"]) self.root=Tk() self.title='Pi Presents - '+ self.pp_profile self.icon_text= 'Pi Presents' self.root.title(self.title) self.root.iconname(self.icon_text) self.root.config(bg=self.starter_show['background-colour']) self.mon.log(self, 'monitor screen dimensions are ' + str(self.root.winfo_screenwidth()) + ' x ' + str(self.root.winfo_screenheight()) + ' pixels') if self.options['screensize'] =='': self.screen_width = self.root.winfo_screenwidth() self.screen_height = self.root.winfo_screenheight() else: reason,message,self.screen_width,self.screen_height=self.parse_screen(self.options['screensize']) if reason =='error': self.mon.err(self,message) self.end('error',message) self.mon.log(self, 'forced screen dimensions (--screensize) are ' + str(self.screen_width) + ' x ' + str(self.screen_height) + ' pixels') # set window dimensions and decorations if self.options['fullscreen'] is False: self.window_width=int(self.root.winfo_screenwidth()*self.nonfull_window_width) self.window_height=int(self.root.winfo_screenheight()*self.nonfull_window_height) self.window_x=self.nonfull_window_x self.window_y=self.nonfull_window_y self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y)) else: self.window_width=self.screen_width self.window_height=self.screen_height self.root.attributes('-fullscreen', True) os.system('unclutter &') self.window_x=0 self.window_y=0 self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y)) self.root.attributes('-zoomed','1') # canvas cover the whole screen whatever the size of the window. self.canvas_height=self.screen_height self.canvas_width=self.screen_width # make sure focus is set. self.root.focus_set() # define response to main window closing. self.root.protocol ("WM_DELETE_WINDOW", self.handle_user_abort) # setup a canvas onto which will be drawn the images or text self.canvas = Canvas(self.root, bg=self.starter_show['background-colour']) if self.options['fullscreen'] is True: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=0) else: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=1, highlightcolor='yellow') self.canvas.place(x=0,y=0) # self.canvas.config(bg='black') self.canvas.focus_set() # **************************************** # INITIALISE THE INPUT DRIVERS # **************************************** # each driver takes a set of inputs, binds them to symboic names # and sets up a callback which returns the symbolic name when an input event occurs/ # use keyboard driver to bind keys to symbolic names and to set up callback kbd=KbdDriver() if kbd.read(pp_dir,self.pp_home,self.pp_profile) is False: self.end('error','cannot find, or error in keys.cfg') kbd.bind_keys(self.root,self.handle_input_event) self.sr=ScreenDriver() # read the screen click area config file reason,message = self.sr.read(pp_dir,self.pp_home,self.pp_profile) if reason == 'error': self.end('error','cannot find, or error in screen.cfg') # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes # click areas are made on the Pi Presents canvas not the show canvases. reason,message = self.sr.make_click_areas(self.canvas,self.handle_input_event) if reason == 'error': self.mon.err(self,message) self.end('error',message) # **************************************** # INITIALISE THE APPLICATION AND START # **************************************** self.shutdown_required=False self.terminate_required=False self.exitpipresents_required=False # delete omxplayer dbus files # if os.path.exists("/tmp/omxplayerdbus.{}".format(user)): # os.remove("/tmp/omxplayerdbus.{}".format(user)) # if os.path.exists("/tmp/omxplayerdbus.{}.pid".format(user)): # os.remove("/tmp/omxplayerdbus.{}.pid".format(user)) # kick off GPIO if enabled by command line option self.gpio_enabled=False if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+os.sep+ 'gpio.cfg'): # initialise the GPIO self.gpiodriver=GPIODriver() reason,message=self.gpiodriver.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,50,self.handle_input_event) if reason == 'error': self.end('error',message) else: self.gpio_enabled=True # and start polling gpio self.gpiodriver.poll() # kick off animation sequencer self.animate = Animate() self.animate.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,200,self.handle_output_event) self.animate.poll() #create a showmanager ready for time of day scheduler and osc server show_id=-1 self.show_manager=ShowManager(show_id,self.showlist,self.starter_show,self.root,self.canvas,self.pp_dir,self.pp_profile,self.pp_home) # first time through set callback to terminate Pi Presents if all shows have ended. self.show_manager.init(self.canvas,self.all_shows_ended_callback,self.handle_command,self.showlist) # Register all the shows in the showlist reason,message=self.show_manager.register_shows() if reason == 'error': self.mon.err(self,message) self.end('error',message) # Init OSCDriver, read config and start OSC server self.osc_enabled=False if self.network_connected is True: if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+ os.sep + 'osc.cfg'): self.oscdriver=OSCDriver() reason,message=self.oscdriver.init(self.pp_profile,self.handle_command,self.handle_input_event,self.e_osc_handle_output_event) if reason == 'error': self.mon.err(self,message) self.end('error',message) else: self.osc_enabled=True self.root.after(1000,self.oscdriver.start_server()) # enable ToD scheduler if schedule exists if os.path.exists(self.pp_profile + os.sep + 'schedule.json'): self.tod_enabled = True else: self.tod_enabled=False # warn if the network not available when ToD required if self.tod_enabled is True and self.network_connected is False: self.mon.warn(self,'Network not connected so Time of Day scheduler may be using the internal clock') # warn about start shows and scheduler if self.starter_show['start-show']=='' and self.tod_enabled is False: self.mon.sched(self,"No Start Shows in Start Show and no shows scheduled") self.mon.warn(self,"No Start Shows in Start Show and no shows scheduled") if self.starter_show['start-show'] !='' and self.tod_enabled is True: self.mon.sched(self,"Start Shows in Start Show and shows scheduled - conflict?") self.mon.warn(self,"Start Shows in Start Show and shows scheduled - conflict?") # run the start shows self.run_start_shows() # kick off the time of day scheduler which may run additional shows if self.tod_enabled is True: self.tod=TimeOfDay() self.tod.init(pp_dir,self.pp_home,self.pp_profile,self.root,self.handle_command) self.tod.poll() # start Tkinters event loop self.root.mainloop( ) def parse_screen(self,size_text): fields=size_text.split('*') if len(fields)!=2: return 'error','do not understand --screensize comand option',0,0 elif fields[0].isdigit() is False or fields[1].isdigit() is False: return 'error','dimensions are not positive integers in --screensize',0,0 else: return 'normal','',int(fields[0]),int(fields[1]) # ********************* # RUN START SHOWS # ******************** def run_start_shows(self): self.mon.trace(self,'run start shows') # parse the start shows field and start the initial shows show_refs=self.starter_show['start-show'].split() for show_ref in show_refs: reason,message=self.show_manager.control_a_show(show_ref,'open') if reason == 'error': self.mon.err(self,message) # ********************* # User inputs # ******************** # handles one command provided as a line of text def handle_command(self,command_text,source='',show=''): # print 'PIPRESENTS ',command_text,source,'from',show self.mon.log(self,"command received: " + command_text) if command_text.strip()=="": return if command_text[0]=='/': if self.osc_enabled is True: self.oscdriver.send_command(command_text) return fields= command_text.split() show_command=fields[0] if len(fields)>1: show_ref=fields[1] else: show_ref='' if show_command in ('open','close'): self.mon.sched(self, command_text + ' received from show:'+show) if self.shutdown_required is False and self.terminate_required is False: reason,message=self.show_manager.control_a_show(show_ref,show_command) else: return elif show_command =='monitor': self.handle_monitor_command(show_ref) return elif show_command == 'event': self.handle_input_event(show_ref,'Show Control') return elif show_command == 'exitpipresents': self.exitpipresents_required=True if self.show_manager.all_shows_exited() is True: # need root.after to get out of st thread self.root.after(1,self.e_all_shows_ended_callback) return else: reason,message= self.show_manager.exit_all_shows() elif show_command == 'shutdownnow': # need root.after to get out of st thread self.root.after(1,self.e_shutdown_pressed) return else: reason='error' message = 'command not recognised: '+ show_command if reason=='error': self.mon.err(self,message) return def handle_monitor_command(self,command): if command == 'on': os.system('vcgencmd display_power 1 >/dev/null') elif command == 'off': os.system('vcgencmd display_power 0 >/dev/null') def e_all_shows_ended_callback(self): self.all_shows_ended_callback('normal','no shows running') def e_shutdown_pressed(self): self.shutdown_pressed('now') def e_osc_handle_output_event(self,line): #jump out of server thread self.root.after(1, lambda arg=line: self.osc_handle_output_event(arg)) def osc_handle_output_event(self,line): self.mon.log(self,"output event received: "+ line) #osc sends output events as a string reason,message,delay,name,param_type,param_values=self.animate.parse_animate_fields(line) if reason == 'error': self.mon.err(self,message) self.end(reason,message) self.handle_output_event(name,param_type,param_values,0) def handle_output_event(self,symbol,param_type,param_values,req_time): if self.gpio_enabled is True: reason,message=self.gpiodriver.handle_output_event(symbol,param_type,param_values,req_time) if reason =='error': self.mon.err(self,message) self.end(reason,message) else: self.mon.warn(self,'GPIO not enabled') # all input events call this callback with a symbolic name. # handle events that affect PP overall, otherwise pass to all active shows def handle_input_event(self,symbol,source): self.mon.log(self,"event received: "+symbol + ' from '+ source) if symbol == 'pp-terminate': self.handle_user_abort() elif symbol == 'pp-shutdown': self.shutdown_pressed('delay') elif symbol == 'pp-shutdownnow': # need root.after to grt out of st thread self.root.after(1,self.e_shutdown_pressed) return elif symbol == 'pp-exitpipresents': self.exitpipresents_required=True if self.show_manager.all_shows_exited() is True: # need root.after to grt out of st thread self.root.after(1,self.e_all_shows_ended_callback) return reason,message= self.show_manager.exit_all_shows() else: # events for shows affect the show and could cause it to exit. for show in self.show_manager.shows: show_obj=show[ShowManager.SHOW_OBJ] if show_obj is not None: show_obj.handle_input_event(symbol) def shutdown_pressed(self, when): if when == 'delay': self.root.after(5000,self.on_shutdown_delay) else: self.shutdown_required=True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal','no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def on_shutdown_delay(self): # 5 second delay is up, if shutdown button still pressed then shutdown if self.gpiodriver.shutdown_pressed() is True: self.shutdown_required=True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal','no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def handle_sigterm(self,signum,frame): self.mon.log(self,'SIGTERM received - '+ str(signum)) self.terminate() def handle_user_abort(self): self.mon.log(self,'User abort received') self.terminate() def terminate(self): self.mon.log(self, "terminate received") self.terminate_required=True needs_termination=False for show in self.show_manager.shows: # print show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF] if show[ShowManager.SHOW_OBJ] is not None: needs_termination=True self.mon.log(self,"Sent terminate to show "+ show[ShowManager.SHOW_REF]) # call shows terminate method # eventually the show will exit and after all shows have exited all_shows_callback will be executed. show[ShowManager.SHOW_OBJ].terminate() if needs_termination is False: self.end('killed','killed - no termination of shows required') # ****************************** # Ending Pi Presents after all the showers and players are closed # ************************** # callback from ShowManager when all shows have ended def all_shows_ended_callback(self,reason,message): self.canvas.config(bg=self.starter_show['background-colour']) if reason in ('killed','error') or self.shutdown_required is True or self.exitpipresents_required is True: self.end(reason,message) def end(self,reason,message): self.mon.log(self,"Pi Presents ending with reason: " + reason) if self.root is not None: self.root.destroy() self.tidy_up() # gc.collect() # print gc.garbage if reason == 'killed': if self.email_enabled is True and self.mailer.email_on_terminate is True: subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Terminated' message = time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip self.send_email(reason,subject,message) self.mon.sched(self, "Pi Presents Terminated, au revoir\n") self.mon.log(self, "Pi Presents Terminated, au revoir") # close logging files self.mon.finish() sys.exit(101) elif reason == 'error': if self.email_enabled is True and self.mailer.email_on_error is True: subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Error' message_text = 'Error message: '+ message + '\n'+ time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip self.send_email(reason,subject,message_text) self.mon.sched(self, "Pi Presents closing because of error, sorry\n") self.mon.log(self, "Pi Presents closing because of error, sorry") # close logging files self.mon.finish() sys.exit(102) else: self.mon.sched(self,"Pi Presents exiting normally, bye\n") self.mon.log(self,"Pi Presents exiting normally, bye") # close logging files self.mon.finish() if self.shutdown_required is True: # print 'SHUTDOWN' call (['sudo','shutdown','now','SHUTTING DOWN']) sys.exit(100) def init_network(self): timeout=int(self.options['nonetwork']) if timeout== 0: self.network_connected=False self.unit='' self.ip='' self.interface='' return self.network=Network() self.network_connected=False # try to connect to network self.mon.log (self, 'Waiting up to '+ str(timeout) + ' seconds for network') success=self.network.wait_for_network(timeout) if success is False: self.mon.warn(self,'Failed to connect to network after ' + str(timeout) + ' seconds') # tkMessageBox.showwarning("Pi Presents","Failed to connect to network so using fake-hwclock") return self.network_connected=True self.mon.sched (self, 'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S")) self.mon.log (self, 'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S")) # Get web configuration self.network_details=False network_options_file_path=self.pp_dir+os.sep+'pp_config'+os.sep+'pp_web.cfg' if not os.path.exists(network_options_file_path): self.mon.warn(self,"pp_web.cfg not found at "+network_options_file_path) return self.mon.log(self, 'Found pp_web.cfg in ' + network_options_file_path) self.network.read_config(network_options_file_path) self.unit=self.network.unit # get interface and IP details of preferred interface self.interface,self.ip = self.network.get_preferred_ip() if self.interface == '': self.network_connected=False return self.network_details=True self.mon.log (self, 'Network details ' + self.unit + ' ' + self.interface + ' ' +self.ip) def init_mailer(self): self.email_enabled=False email_file_path = self.pp_dir+os.sep+'pp_config'+os.sep+'pp_email.cfg' if not os.path.exists(email_file_path): self.mon.log(self,'pp_email.cfg not found at ' + email_file_path) return self.mon.log(self,'Found pp_email.cfg at ' + email_file_path) self.mailer=Mailer() self.mailer.read_config(email_file_path) # all Ok so can enable email if config file allows it. if self.mailer.email_allowed is True: self.email_enabled=True self.mon.log (self,'Email Enabled') def send_email(self,reason,subject,message): if self.try_connect() is False: return False else: success,error = self.mailer.send(subject,message) if success is False: self.mon.log(self, 'Failed to send email: ' + str(error)) success,error=self.mailer.disconnect() if success is False: self.mon.log(self,'Failed disconnect after send:' + str(error)) return False else: self.mon.log(self,'Sent email for ' + reason) success,error=self.mailer.disconnect() if success is False: self.mon.log(self,'Failed disconnect from email server ' + str(error)) return True def try_connect(self): tries=1 while True: success, error = self.mailer.connect() if success is True: return True else: self.mon.log(self,'Failed to connect to email SMTP server ' + str(tries) + '\n ' +str(error)) tries +=1 if tries >5: self.mon.log(self,'Failed to connect to email SMTP server after ' + str(tries)) return False # tidy up all the peripheral bits of Pi Presents def tidy_up(self): self.handle_monitor_command('on') self.mon.log(self, "Tidying Up") # turn screen blanking back on if self.options['noblank'] is True: call(["xset","s", "on"]) call(["xset","s", "+dpms"]) # tidy up animation and gpio if self.animate is not None: self.animate.terminate() if self.gpio_enabled==True: self.gpiodriver.terminate() if self.osc_enabled is True: self.oscdriver.terminate() # tidy up time of day scheduler if self.tod_enabled is True: self.tod.terminate()
class PiPresents(object): def __init__(self): gc.set_debug(gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS | gc.DEBUG_SAVEALL) self.pipresents_issue = "1.3" self.pipresents_minorissue = '1.3.1g' # position and size of window without -f command line option self.nonfull_window_width = 0.45 # proportion of width self.nonfull_window_height = 0.7 # proportion of height self.nonfull_window_x = 0 # position of top left corner self.nonfull_window_y = 0 # position of top left corner self.pp_background = 'black' StopWatch.global_enable = False # set up the handler for SIGTERM signal.signal(signal.SIGTERM, self.handle_sigterm) # **************************************** # Initialisation # *************************************** # get command line options self.options = command_options() # get Pi Presents code directory pp_dir = sys.path[0] self.pp_dir = pp_dir if not os.path.exists(pp_dir + "/pipresents.py"): if self.options['manager'] is False: tkMessageBox.showwarning( "Pi Presents", "Bad Application Directory:\n{0}".format(pp_dir)) exit(103) # Initialise logging and tracing Monitor.log_path = pp_dir self.mon = Monitor() # Init in PiPresents only self.mon.init() # uncomment to enable control of logging from within a class # Monitor.enable_in_code = True # enables control of log level in the code for a class - self.mon.set_log_level() # make a shorter list to log/trace only some classes without using enable_in_code. Monitor.classes = [ 'PiPresents', 'pp_paths', 'HyperlinkShow', 'RadioButtonShow', 'ArtLiveShow', 'ArtMediaShow', 'MediaShow', 'LiveShow', 'MenuShow', 'PathManager', 'ControlsManager', 'ShowManager', 'PluginManager', 'MplayerDriver', 'OMXDriver', 'UZBLDriver', 'KbdDriver', 'GPIODriver', 'TimeOfDay', 'ScreenDriver', 'Animate', 'OSCDriver' ] # Monitor.classes=['PiPresents','ArtMediaShow','VideoPlayer','OMXDriver'] # get global log level from command line Monitor.log_level = int(self.options['debug']) Monitor.manager = self.options['manager'] # print self.options['manager'] self.mon.newline(3) self.mon.log( self, "Pi Presents is starting, Version:" + self.pipresents_minorissue) # self.mon.log (self," OS and separator:" + os.name +' ' + os.sep) self.mon.log(self, "sys.path[0] - location of code: " + sys.path[0]) if os.geteuid() != 0: user = os.getenv('USER') else: user = os.getenv('SUDO_USER') self.mon.log(self, 'User is: ' + user) # self.mon.log(self,"os.getenv('HOME') - user home directory (not used): " + os.getenv('HOME')) # does not work # self.mon.log(self,"os.path.expanduser('~') - user home directory: " + os.path.expanduser('~')) # does not work # optional other classes used self.root = None self.ppio = None self.tod = None self.animate = None self.gpiodriver = None self.oscdriver = None self.osc_enabled = False self.gpio_enabled = False self.tod_enabled = False # get home path from -o option self.pp_home = pp_paths.get_home(self.options['home']) if self.pp_home is None: self.end('error', 'Failed to find pp_home') # get profile path from -p option # pp_profile is the full path to the directory that contains # pp_showlist.json and other files for the profile self.pp_profile = pp_paths.get_profile_dir(self.pp_home, self.options['profile']) if self.pp_profile is None: self.end('error', 'Failed to find profile') # check profile exists if os.path.exists(self.pp_profile): self.mon.log( self, "Found Requested profile - pp_profile directory is: " + self.pp_profile) else: self.mon.err( self, "Failed to find requested profile: " + self.pp_profile) self.end('error', 'Failed to find profile') self.mon.start_stats(self.options['profile']) # check 'verify' option if self.options['verify'] is True: val = Validator() if val.validate_profile(None, pp_dir, self.pp_home, self.pp_profile, self.pipresents_issue, False) is False: self.mon.err(self, "Validation Failed") self.end('error', 'Validation Failed') # initialise and read the showlist in the profile self.showlist = ShowList() self.showlist_file = self.pp_profile + "/pp_showlist.json" if os.path.exists(self.showlist_file): self.showlist.open_json(self.showlist_file) else: self.mon.err(self, "showlist not found at " + self.showlist_file) self.end('error', 'showlist not found') # check profile and Pi Presents issues are compatible if float(self.showlist.sissue()) != float(self.pipresents_issue): self.mon.err( self, "Version of profile " + self.showlist.sissue() + " is not same as Pi Presents, must exit") self.end('error', 'wrong version of profile') # get the 'start' show from the showlist index = self.showlist.index_of_show('start') if index >= 0: self.showlist.select(index) self.starter_show = self.showlist.selected_show() else: self.mon.err(self, "Show [start] not found in showlist") self.end('error', 'start show not found') if self.starter_show['start-show'] == '': self.mon.warn(self, "No Start Shows in Start Show") # ******************** # SET UP THE GUI # ******************** # turn off the screenblanking and saver if self.options['noblank'] is True: call(["xset", "s", "off"]) call(["xset", "s", "-dpms"]) self.root = Tk() self.title = 'Pi Presents - ' + self.pp_profile self.icon_text = 'Pi Presents' self.root.title(self.title) self.root.iconname(self.icon_text) self.root.config(bg=self.pp_background) self.mon.log( self, 'native screen dimensions are ' + str(self.root.winfo_screenwidth()) + ' x ' + str(self.root.winfo_screenheight()) + ' pixcels') if self.options['screensize'] == '': self.screen_width = self.root.winfo_screenwidth() self.screen_height = self.root.winfo_screenheight() else: reason, message, self.screen_width, self.screen_height = self.parse_screen( self.options['screensize']) if reason == 'error': self.mon.err(self, message) self.end('error', message) self.mon.log( self, 'commanded screen dimensions are ' + str(self.screen_width) + ' x ' + str(self.screen_height) + ' pixcels') # set window dimensions and decorations if self.options['fullscreen'] is False: self.window_width = int(self.root.winfo_screenwidth() * self.nonfull_window_width) self.window_height = int(self.root.winfo_screenheight() * self.nonfull_window_height) self.window_x = self.nonfull_window_x self.window_y = self.nonfull_window_y self.root.geometry("%dx%d%+d%+d" % (self.window_width, self.window_height, self.window_x, self.window_y)) else: self.window_width = self.screen_width self.window_height = self.screen_height self.root.attributes('-fullscreen', True) os.system( 'unclutter 1>&- 2>&- &' ) # Suppress 'someone created a subwindow' complaints from unclutter self.window_x = 0 self.window_y = 0 self.root.geometry("%dx%d%+d%+d" % (self.window_width, self.window_height, self.window_x, self.window_y)) self.root.attributes('-zoomed', '1') # canvs cover the whole screen whatever the size of the window. self.canvas_height = self.screen_height self.canvas_width = self.screen_width # make sure focus is set. self.root.focus_set() # define response to main window closing. self.root.protocol("WM_DELETE_WINDOW", self.handle_user_abort) # setup a canvas onto which will be drawn the images or text self.canvas = Canvas(self.root, bg=self.pp_background) if self.options['fullscreen'] is True: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=0) else: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=1, highlightcolor='yellow') self.canvas.place(x=0, y=0) # self.canvas.config(bg='black') self.canvas.focus_set() # **************************************** # INITIALISE THE INPUT DRIVERS # **************************************** # each driver takes a set of inputs, binds them to symboic names # and sets up a callback which returns the symbolic name when an input event occurs/ # use keyboard driver to bind keys to symbolic names and to set up callback kbd = KbdDriver() if kbd.read(pp_dir, self.pp_home, self.pp_profile) is False: self.end('error', 'cannot find or error in keys.cfg') kbd.bind_keys(self.root, self.handle_input_event) self.sr = ScreenDriver() # read the screen click area config file reason, message = self.sr.read(pp_dir, self.pp_home, self.pp_profile) if reason == 'error': self.end('error', 'cannot find screen.cfg') # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes # click areas are made on the Pi Presents canvas not the show canvases. reason, message = self.sr.make_click_areas(self.canvas, self.handle_input_event) if reason == 'error': self.mon.err(self, message) self.end('error', message) # **************************************** # INITIALISE THE APPLICATION AND START # **************************************** self.shutdown_required = False self.exitpipresents_required = False # kick off GPIO if enabled by command line option self.gpio_enabled = False if os.path.exists(self.pp_profile + os.sep + 'pp_io_config' + os.sep + 'gpio.cfg'): # initialise the GPIO self.gpiodriver = GPIODriver() reason, message = self.gpiodriver.init(pp_dir, self.pp_home, self.pp_profile, self.canvas, 50, self.handle_input_event) if reason == 'error': self.end('error', message) else: self.gpio_enabled = True # and start polling gpio self.gpiodriver.poll() # kick off animation sequencer self.animate = Animate() self.animate.init(pp_dir, self.pp_home, self.pp_profile, self.canvas, 200, self.handle_output_event) self.animate.poll() #create a showmanager ready for time of day scheduler and osc server show_id = -1 self.show_manager = ShowManager(show_id, self.showlist, self.starter_show, self.root, self.canvas, self.pp_dir, self.pp_profile, self.pp_home) # first time through set callback to terminate Pi Presents if all shows have ended. self.show_manager.init(self.canvas, self.all_shows_ended_callback, self.handle_command, self.showlist) # Register all the shows in the showlist reason, message = self.show_manager.register_shows() if reason == 'error': self.mon.err(self, message) self.end('error', message) # Init OSCDriver, read config and start OSC server self.osc_enabled = False if os.path.exists(self.pp_profile + os.sep + 'pp_io_config' + os.sep + 'osc.cfg'): self.oscdriver = OSCDriver() reason, message = self.oscdriver.init( self.pp_profile, self.handle_command, self.handle_input_event, self.e_osc_handle_output_event) if reason == 'error': self.end('error', message) else: self.osc_enabled = True self.root.after(1000, self.oscdriver.start_server()) # and run the start shows self.run_start_shows() # set up the time of day scheduler including catchup self.tod_enabled = False if os.path.exists(self.pp_profile + os.sep + 'schedule.json'): # kick off the time of day scheduler which may run additional shows self.tod = TimeOfDay() self.tod.init(pp_dir, self.pp_home, self.pp_profile, self.root, self.handle_command) self.tod_enabled = True # then start the time of day scheduler if self.tod_enabled is True: self.tod.poll() # start Tkinters event loop self.root.mainloop() def parse_screen(self, size_text): fields = size_text.split('*') if len(fields) != 2: return 'error', 'do not understand --fullscreen comand option', 0, 0 elif fields[0].isdigit() is False or fields[1].isdigit() is False: return 'error', 'dimensions are not positive integers in ---fullscreen', 0, 0 else: return 'normal', '', int(fields[0]), int(fields[1]) # ********************* # RUN START SHOWS # ******************** def run_start_shows(self): self.mon.trace(self, 'run start shows') # parse the start shows field and start the initial shows show_refs = self.starter_show['start-show'].split() for show_ref in show_refs: reason, message = self.show_manager.control_a_show( show_ref, 'open') if reason == 'error': self.mon.err(self, message) # ********************* # User inputs # ******************** # handles one command provided as a line of text def handle_command(self, command_text): self.mon.log(self, "command received: " + command_text) if command_text.strip() == "": return if command_text[0] == '/': if self.osc_enabled is True: self.oscdriver.send_command(command_text) return fields = command_text.split() show_command = fields[0] if len(fields) > 1: show_ref = fields[1] else: show_ref = '' if show_command in ('open', 'close'): if self.shutdown_required is False: reason, message = self.show_manager.control_a_show( show_ref, show_command) else: return elif show_command == 'exitpipresents': self.exitpipresents_required = True if self.show_manager.all_shows_exited() is True: # need root.after to get out of st thread self.root.after(1, self.e_all_shows_ended_callback) return else: reason, message = self.show_manager.exit_all_shows() elif show_command == 'shutdownnow': # need root.after to get out of st thread self.root.after(1, self.e_shutdown_pressed) return else: reason = 'error' message = 'command not recognised: ' + show_command if reason == 'error': self.mon.err(self, message) return def e_all_shows_ended_callback(self): self.all_shows_ended_callback('normal', 'no shows running') def e_shutdown_pressed(self): self.shutdown_pressed('now') def e_osc_handle_output_event(self, line): #jump out of server thread self.root.after(1, lambda arg=line: self.osc_handle_output_event(arg)) def osc_handle_output_event(self, line): self.mon.log(self, "output event received: " + line) #osc sends output events as a string reason, message, delay, name, param_type, param_values = self.animate.parse_animate_fields( line) if reason == 'error': self.mon.err(self, message) self.end(reason, message) self.handle_output_event(name, param_type, param_values, 0) def handle_output_event(self, symbol, param_type, param_values, req_time): if self.gpio_enabled is True: reason, message = self.gpiodriver.handle_output_event( symbol, param_type, param_values, req_time) if reason == 'error': self.mon.err(self, message) self.end(reason, message) else: self.mon.warn(self, 'GPIO not enabled') # all input events call this callback with a symbolic name. # handle events that affect PP overall, otherwise pass to all active shows def handle_input_event(self, symbol, source): self.mon.log(self, "event received: " + symbol + ' from ' + source) if symbol == 'pp-terminate': self.handle_user_abort() elif symbol == 'pp-shutdown': self.shutdown_pressed('delay') elif symbol == 'pp-shutdownnow': # need root.after to grt out of st thread self.root.after(1, self.e_shutdown_pressed) return elif symbol == 'pp-exitpipresents': self.exitpipresents_required = True if self.show_manager.all_shows_exited() is True: # need root.after to grt out of st thread self.root.after(1, self.e_all_shows_ended_callback) return reason, message = self.show_manager.exit_all_shows() else: # events for shows affect the show and could cause it to exit. for show in self.show_manager.shows: show_obj = show[ShowManager.SHOW_OBJ] if show_obj is not None: show_obj.handle_input_event(symbol) def shutdown_pressed(self, when): if when == 'delay': self.root.after(5000, self.on_shutdown_delay) else: self.shutdown_required = True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal', 'no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def on_shutdown_delay(self): # 5 second delay is up, if shutdown button still pressed then shutdown if self.gpiodriver.shutdown_pressed() is True: self.shutdown_required = True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal', 'no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def handle_sigterm(self, signum, frame): self.mon.log(self, 'SIGTERM received - ' + str(signum)) self.terminate() def handle_user_abort(self): self.mon.log(self, 'User abort received') self.terminate() def terminate(self): self.mon.log(self, "terminate received") needs_termination = False for show in self.show_manager.shows: # print show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF] if show[ShowManager.SHOW_OBJ] is not None: needs_termination = True self.mon.log( self, "Sent terminate to show " + show[ShowManager.SHOW_REF]) # call shows terminate method # eventually the show will exit and after all shows have exited all_shows_callback will be executed. show[ShowManager.SHOW_OBJ].terminate() if needs_termination is False: self.end('killed', 'killed - no termination of shows required') # ****************************** # Ending Pi Presents after all the showers and players are closed # ************************** # callback from ShowManager when all shows have ended def all_shows_ended_callback(self, reason, message): self.canvas.config(bg=self.pp_background) if reason in ( 'killed', 'error' ) or self.shutdown_required is True or self.exitpipresents_required is True: self.end(reason, message) def end(self, reason, message): self.mon.log(self, "Pi Presents ending with reason: " + reason) if self.root is not None: self.root.destroy() self.tidy_up() # gc.collect() # print gc.garbage if reason == 'killed': self.mon.log(self, "Pi Presents Aborted, au revoir") # close logging files self.mon.finish() sys.exit(101) elif reason == 'error': self.mon.log(self, "Pi Presents closing because of error, sorry") # close logging files self.mon.finish() sys.exit(102) else: self.mon.log(self, "Pi Presents exiting normally, bye") # close logging files self.mon.finish() if self.shutdown_required is True: # print 'SHUTDOWN' call(['sudo', 'shutdown', '-h', '-t 5', 'now']) sys.exit(100) else: sys.exit(100) # tidy up all the peripheral bits of Pi Presents def tidy_up(self): self.mon.log(self, "Tidying Up") # turn screen blanking back on if self.options['noblank'] is True: call(["xset", "s", "on"]) call(["xset", "s", "+dpms"]) # tidy up animation and gpio if self.animate is not None: self.animate.terminate() if self.gpio_enabled == True: self.gpiodriver.terminate() if self.osc_enabled is True: self.oscdriver.terminate() # tidy up time of day scheduler if self.tod_enabled is True: self.tod.terminate()
class calculadora(object): def __init__(self): # DEFINIR VARIABLES GENERALES self.maxprec = 20000 # Precision numérica de la calculadora - Dev:1000, Prd: 20000 self.debuguear = 1 # Debug. Muestra en pantalla lo que se envia al display self.sendToDisplay = 0 # Enviar dígitos a Display (on/off) self.ard_comm = 'COM3' # Serial com port, debe coincidir con los baudios y el puerto arduino self.ard_baud = 9600 # Serial baud rate, debe coincidir con los baudios y el puerto arduino self.ard_tiot = 0.1 # Serial timeout 100ms, testeado con arduino UNO self.fullscreen = 0 # Abrir en pantalla completa. Dev: 0, Prd: 1 self.ultrawidescreen = 0 # Monitor UltraWideScreen def iniciar(self, master): ######### VARIABLES GENERALES ######### # Velocidad (lista de velocidades en milisegundos) self.velist = [1000, 700, 500, 400, 300, 200, 150, 100] self.velmax = len(self.velist) - 1 self.vel = -1 self.memvel = 0 # Debug self.porcionlen = 70 # Porcion a mostrar self.porcion = '' self.playsounds = 0 # VERSION DE PRUEBA!! self.playwaves = 1 # VERSION DE PRUEBA!! #Arduino COMM (Display) if self.sendToDisplay > 0: # debe coincidir con los baudios y el puerto arduino self.arduino = serial.Serial(self.ard_comm, self.ard_baud, timeout=self.ard_tiot) time.sleep(1) if self.sendToDisplay > 0: self.arduino.write('N') # RESET DYSPLAY time.sleep(1) # nsp class self.nsp = NumericStringParser() self.nsp.setPresicion(self.maxprec) #Set presicion # Contador de envio a Arduino self.resultadoAduino = '' self.resultadoNormal = '' self.contador = -1 self._job = None ####################################### if self.playwaves > 0: p = mu.pyaudio.PyAudio() self.stream = p.open(format=mu.pyaudio.paFloat32, channels=mu.CHANNELS, rate=mu.RATE, output=True, stream_callback=mu.callback) self.stream.stop_stream() ####################################### self.master = master if self.fullscreen > 0: # Full screen master.overrideredirect(True) master.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight())) master.focus_set() # <-- move focus to this widget # Otra opción # master.attributes('-fullscreen', True) else: master.geometry("%dx%d+0+0" % (master.winfo_screenwidth() - 16, master.winfo_screenheight() - 80)) master.title("Calculadora") master.bind("<Escape>", lambda e: e.widget.quit()) # Python 2 master.bind("<Key>", self.recibeChar) self.dondestoy = 'p' # Dividendo p self.dividendostr = "" self.dividendo = StringVar() self.dividendo.set(self.dividendostr) if self.ultrawidescreen > 0: # UltraWide Screen self.labelp = Label(master, textvariable=self.dividendo, bg="#fd0", width=18, justify="center", font=("Roboto", 192)) else: # 16:9 Screen self.labelp = Label(master, textvariable=self.dividendo, bg="#fd0", width=21, justify="center", font=("Roboto", 96)) self.line = Canvas(master, width=master.winfo_screenwidth(), height=50) # self.line.create_rectangle(0, 0, master.winfo_screenwidth(), 20, outline="#000", fill="#000") self.line.create_line(0, 0, master.winfo_screenwidth(), 0, fill="#000", width=50) # Divisor q self.divisorstr = "1" self.divisor = StringVar() self.divisor.set(self.divisorstr) if self.ultrawidescreen > 0: # UltraWide Screen self.labelq = Label(master, textvariable=self.divisor, bg="#eee", fg="#aaa", width=18, justify="center", font=("Roboto", 192)) else: # 16:9 Screen self.labelq = Label(master, textvariable=self.divisor, bg="#eee", fg="#aaa", width=21, justify="center", font=("Roboto", 96)) # Resultado res self.resultastr = "" self.resulta = StringVar() self.resulta.set(self.resultastr) if self.ultrawidescreen > 0: # UltraWide Screen self.labelr = Label(master, textvariable=self.resulta, bg="#eee", width=213, justify="left", font=("Roboto", 16)) else: # 16:9 Screen self.labelr = Label(master, textvariable=self.resulta, bg="#eee", width=120, justify="left", font=("Roboto", 16)) # Posiciona self.line.place(relx=0, rely=.495) self.labelp.place(relx=0, rely=.22) self.labelq.place(relx=0, rely=.545) self.labelr.place(relx=0, rely=.80) # init timer de envio a arduino # self.onUpdate() ####################################### def filtrar(self, s): if '.' in s: r = { '1': 'A', '2': 'B', '3': 'C', '4': 'D', '5': 'E', '6': 'F', '7': 'G', '8': 'H', '9': 'I', '0': 'J' } s = s.split('.') c = s[0][-1:] s[0] = s[0][0:-1] return s[0] + r[c] + s[1] else: return s def modcad(self, cad, c): cad = cad.decode('utf-8') p = cad[-1:] if isinstance(c, int): if (len(cad) >= c): cad = cad[:-c] else: c = c.decode('utf-8') cad = cad + c cad = cad.encode('utf-8') return cad def recibeChar(self, event): k = event.keycode c = event.char p = str(self.dividendostr) q = str(self.divisorstr) # # Test input del teclado # self.resultastr = c+': ',str(k)+': '+str(event.state) # self.resulta.set(self.resultastr) # return if self.debuguear == 0: self.resultastr = '' self.resulta.set(self.resultastr) numrs = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] if (self.dondestoy == 'q'): cadena = q # if cadena=='1': # cadena = '' else: cadena = p # SALIDAS if c == 'c': # c # reiniciar programa self.calculadora('REINICIAR', '', p, q) return # return '','REINICIAR' elif c == 'k': # k # salir del programa self.calculadora('SALIR', '', p, q) return # return '','SALIR' # AVANZAR Y STOP if c == 'a': # Avanza/Acelera if self.vel < 0 and self.resultadoAduino != '': self.vel = 0 self.calcelUpdate('Avanzar') self.onUpdate() elif self.vel < self.velmax: self.vel = self.vel + 1 return # return '','REINICIAR' elif c == 's': # Stop if self.vel >= 0: self.vel = self.vel - 1 return # IGUAL A elif k == 10 or k == 13 or c == 'i': # or k==61: # [ENTER] o [=] > Salto de línea o igual: '\n' ó '\r' ó '=' # imprimir cadena RESULTADO self.calculadora('RESULTADO', cadena, p, q) return # return cadena,'RESULTADO' # ESCRITURA NORMAL elif k == 8 or c == 'x': # BACKSPACE # recortar cadena un digito cadena = self.modcad(cadena, 1) elif c in numrs: # NUMEROS 0-9 # incrementa la cadena con c cadena = self.modcad(cadena, str(c)) # elif c==',' or c=='.': # COMA o PUNTO # c='.' # Siempre usa punto # # incrementa la cadena con c # cadena = self.modcad(cadena,str(c)) # NUMEROS ESPECIALES e y pi elif c == 'e': # e => 101 # Euler's number => 'e' c = 'e' # incrementa la cadena con c cadena = self.modcad(cadena, str(c)) elif c == 'h': # h => 104 # PI => 'h' c = 'π' # incrementa la cadena con c cadena = self.modcad(cadena, str(c)) elif c == 'f': # f => 104 # PI => 'h' c = 'φ' # incrementa la cadena con c cadena = self.modcad(cadena, str(c)) # OPERACIONES SIMPLES: * + - / elif c == '*': # * => 42 # Multiplicación => Reemplaza asterisco con signo de multiplicacion × c = '×' # incrementa la cadena con c cadena = self.modcad(cadena, str(c)) elif c == '+' or c == 'm': # + => 43 # incrementa la cadena con c c = '+' cadena = self.modcad(cadena, str(c)) elif c == '-' or c == 'n': # - => 45 # incrementa la cadena con c c = '-' cadena = self.modcad(cadena, str(c)) elif c == 'r': # r # SQRT => 'r' rcadena = cadena[::-1] if '(' in rcadena: if ')' in rcadena: ax = rcadena.index('(') cx = rcadena.index(')') if ax < cx: c = ')' else: c = '√(' else: c = ')' else: c = '√(' # incrementa la cadena con c cadena = self.modcad(cadena, str(c)) elif c == 'p': # p # Debe enviar al valor p sólo si no estamos ahí if (self.dondestoy != 'p'): self.calculadora('SETP', cadena, p, q) return elif c == 'q': # q # Debe enviar al valor q sólo si no estamos ahí if (self.dondestoy != 'q'): self.calculadora('SETQ', cadena, p, q) return if (self.dondestoy == 'p'): p = cadena if (self.dondestoy == 'q'): q = cadena # if (q==''): # q = '1' self.operacion(p, q) def calculadora(self, estado, cadena='', p='', q=''): if (estado == 'RESULTADO'): self.calcelUpdate('Nuevo resultado') self.porcion = '' self.memvel = 0 #Memoria de la volicidad actual if self.vel > 0: self.memvel = self.vel self.vel = -1 # Stop timer self.contador = -1 # Reset timer if self.sendToDisplay > 0: self.arduino.write('N') # RESET DYSPLAY time.sleep(1) if (self.dondestoy == 'p'): p = cadena if (self.dondestoy == 'q'): q = cadena if p == '': p = '0' if (q == ''): q = '1' rcadena = p[::-1] if '(' in rcadena: if ')' in rcadena: ax = rcadena.index('(') cx = rcadena.index(')') if ax < cx: p = p + ')' else: p = p + ')' rcadena = q[::-1] if '(' in rcadena: if ')' in rcadena: ax = rcadena.index('(') cx = rcadena.index(')') if ax < cx: q = q + ')' else: q = q + ')' self.resultado(p, q) if (estado == 'REINICIAR'): self.calcelUpdate('Reiniciar') self.resultadoNormal = '' self.resultadoAduino = '' self.vel = -1 # Stop timer self.contador = -1 # Reset timer self.operacion(p='', q=1) self.resultastr = '' self.resulta.set(self.resultastr) self.dondestoy = 'p' self.labelp.config(bg="#fd0") self.labelq.config(bg="#eee") if self.sendToDisplay > 0: self.arduino.write('N') # RESET DYSPLAY time.sleep(1) # self.calculadora() if (estado == 'SALIR'): self.calcelUpdate() logging.info("INFO\tSalir del programa") time.sleep(1) self.vel = -1 # Stop timer self.master.quit() # return if (estado == 'SETP'): q = cadena if '(' in q and ')' not in q: q = q + ')' if q == '0' or q == '': self.divisorstr = str('1') self.divisor.set(self.divisorstr) self.labelq.config(fg="#aaa") self.dondestoy = 'p' self.labelp.config(bg="#fd0") self.labelq.config(bg="#eee") # self.calculadora(p,p,q,dondestoy) if (estado == 'SETQ'): p = cadena if '(' in p and ')' not in p: p = p + ')' if q == '1': self.divisorstr = str('') self.divisor.set(self.divisorstr) self.labelq.config(fg="#aaa") self.dondestoy = 'q' self.labelp.config(bg="#eee") self.labelq.config(bg="#fd0") # self.calculadora(q,p,q,dondestoy) def maxlen(self, p, q): maxlen = len(str(p)) if (len(str(q)) > maxlen): maxlen = len(str(q)) lp = len(str(p)) lq = len(str(q)) return maxlen, lp, lq def operacion(self, p='', q=1): ml, lp, lq = self.maxlen(p, q) self.dividendostr = str(p) self.dividendo.set(self.dividendostr) self.divisorstr = str(q) self.divisor.set(self.divisorstr) # Color gris en divisor cuando es 1 if self.divisorstr != "1": self.labelq.config(fg="#000") else: self.labelq.config(fg="#aaa") def resultado(self, p, q): self.calcelUpdate() ml, lp, lq = self.maxlen(p, q) self.dividendostr = str(p) self.dividendo.set(self.dividendostr) self.divisorstr = str(q) self.divisor.set(self.divisorstr) # Color gris en divisor cuando es 1 if self.divisorstr != "1": self.labelq.config(fg="#000") else: self.labelq.config(fg="#aaa") ################################################ # Calcula p/q en la presición definida equa = '(' + p + ')/(' + q + ')' res = self.nsp.eval(equa) # RESULTADO COMO CADENA nres = '' sres = str(res) if sres == 'ERROR': self.resultastr = sres self.resulta.set(self.resultastr) logging.info("ERROR\t" + equa) return # Set start envio Arduino self.resultadoNormal = sres self.resultadoAduino = self.filtrar(sres) self.contador = -1 self.vel = self.memvel logging.info("OK\t" + equa) # Inicia envío a display arduino self.onUpdate() def calcelUpdate(self, quien=''): if self.playwaves > 0: mu.newfreq = 0 if self._job is not None: if quien != '': logging.info("CANCEL\t" + quien) self.master.after_cancel(self._job) self._job = None def onUpdate(self): self.calcelUpdate() # Actualiza el caracter enviado, la posición y el estado actual (pausa/play) self.contador = self.contador + 1 inicio = self.contador - self.porcionlen if self.contador > self.maxprec: self.porcion = '' self.contador = 0 self.resultado(self.dividendostr, self.divisorstr) if self.playwaves > 0: mu.newfreq = 0 return if inicio < 0: inicio = 0 if self.contador > len(self.resultadoAduino) - 1: enviar = '0' else: enviar = self.resultadoAduino[self.contador] self.porcion = self.porcion + enviar if len(self.porcion) > self.porcionlen - 1: self.porcion = self.porcion[-self.porcionlen:] if self.debuguear > 0: salida = u"Resultado: " + self.resultadoNormal[0:self.porcionlen] salida = salida + u"\nVelocidad: " + str( self.velist[self.vel]) + " ms" tiempofaltante = round( self.velist[self.vel] * (len(self.resultadoAduino) - self.contador) / 1000) m, s = divmod(tiempofaltante, 60) h, m = divmod(m, 60) salida = salida + u"\nTiempo restante: " + str("%d:%02d:%02d" % (h, m, s)) + " hms" salida = salida + u"\nPosición: " + str( self.contador) + " / " + str(len(self.resultadoAduino)) salida = salida + u"\nDígito: " + enviar salida = salida + u"\nPorción: " + self.porcion.rjust( self.porcionlen, ' ').replace(' ', ' ') self.resultastr = salida self.resulta.set(self.resultastr) if self.playwaves > 0: self.stream.start_stream() try: nx = int(enviar) except ValueError: nx = -1 pass if nx > 0: nx = nx - 1 elif nx == 0: nx = -1 if nx < 0: mu.newfreq = 0 else: mu.newfreq = mu.listaFreq[nx] # ENVIO A DISPLAY if self.sendToDisplay > 0: self.arduino.write( enviar ) # Envia digito actual a DISPLAY, la pausa la genera el unUpdate mismo # DEBUG EN CONSOLA if self.debuguear > 1: print(current_iso8601(), self.contador, self.vel, self.velist[self.vel], enviar) # schedule timer para ayutollamarse cada segundo if self.vel >= 0: self._job = self.master.after(self.velist[self.vel], self.onUpdate) # Versión de prueba !!! if self.playsounds > 0 and self.char2wav(enviar) != '': corto = '' if self.velist[self.vel] < 300: corto = '_' winsound.PlaySound('wav/' + self.char2wav(enviar) + corto + '.wav', winsound.SND_FILENAME | winsound.SND_ASYNC) def char2wav(self, c): r = { 'A': '1', 'B': '2', 'C': '3', 'D': '4', 'E': '5', 'G': '7', 'H': '8', 'I': '9', 'J': '0', '-': '0' } if c in r.keys(): c = r[c] n = { # '1':'c1', '2':'d1', '3':'e1', '4':'f1', '5':'', '6':'g1', '7':'a1', '8':'b1', '9':'c2', '0':'' # Mayor, Silencios: 0, 5 '1': 'c1', '2': 'd1', '3': 'd1s', '4': 'e1', '5': 'f1', '6': 'g1', '7': 'a1', '8': 'b1', '9': 'c2', '0': '' # Mayor/Menor, Silencio: 0 } return n[c]
class SkyglowEstimationToolbox: """Main class that establishes GUI.""" def __init__(self, root): self.root = root # Radio action buttons self.action = None self.sgmap_single_btn, self.krn_lib_btn, self.multi_map_btn = None, None, None self.file_log_var = StringVar() self.csv_file_var = StringVar() self.krn_folder_var = StringVar() self.output_folder_var = StringVar() self.sgmap_folder_var = StringVar() self.krn_ent_var = StringVar() self.krn_var, self.hem_var = IntVar(), IntVar() self.img, self.cdiag = None, None self.lat_lbl, self.lat_entry = None, None self.k_lbl, self.k_entry = None, None self.zen_lbl, self.zen_entry = None, None self.azi_lbl, self.azi_entry = None, None self.krn_lvl, self.krn_entry, self.krn_btn = None, None, None self.txt_redir, self.prg_log = None, None self.map_btn, self.gen_krn_btn = None, None # Sets window title, size, and icon on screen. self.root.title("Skyglow Estimation Toolbox (SET)") self.root.geometry('%dx%d+%d+%d' % (constants.SW * 0.75, constants.SH * 0.75, 25, 25)) self.root.iconbitmap(os.path.join(os.getcwd(), constants.ICO)) self.root.resizable(False, False) self.root.update_idletasks() # Creates three paned windows for the main screen. base = PanedWindow() base.pack(fill=BOTH, expand=1) sub1 = PanedWindow(base, orient=VERTICAL, height=self.root.winfo_height() * 3 / 4) base.add(sub1) sub2 = PanedWindow(sub1, orient=HORIZONTAL, height=self.root.winfo_height() / 5) sub1.add(sub2) # Creates frame for holding inputs. self.input_frame = Frame(sub2) sub2.add(self.input_frame) # Creates frame for bottom half of main screen. self.img_frame = Frame(sub1, bd=2, bg='white', relief="sunken") sub1.add(self.img_frame) # Creates canvas for displaying images. self.img_canvas = Canvas(self.img_frame, bd=2, relief="groove", width=constants.SW * 0.6, height=self.root.winfo_height() * 3 / 4 * 0.9) self.img_canvas.place(relx=.5, rely=.5, anchor=CENTER) # Creates help button for link to documentation, instructions, and about. self.help_btn = Menubutton(self.input_frame, text="Help", relief="raised", bd=2, width=8, pady=1) #self.help_btn.place(relx=1, rely=0, anchor=NE) self.help_btn.grid(column=4, columnspan=1, row=0) self.help_btn_menu = Menu(self.help_btn, tearoff=0) doc = 'https://github.com/NASA-DEVELOP' self.help_btn_menu.add_command(label="Documentation", command=lambda: self.open_url(doc)) self.help_btn_menu.add_command(label="Instructions", command=self.instructions) self.help_btn_menu.add_separator() self.help_btn_menu.add_command(label="About", command=self.about) self.help_btn["menu"] = self.help_btn_menu def main_screen(self): """Set up input GUI and image display screen.""" self.action = IntVar() btn_width = int(constants.SW / 60) file_width = int(constants.SW / 18) lbl_width = int(constants.SW / 60) gen_width = int(constants.SW / 42) radio_font = Font(family='TkDefaultFont', size=12) self.sgmap_single_btn = Radiobutton( self.input_frame, text="Generate Artificial Skyglow Map", font=radio_font, width=btn_width, variable=self.action, value='sng', command=self.sng_popup) self.krn_lib_btn = Radiobutton(self.input_frame, text="Generate Kernel Library", font=radio_font, width=btn_width, variable=self.action, value='krn', command=self.krn_popup) self.multi_map_btn = Radiobutton( self.input_frame, text="Generate Maps from Multiple Kernels", font=radio_font, width=btn_width, variable=self.action, value='mul', command=self.mul_popup) self.hem_map_btn = Radiobutton( self.input_frame, text="Generate Hemispherical Visualization", font=radio_font, width=btn_width, variable=self.action, value='hem', command=self.hem_popup) #Place widget self.sgmap_single_btn.grid(column=0, columnspan=1, row=0) self.krn_lib_btn.grid(column=1, columnspan=1, row=0) self.multi_map_btn.grid(column=2, columnspan=1, row=0) self.hem_map_btn.grid(column=3, columnspan=1, row=0) # VIIRS Image Reference File self.file_lbl = Label(self.input_frame, text="Image File:", width=lbl_width, anchor=E) self.file_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.file_log_var) self.browse_btn = Button(self.input_frame, text="Browse", command=self.import_viirs) # Angles CSV File self.csv_file_lbl = Label(self.input_frame, text="Angles CSV File:", width=lbl_width, anchor=E) self.csv_file_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.csv_file_var) self.csv_browse_btn = Button(self.input_frame, text="Browse", command=self.import_csv) # Multiple Maps form Kernel library self.mul_file_lbl = Label(self.input_frame, text="Kernel Folder:", width=lbl_width, anchor=E) self.mul_file_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.krn_folder_var) self.mul_browse_btn = Button(self.input_frame, text="Browse", command=self.import_krn_folder) # MultiKrn Map Output Location self.output_lbl = Label(self.input_frame, text="Output Location:", width=lbl_width, anchor=E) self.output_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.output_folder_var) self.output_btn = Button(self.input_frame, text="Browse", command=self.import_out_folder) # Hemisphere Output Location self.sgmap_folder_lbl = Label(self.input_frame, text="Skyglow Map Location:", width=lbl_width, anchor=E) self.sgmap_folder_log = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.sgmap_folder_var) self.sgmap_folder_btn = Button(self.input_frame, text="Browse", command=self.import_sgmap_folder) # Import Kernel Checkbutton self.check_lbl = Label(self.input_frame, text="Import Kernel:", width=lbl_width, anchor=E) self.krn_chk = Checkbutton(self.input_frame, anchor=W, variable=self.krn_var, command=self.checkbtn_val) self.hem_chk_lbl = Label(self.input_frame, text="Generate kernels for hemisphere:", width=lbl_width, anchor=E) self.hem_chk = Checkbutton(self.input_frame, anchor=W, variable=self.hem_var) # Region Latitude (deg), Grand Teton National park = 43.7904 degrees N self.lat_lbl = Label(self.input_frame, text="Latitude (deg):", width=lbl_width, anchor=E) self.lat_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") self.lon_lbl = Label(self.input_frame, text="Longitude (deg):", width=lbl_width, anchor=E) self.lon_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") # Atmospheric Clarity Parameter, REF 2, Eq. 12, p. 645 self.k_lbl = Label(self.input_frame, text="Atmospheric Clarity Parameter:", width=btn_width, anchor=E) self.k_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") # Zenith angle (deg), z, REF 2, Fig. 6, p.648 self.zen_lbl = Label(self.input_frame, text="Zenith Angle (deg):", width=lbl_width, anchor=E) self.zen_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") # Azimuth angle (deg) self.azi_lbl = Label(self.input_frame, text="Azimuth Angle (deg):", width=lbl_width, anchor=E) self.azi_entry = Entry(self.input_frame, width=btn_width, bd=2, relief="sunken") self.krn_lbl = Label(self.input_frame, text="Kernel File:", width=lbl_width, anchor=E) self.krn_ent = Entry(self.input_frame, width=file_width, bd=2, relief="sunken", textvariable=self.krn_ent_var) self.krn_btn = Button(self.input_frame, text="Browse", command=self.import_krn) # Generate Artificial Skyglow Map Button self.map_btn = Button(self.input_frame, text="Generate Artificial Skyglow Map", width=gen_width, command=self.generate_map) # Generate Kernal library button for SET self.gen_krn_btn = Button(self.input_frame, text="Generate Kernel Library", width=gen_width, command=self.generate_krn) # Generate Map of Multiple Kernals(word better later on) self.mul_map_btn = Button(self.input_frame, text="Generate Maps from Multiple Kernels", width=gen_width, command=self.generate_mmap) # Generate Hemispherical Visualization Display of Skyglow self.hem_gen_btn = Button(self.input_frame, text="Generate Hemisphere", width=gen_width, command=self.generate_hem) def import_viirs(self): """Import a VIIRS DNB file.""" # Allows user to search through his directory for VIIRS Image file. file_types = [('TIFF Files', '*.tif'), ('All files', '*')] file_name = filedialog.askopenfilename(initialdir='/', title="Select file", filetypes=file_types) self.file_log_var.set(file_name) # Checks to see if file is empty. If not, displays image on canvas. if file_name != '': pilimg = Image.open(file_name) pilimg_width, pilimg_height = pilimg.size pilimg.tile = [ t for t in pilimg.tile if t[1][2] < pilimg_width and t[1][3] < pilimg_height ] canvas_size = (self.img_canvas.winfo_width(), self.img_canvas.winfo_height()) pilimg_r = pilimg.resize(canvas_size, Image.ANTIALIAS) pilimg_col = ImageOps.colorize(ImageOps.grayscale(pilimg_r), (0, 0, 0), (255, 255, 255)) pilimg_cont = ImageOps.autocontrast(pilimg_col, cutoff=.4, ignore=None) self.img = ImageTk.PhotoImage(pilimg_cont) self.img_canvas.create_image(canvas_size[0] / 2, canvas_size[1] / 2, image=self.img) else: print('File is empty.') def import_csv(self): """Import CSV file.""" file_types = [('CSV Files', '*.csv'), ('All files', '*')] file_name = filedialog.askopenfilename(initialdir='/', title="Select file", filetypes=file_types) self.csv_file_var.set(file_name) if file_name is '': print('File is empty.') def import_krn_folder(self): """Import kernel folder.""" krn_dir = filedialog.askdirectory(initialdir='/', title="Select kernel folder") self.krn_folder_var.set(krn_dir) if krn_dir is '': print('Directory is empty.') def import_out_folder(self): """Import skyglow output folder.""" output_dir = filedialog.askdirectory(initialdir='/', title="Select output folder") self.output_folder_var.set(output_dir) if output_dir is '': print('Directory is empty.') def import_krn(self): """Import existing kernel tif.""" file_types = [('TIFF Files', '*.tif'), ('All files', '*')] file_name = filedialog.askopenfilename(initialdir='/', title="Select file", filetypes=file_types) self.krn_ent_var.set(file_name) def import_sgmap_folder(self): """Import skyglow map folder for hemisphere building.""" sgmap_dir = filedialog.askdirectory(initialdir='/', title="Select skyglow map folder") self.sgmap_folder_var.set(sgmap_dir) if sgmap_dir is '': print('Directory is empty.') def sng_popup(self): """Single map tab.""" self.remove_all() self.check_lbl.grid(column=0, row=2) self.krn_chk.place(relx=.22, rely=.41, anchor=CENTER) self.file_lbl.grid(column=0, row=1) self.file_log.grid(column=1, columnspan=3, row=1) self.browse_btn.grid(column=4, row=1, sticky=W, padx=3) self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) self.k_lbl.grid(column=2, row=3) self.k_entry.grid(column=3, row=3) self.zen_lbl.grid(column=0, row=4) self.zen_entry.grid(column=1, row=4) self.azi_lbl.grid(column=2, row=4) self.azi_entry.grid(column=3, row=4) self.map_btn.grid(column=1, columnspan=3, row=5, sticky=N + S + E + W) def krn_popup(self): """Kernel lib tab.""" self.remove_all() # latitude self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) # atmospheric clarity self.k_lbl.grid(column=2, row=3) self.k_entry.grid(column=3, row=3) # angles file self.csv_file_lbl.grid(column=0, row=1) self.csv_file_log.grid(column=1, columnspan=3, row=1) self.csv_browse_btn.grid(column=4, row=1, sticky=W, padx=3) # input VIIRS image self.file_lbl.grid(column=0, row=2) self.file_log.grid(column=1, columnspan=3, row=2) self.browse_btn.grid(column=4, row=2, sticky=W, padx=3) self.hem_chk_lbl.grid(column=0, row=4) self.hem_chk.place(relx=.21, rely=.69) self.gen_krn_btn.grid(column=1, columnspan=3, row=5, sticky=N + S + E + W) def mul_popup(self): """Multiple maps tab.""" self.remove_all() # Kernel folder location self.mul_file_lbl.grid(column=0, row=1) self.mul_file_log.grid(column=1, columnspan=3, row=1) self.mul_browse_btn.grid(column=4, row=1, sticky=W, padx=3) # input VIIRS image self.file_lbl.grid(column=0, row=2) self.file_log.grid(column=1, columnspan=3, row=2) self.browse_btn.grid(column=4, row=2, sticky=W, padx=3) # Choose output location self.output_lbl.grid(column=0, row=3) self.output_log.grid(column=1, columnspan=3, row=3) self.output_btn.grid(column=4, row=3, sticky=W, padx=3) # Generate map from kernel folder self.mul_map_btn.grid(column=1, columnspan=3, row=4, sticky=N + S + E + W) def hem_popup(self): """Hemisphere tab.""" self.remove_all() # Skyglow Map Folder self.sgmap_folder_lbl.grid(column=0, row=1) self.sgmap_folder_log.grid(column=1, columnspan=3, row=1) self.sgmap_folder_btn.grid(column=4, row=1, sticky=W, padx=3) # Latitude entry self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) # Longitude entry self.lon_lbl.grid(column=2, row=3) self.lon_entry.grid(column=3, row=3) # Generate Hemispherical Visualization button self.hem_gen_btn.grid(column=1, columnspan=3, row=4, sticky=N + S + E + W) def remove_all(self): """Remove all existing GUI elements before opening new tab.""" self.check_lbl.grid_remove() self.krn_chk.place_forget() self.hem_chk.place_forget() self.hem_chk_lbl.grid_remove() self.file_lbl.grid_remove() self.file_log.grid_remove() self.browse_btn.grid_remove() self.krn_lbl.grid_remove() self.krn_ent.grid_remove() self.krn_btn.grid_remove() self.lat_lbl.grid_remove() self.lat_entry.grid_remove() self.k_lbl.grid_remove() self.k_entry.grid_remove() self.zen_lbl.grid_remove() self.zen_entry.grid_remove() self.azi_lbl.grid_remove() self.azi_entry.grid_remove() self.map_btn.grid_remove() self.gen_krn_btn.grid_remove() self.mul_map_btn.grid_remove() self.csv_file_lbl.grid_remove() self.csv_file_log.grid_remove() self.csv_browse_btn.grid_remove() self.mul_file_lbl.grid_remove() self.mul_file_log.grid_remove() self.mul_browse_btn.grid_remove() self.output_lbl.grid_remove() self.output_log.grid_remove() self.output_btn.grid_remove() self.hem_gen_btn.grid_remove() self.lat_lbl.grid_remove() self.lat_entry.grid_remove() self.lon_lbl.grid_remove() self.lon_entry.grid_remove() self.sgmap_folder_lbl.grid_remove() self.sgmap_folder_log.grid_remove() self.sgmap_folder_btn.grid_remove() def checkbtn_val(self): """Change interface based on if Import Kernel button is checked.""" # Import Kernel File widgets when Kernel Checkbutton is marked. if self.krn_var.get(): self.lat_lbl.grid_remove() self.lat_entry.grid_remove() self.k_lbl.grid_remove() self.k_entry.grid_remove() self.zen_lbl.grid_remove() self.zen_entry.grid_remove() self.azi_lbl.grid_remove() self.azi_entry.grid_remove() self.krn_lbl.grid(column=0, row=2) self.krn_ent.grid(column=1, columnspan=3, row=2) self.krn_btn.grid(column=4, row=2, sticky=W, padx=3) self.krn_chk.place_forget() self.krn_chk.place(relx=0.19, rely=.5) # Input parameter widgets when Kernel Checkbuttton is unmarked else: self.krn_lbl.grid_remove() self.krn_ent.grid_remove() self.krn_btn.grid_remove() self.lat_lbl.grid(column=0, row=3) self.lat_entry.grid(column=1, row=3) self.k_lbl.grid(column=2, row=3) self.k_entry.grid(column=3, row=3) self.zen_lbl.grid(column=0, row=4) self.zen_entry.grid(column=1, row=4) self.azi_lbl.grid(column=2, row=4) self.azi_entry.grid(column=3, row=4) self.krn_chk.place_forget() self.krn_chk.place(relx=0.22, rely=.41, anchor=CENTER) @staticmethod def open_url(url): """"Open a url""" webbrowser.open_new(url) def instructions(self): """Open instructions window.""" # Instantiates separate Toplevel instruction window. instr_window = Toplevel(self.root) instr_window.geometry('550x575+25+25') instr_window.title('Instructions') instr_window.wm_iconbitmap(constants.ICO) instr_window.resizable(False, False) # Creatse Scrollbar and Frame for containing other widgets. instr_scroll = Scrollbar(instr_window) instr_scroll.pack(fill=Y, side="right") instr_frame = Frame(instr_window, bg='white') instr_frame.pack(fill=BOTH, side="left") # Adds instruction text from constants and adds image of Cinzano's diagram. instr = Text(instr_frame, width=65, height=40, padx=10, pady=5, bd=0, wrap="word") instr.insert("end", constants.INSTR) cdiagram_file = Image.open("./static/cinzano_diagram.PNG") cdiagram_file = cdiagram_file.resize((500, 450), Image.ANTIALIAS) self.cdiag = ImageTk.PhotoImage(cdiagram_file) instr.image_create("end", image=self.cdiag) instr.tag_add("top", "1.0", "4.10") instr.tag_config("top", font='Times 12 bold') instr.tag_add("body", "5.0", "19.20") instr.tag_config("body", font='Times 12') instr.insert("end", constants.CDIAG) instr.pack() instr_scroll.config(command=instr.yview) def about(self): """Open an about window. Window gives authors, SET version number, and icon credit. """ # Instantiates a new Toplevel about window. about_window = Toplevel(self.root) about_window.geometry('350x335+25+25') about_window.title('About') about_window.wm_iconbitmap(constants.ICO) about_window.resizable(False, False) # Adds text to about window. about = Text(about_window, width=50, height=30, padx=10, pady=3) about.insert("end", constants.ABOUT) about.tag_add("abt", "1.0", "21.30") about.tag_config("abt", font='Times 10 bold', justify=CENTER) about.pack() def progress(self): """Construct a progress window to monitor darksky.""" # Instantiates a new Toplevel window and frame for progress bar and loading log. self.prg_window = Toplevel(self.root) self.prg_window.geometry('650x325+250+250') self.prg_window.title('Generating Artificial Skyglow Map...') self.prg_window.iconbitmap(constants.ICO) self.prg_window.resizable(False, False) prg_frame = Frame(self.prg_window) prg_frame.pack(fill=BOTH) # Creates Scrollbar, Progressbar, and Label for checking progress.. prg_scroll = Scrollbar(prg_frame) prg_scroll.pack(fill=Y, side="right") self.prg_bar = ttk.Progressbar(prg_frame, orient=HORIZONTAL, length=750, mode='indeterminate') self.prg_bar.pack() self.prg_bar.start() prg_lbl_txt = StringVar() prg_lbl = Label(prg_frame, textvariable=prg_lbl_txt) prg_lbl.pack() # Displays message log that prints from log file and starts darkskypy. self.prg_log = Text(prg_frame, width=90, padx=5, pady=5, relief="sunken") self.prg_log.pack() self.prg_log.insert( "end", "*****Progress Log*****\n=======================\n") self.prg_log.tag_add("abt", "1.0", "3.0") self.prg_log.tag_config("abt", font='Courier 12 bold', justify=CENTER) self.txt_redir = LogRedirector(self.prg_log) logger.addHandler(self.txt_redir) sys.stderr = StderrRedirector(self.prg_log) prg_lbl_txt.set("Start time: " + str(time.asctime())) self.no_progress = 0 def update_progress(self): """Update progress window to prevent it from freezing.""" self.prg_log.update() # if only one thread exists, stop progress bar and close window if len(threading.enumerate()) == 1: self.prg_bar.stop() self.no_progress += 1 if self.no_progress == 3: self.prg_window.withdraw() else: self.prg_bar.start() self.root.after(1000, self.update_progress) def generate_map(self): """Call darksky.sgmapper in background thread.""" # Acquires input arguments. lat_in, k_in, zen_in, azi_in, file_in, krn_file_in = 0, 0, 0, 0, '', '' if self.krn_var.get(): krn_file_in = self.krn_ent_var.get() else: lat_in = float(self.lat_entry.get()) k_in = float(self.k_entry.get()) zen_in = float(self.zen_entry.get()) azi_in = float(self.azi_entry.get()) file_in = self.file_log_var.get() self.progress() # Create new threads to run light propagation model simultaneously. p_thread = threading.Thread(target=self.update_progress()) t_thread = threading.Thread(target=darksky.sgmapper, args=(lat_in, k_in, zen_in, azi_in, file_in, krn_file_in)) t_thread.setDaemon(True) p_thread.start() t_thread.start() def generate_krn(self): """Start kernel generation in background threads.""" # Acquires input arguments csv_in, file_in, lat_in, k_in, hem = '', '', 0, 0, False csv_in = self.csv_file_var.get() file_in = self.file_log_var.get() lat_in = float(self.lat_entry.get()) k_in = float(self.k_entry.get()) hem = self.hem_var.get() self.progress() # Create new threads to run light propagation model simultaneously. p_thread = threading.Thread(target=self.update_progress()) with open(csv_in, "rb") as f: angle_list = loadtxt(f, delimiter=",", skiprows=1) p_thread.start() for angle_set in angle_list: t_thread = threading.Thread(target=darksky.generate_krn, args=(lat_in, k_in, angle_set[0], angle_set[1], file_in, hem)) t_thread.setDaemon(True) t_thread.start() def generate_mmap(self): """Start brightness map creation from kernels.""" # Acquires input arguments krn_folder_in, file_in, output_in, = '', '', '' krn_folder_in = self.krn_folder_var.get() file_in = self.file_log_var.get() output_in = self.output_folder_var.get() self.progress() # Create new threads to run light propagation model simultaneously. p_thread = threading.Thread(target=self.update_progress()) t_thread = threading.Thread(target=darksky.multisgmapper, args=(file_in, krn_folder_in, output_in)) t_thread.setDaemon(True) p_thread.start() t_thread.start() def generate_hem(self): """Generate hemisphere.""" sgmap_folder_in, lat_in, lon_in, = '', 0, 0 sgmap_folder_in = self.sgmap_folder_var.get() lat_in = float(self.lat_entry.get()) lon_in = float(self.lon_entry.get()) darksky.generate_hem(lat_in, lon_in, sgmap_folder_in)
mainframe.resizable(False, False) def mainexit(): global cv, cv_frame, viewer, select_ball del cv del cv_frame del viewer select_ball[0] = -1 mainframe.destroy() mainframe.protocol('WM_DELETE_WINDOW', mainexit) cv_bg_color = '#d5d5d5' cv_frame = Canvas(mainframe) #,bg=cv_bg_color cv_frame.place(x=0, y=0, relwidth=1.0, relheight=1.0) point = 0 point_max = 0 point_canvas = cv_frame.create_text(81, 27, font=('Purisa', 24), text=point) point_max_canvas = cv_frame.create_text(405, 27, font=('Purisa', 24), text=point_max) viewer = Canvas(cv_frame) #,bg=cv_bg_color) viewer.place(x=162, y=0, width=162, height=54) cv = Canvas(cv_frame) #,bg=cv_bg_color) cv.place(x=0, y=55, width=490, height=490) width_board = 9 height_board = 9 map_board = []
class ColourSetter: def __init__(self, parent): self.parent = parent self.root = self.parent.root self.size = (1, 1) self.colours = [(0, 0, 255)] self.colour_cells = [] self.draw(init=True) return def draw(self, init=False): if init: self.canvas_width, self.canvas_height = 0, 0 self.canvas = Canvas(self.root, bg="black") self.colour_cells = [] # update colour cells while self.colour_cells != []: #print('killing...') self.colour_cells[0].unbind("<Button-1>") self.colour_cells[0].destroy() del self.colour_cells[0] self.button_index_dict = dict() nb_colours = self.size[0]*self.size[1] pos = 0 for ix in range(self.size[0]): for iy in range(self.size[1]): colour = self.colours[pos] # create the new cell colour_cell = Button(self.canvas, bg=toHex([v/255. for v in colour]), activebackground=toHex([v/255. for v in colour])) colour_cell.bind("<Button-1>", self.handleColourSelector) # place the cell cell_width = self.canvas_width/self.size[0] cell_height = self.canvas_height/self.size[1] cell_width = min(cell_width, cell_height) cell_height = min(cell_width, cell_height) x = ix * cell_width y = iy * cell_height colour_cell.place(x = x, y = y, width = cell_width, height=cell_height) self.button_index_dict[colour_cell] = pos self.colour_cells.append(colour_cell) pos += 1 def handleColourSelector(self, event=[]): #print("SELECTOR:", event) #print(dir(event)) btn_pos = self.button_index_dict[event.widget] #event.widget.configure(bg="black") new_colour_rgb, new_colour_hex = tkcolorpicker.askcolor(color=self.colours[btn_pos]) if new_colour_rgb == None: print("No colour selected.") return self.colours[btn_pos] = new_colour_rgb self.draw() return def place(self, x, y, width, height): self.canvas_width = width self.canvas_height = height self.canvas.place(x=x, y=y, width=width, height=height) return def setGridSize(self, size): self.size = size nb_colours = self.size[0] * self.size[1] # need to make sure there are the proper number of colours self.colours = self.colours[:nb_colours] if len(self.colours) < nb_colours: for _ in range(nb_colours - len(self.colours)): self.colours.append(self.colours[-1]) self.draw() def randomize(self): nb_colours = self.size[0] * self.size[1] new_seed_colours = [] for _ in range(nb_colours): c = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) new_seed_colours.append(c) self.colours = new_seed_colours self.draw() return def getSeed(self): # return the seed image with specified colours N1 = Image.new('RGB', self.size, "white") pix1 = N1.load() pos = 0 for x in range(N1.size[0]): for y in range(N1.size[1]): r, g, b = self.colours[pos] pix1[x,y] = (r, g, b) pos += 1 return N1
win = tk.Tk() win.title('TRR Eyeglasses Selector 1.0.1') img = PhotoImage(file='select.gif') win.tk.call('wm', 'iconphoto', win._w, img) frame1 = tk.Frame( master = win, width = 640, height = 550, bg = '#8B4513' ) frame3 = tk.Frame(master = win, width=350, height=50, bg='#ffffff') frame4 = tk.Frame(master = win, width=150, height=50, bg='#000000') frame1.pack(fill='both', expand='yes') canvas = Canvas(frame1, width=640, height=450) canvas.place(in_=frame1,x=0,y=0,width=640,height=450) frame3.place(in_=frame1, x=5, y=460, width=427, height=75) rsstext=tk.Text(frame3) rsstext.insert(END,'ข่าวสาร') rsstext.pack() localtime = time.asctime( time.localtime(time.time()) ) frame4.place(in_=frame1, x=435, y=460, width=205, height=56) label4001 = tk.Label(frame4, text=format(price,'01'),font="Arial 28 bold",fg='#ffffff', bg='#000000') label4001.place(x=170,y=0) label4002 = tk.Label(frame4, text=localtime,font="Arial 6",fg='#ffffff', bg='#000000') label4002.place(x=5,y=40) def plu_take_a_picture(i): global plu_button,image_CV,plu_tkpi,cam_num,plu_pic,nok_air win.after_cancel(nok_air)
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() self.img_labels = [Label(self), Label(self)] def initUI(self): self.bg_color = '#333' # self.parent.title("Comparação de imagens") self.style = Style() self.style.configure('TFrame', background=self.bg_color) self.pack(fill=BOTH, expand=1) menu_bar = Menu(self.parent) self.parent.config(menu=menu_bar) size = self.parent.size select_image_btn = Button(self, text='Selecionar Imagem', command=self.select_image_file) select_image_btn.place(x=10, y=10) quit_button = Button(self, text='Sair', command=self.quit) quit_button.place(x=size[0] - 100, y=size[1] - 50) self.canvas = Canvas(self, bg=self.bg_color, bd=10) self.canvas.pack() self.canvas.place(x=0, y=600, height=200, width=650) def text_dialog_box(self, box_title, msg): return tkSimpleDialog.askstring(box_title, msg) def draw_result(self, results): self.canvas.grid_forget() self.canvas = Canvas(self, bg=self.bg_color, bd=10) self.canvas.pack() self.canvas.place(x=0, y=600, height=200, width=650) font = ('Helvetica', '12') self.canvas.create_text(20, 40, anchor=Tkinter.W, font=font, text='Probability of being the same image according different algorithms:', fill='white') self.canvas.create_text(20, 65, anchor=Tkinter.W, font=font, text=results[0], fill='white') self.canvas.create_text(20, 90, anchor=Tkinter.W, font=font, text=results[1], fill='white') self.canvas.create_text(20, 115, anchor=Tkinter.W, font=font, text=results[2], fill='white') def load_image(self, file_name, position, label): image = Image.open(file_name) image = ImageTk.PhotoImage(image) label.__setitem__('image', image) label.image = image label.place(x=position[0], y=position[1]) def select_image_file(self): file_types = [('PNG Image', '*.png'), ('Todos arquivos', '*')] dialog_box = tkFileDialog.Open(self, filetypes=file_types) file_name = dialog_box.show() self.file_name = file_name msg = 'Qual a largura desejada (em pixels) da imagem?\nO menor valor aceito é 20, e o maior, 200' image_width = self.text_dialog_box('Largura da imagem', msg) while not image_width.isdigit() or int(image_width) < 20 or int(image_width) > 200: msg = 'Valor Inválido! Os valores aceitos para largura (em pixels) vão de 20 a 200\nEntre com novo valor:' image_width = self.text_dialog_box('Largura da imagem', msg) msg = 'Qual a altura desejada (em pixels) da imagem?\nO menor valor aceito é 20, e o maior, 150' image_height = self.text_dialog_box('Altura da imagem', msg) while not image_height.isdigit() or int(image_height) < 20 or int(image_height) > 150: msg = 'Valor Inválido! Os valores aceitos para altura (em pixels) vão de 20 a 150\nEntre com novo valor:' image_height = self.text_dialog_box('Altura da imagem', msg) image_size = (int(image_width), int(image_height)) if file_name is not None: logging.debug('Imagem selecionada: ' + file_name) file_names, results = create_images(file_name, image_size) self.load_image(file_names[0], (10, 50), self.img_labels[0]) x_position = self.parent.size[0] / 2 - 200 self.load_image(file_names[1], (x_position, 50), self.img_labels[1]) print results self.draw_result(results) else: logging.debug('Nenhum arquivo de imagem foi selecionado')
class Gui(Frame, threading.Thread): def __init__(self, parent): threading.Thread.__init__(self) Frame.__init__(self, parent) self.parent = parent self.closeRequest = False self.initUI() self.start() def initUI(self): self.parent.title("Crazyflie Client") Label(self, text="Pitch").place(x=5, y=5) self.label_pitch = Label(self, text="0.00") self.label_pitch.place(x=60, y=5) Label(self, text="Roll").place(x=5, y=25) self.label_roll = Label(self, text="0.00") self.label_roll.place(x=60, y=25) Label(self, text="Yaw").place(x=5, y=50) self.label_yaw = Label(self, text="0.00") self.label_yaw.place(x=60, y=50) Label(self, text="Throttle").place(x=5, y=70) self.label_thrust = Label(self, text="0.00") self.label_thrust.place(x=60, y=70) self.canvas1 = Canvas(self, bg="#ddd", width=150, height=150) self.canvas1.place(x=395, y=25) self.canvas2 = Canvas(self, bg="#eee", width=340, height=280) self.canvas2.place(x=300, y=200) self.pack(fill=BOTH, expand=1) def onClose(self): self.closeRequest = True def drawCanvas1(self, status): self.canvas1.delete("all") max = 30. x = (status.roll / max) * 75 + 76 y = (status.pitch / max) * 75 + 76 w0 = 2 w10 = 75 * 1 / 3. w20 = 75 * 2 / 3. w30 = 75 * 3 / 3. self.canvas1.create_line(76, 0, 76, 150, fill="#bbb") self.canvas1.create_line(0, 76, 150, 76, fill="#bbb") self.canvas1.create_oval(76 - w0, 76 - w0, 76 + w0, 76 + w0, outline="#bbb") self.canvas1.create_oval(76 - w10, 76 - w10, 76 + w10, 76 + w10, outline="#bbb") self.canvas1.create_oval(76 - w20, 76 - w20, 76 + w20, 76 + w20, outline="#bbb") self.canvas1.create_oval(76 - w30, 76 - w30, 76 + w30, 76 + w30, outline="#bbb") self.canvas1.create_oval(x - 4, y - 4, x + 4, y + 4, fill="#000") def drawCanvas2(self, status): self.canvas2.delete("all") w = 40 w2 = 80 self.canvas2.create_rectangle(0 * w2, 0, w + 0 * w2, 200, outline="#aaa") self.canvas2.create_rectangle(1 * w2, 0, w + 1 * w2, 200, outline="#aaa") self.canvas2.create_rectangle(2 * w2, 0, w + 2 * w2, 200, outline="#aaa") self.canvas2.create_rectangle(3 * w2, 0, w + 3 * w2, 200, outline="#aaa") pixel_M1 = (status.motor_1 / 60000.) * 200 pixel_M2 = (status.motor_2 / 60000.) * 200 pixel_M3 = (status.motor_3 / 60000.) * 200 pixel_M4 = (status.motor_4 / 60000.) * 200 self.canvas2.create_rectangle(0 * w2, 200 - pixel_M1, w + 0 * w2, 200, fill="#0f0", outline="#0f0") self.canvas2.create_rectangle(1 * w2, 200 - pixel_M2, w + 1 * w2, 200, fill="#0f0", outline="#0f0") self.canvas2.create_rectangle(2 * w2, 200 - pixel_M3, w + 2 * w2, 200, fill="#0f0", outline="#0f0") self.canvas2.create_rectangle(3 * w2, 200 - pixel_M4, w + 3 * w2, 200, fill="#0f0", outline="#0f0") self.canvas2.create_rectangle(75, 230, 275, 270, outline="#aaa") pixel_bat = (status.bat / 4.) * 200 self.canvas2.create_rectangle(75, 230, 75 + pixel_bat, 270, fill="#0f0", outline="#0f0") def run(self): while self.closeRequest == False: fc = flight.getFlightController() self.label_pitch.config(text="%2.2f" % fc.pitch) self.label_roll.config(text="%2.2f" % fc.roll) self.label_yaw.config(text="%2.2f" % fc.yawrate) self.label_thrust.config(text="%2.2f" % fc.throttle) self.drawCanvas1(flight.getCFStatus()) self.drawCanvas2(flight.getCFStatus()) time.sleep(0.05) self.quit()
class liuyao: def __init__(self,root,gua64): self.cntoint={u'少阳-----':'1',u'少阴-- --':'2',u'老阳--O--':'3',u'老阴--X--':'4'} self.tfont=tkFont.Font(family='Fixdsys',size=25,weight=tkFont.BOLD) self.gfont=tkFont.Font(family='Fixdsys',size=13,weight=tkFont.BOLD) self.dgua=[] #动爻 self.ygua=[] #原始卦 self.bbgua=[] #变卦 self.yguastr=[] #原始卦 self.gua=[] #只有12的卦 self.pabout=True #右键显示消失淮南标题 self.guax=200 self.guay=100 self.liushen={'甲':0,'乙':0,'丙':1,'丁':1,'戊':2,'己':3,'庚':4,'辛':4,'壬':5,'癸':5} self.liushencn=['青龙','朱雀','勾陈','腾蛇','白虎','玄武'] self.tiangan={'甲':1,'乙':2,'丙':3,'丁':4,'戊':5,'己':6,'庚':7,'辛':8,'壬':9,'癸':10} self.dizhi={'子':1,'丑':2,'寅':3,'卯':4,'辰':5,'巳':6,'午':7,'未':8,'申':9,'酉':10,'戌':11,'亥':12} self.kongwangzu=['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'] self.root=root self.root.title(u'===六爻排盘===[淮南内部专用]') self.root.minsize(550,380) self.root.maxsize(550,380) self.canvas=Canvas(root,width=460,height=380,bg='gray') # self.picyang=PhotoImage(file='tk\\yang.gif') # self.picyin=PhotoImage(file='tk\\yin.gif') self.canvas.place(relx=0,rely=0) self.com={} for i in xrange(6): self.com[i]=Combobox(root,state='readonly') self.com[i]['values']=(u'少阳-----',u'少阴-- --',u'老阳--O--',u'老阴--X--') self.com[i].current(0) self.com[i].place(relx=0.85,rely=0.36-0.07*i,width=80) bt1=Button(self.root,text=u'排盘',command=self.paipan) bt2=Button(self.root,text=u'清除',command=self.cls) l1=Label(self.root,text=u'右键水印') l1.place(x=480,y=327) # bt1.place(relx=0.85,rely=0.35+0.7) # bt1.pack(side='right') bt1.place(x=467,y=170,width=78) bt2.place(x=467,y=350,width=78) self.date() #干支 #=========================== self.root.bind('<Button-3>',self.about) def cls(self): self.canvas.delete('pic') #删除所有上次产生的ITEMS self.canvas.delete('liushen') def liushenf(self): #配六神 xu=self.liushen[self.ritian.encode('utf-8')] for i in xrange(6): self.canvas.create_text(self.guax-170,100+150-30*i,font=self.gfont,text=self.liushencn[xu],tag='liushen') xu+=1 if xu>5: xu-=6 def date(self): turl=urllib2.urlopen('http://www.nongli.com/item4/index.asp',timeout=10).read() soup=BeautifulSoup(turl) zu=soup.findAll('td',{'width':'74%','bgcolor':'#FFFFFF'})[1].text # print zu wanzu=[] #wanzu里面是完成的年月日干支 wanzu.append(zu.split(' ')[0]) wanzu.append(zu.split(' ')[2]) wanzu.append(zu.split(' ')[3]) for i in xrange(3): # print u'干支',wanzu[i] self.canvas.create_text(self.guax-90+60*i,30,text=wanzu[i],font=self.gfont,tag='riqi') ri=wanzu[2] self.ritian=list(ri)[0] self.ridi=list(ri)[1] self.kongwang() def kongwang(self): # print u'日干支:',self.ridi,self.ritian cha=self.dizhi[self.ridi.encode('utf-8')]-self.tiangan[self.ritian.encode('utf-8')] if cha<0: cha+=+10 self.canvas.create_text(self.guax-90+120+30,30,font=self.gfont,text='(',tag='riqi') self.canvas.create_text(self.guax-90+120+30+15,30,font=self.gfont,text=self.kongwangzu[cha-2],tag='riqi') self.canvas.create_text(self.guax-90+120+30+30,30,font=self.gfont,text=self.kongwangzu[cha-1],tag='riqi') self.canvas.create_text(self.guax-90+120+30+45,30,font=self.gfont,text=')',tag='riqi') def about(self,event): if self.pabout: self.canvas.create_text(self.guax,100+250,text='淮南法教专用水印',fill='tan',font=self.tfont,tag='about') self.canvas.create_text(self.guax+140,370,text='--无名',fill='tan',tag='about') self.pabout=False else: self.canvas.delete('about') self.pabout=True def paipan(self): for i in xrange(6): self.ygua.append(self.cntoint[self.com[i].get()]) #得到原始爻名,转换为1234,添加入gua self.gua=self.ygua bbgua=self.gua print '=======================' print 'sel.gua',self.gua for i in xrange(6): if self.ygua[i]=='3': self.gua[i]='1' self.dgua.append(str(i)) self.dgua.append('1') elif self.ygua[i]=='4': self.gua[i]='2' self.dgua.append(str(i)) self.dgua.append('2') self.guastr=''.join(self.gua) # print u'变卦',bbgua # print u'字符串卦数',self.guastr # print u'数列卦',self.gua # print u'动卦',self.dgua # print gua64[guastr] self.draw() self.liushenf()#六神 def draw(self): self.canvas.delete('pic') #删除所有上次产生的ITEMS self.canvas.delete('liushen') # print u'当前itme数',self.canvas.find_all() #本卦 for i in xrange(6): if self.gua[i]=='1': # self.canvas.create_image(self.guax,100+150-30*i,image=self.picyang,tag='pic') self.canvas.create_text(self.guax,95+150-30*i,text='▅▅▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic') else: # self.canvas.create_image(self.guax,100+150-30*i,image=self.picyin,tag='pic') self.canvas.create_text(self.guax,95+150-30*i,text='▅ ▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic') #下面是六亲 for i in xrange(6): self.canvas.create_text(self.guax-70,100+30*i,font=self.gfont,text=gua64[self.guastr][i],tag='pic') #动爻标记 for i in xrange(0,len(self.dgua),2): if self.dgua[i+1]=='1': self.canvas.create_text(self.guax+70,247-30*int(self.dgua[i]),font=self.gfont,text='O',tag='pic',fill='red') else: self.canvas.create_text(self.guax+70,247-30*int(self.dgua[i]),font=self.gfont,text='X',tag='pic',fill='red') #世 syw=gua64[self.guastr][6] self.canvas.create_text(self.guax+55,280-30*syw,font=self.gfont,text='世',tag='pic') #应 yyw=gua64[self.guastr][7] self.canvas.create_text(self.guax+55,280-30*yyw,font=self.gfont,text='应',tag='pic') #六合、冲 hc=gua64[self.guastr][8] self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=hc,tag='pic') #游魂、归魂 zg=gua64[self.guastr][9] self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=zg,tag='pic') #卦宫 gg=gua64[self.guastr][10] self.canvas.create_text(self.guax,100-30,font=self.gfont,text=gg,tag='pic') #变卦 self.biangua() self.guastr='' self.dgua=[] #动爻 self.ygua=[] #原始卦 self.bbgua=[] #变卦 self.yguastr=[] #原始卦 self.gua=[] #只有12的卦 def biangua(self): self.bbgua=self.gua # print 'biangua',self.bbgua ''' sel.gua ['4', '4', '3', '3', '4', '3'] 字符串卦数 221121 数列卦 ['2', '2', '1', '1', '2', '1'] 动卦 ['0', '2', '1', '2', '2', '1', '3', '1', '4', '2', '5', '1'] 当前itme数 (1, 2, 3, 4, 5, 6, 7) biangua ['1', '1', '2', '2', '1', '2'] bguastr 112212 ''' for i in xrange(0,len(self.dgua),2): if self.dgua[i+1]=='1': self.bbgua[int(self.dgua[i])]='2' else: self.bbgua[int(self.dgua[i])]='1' print 'biangua',self.bbgua self.bguastr=''.join(self.bbgua) print 'bguastr',self.bguastr for i in xrange(6): if self.bbgua[i]=='1': # self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyang,tag='pic') self.canvas.create_text(self.guax+130,95+150-30*i,text=u'▅▅▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic') else: # self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyin,tag='pic') self.canvas.create_text(self.guax+130,95+150-30*i,text=u'▅ ▅',font=('Fixdsys',17,tkFont.BOLD),tag='pic') #下面是六亲 for i in xrange(6): self.canvas.create_text(self.guax+200,100+30*i,font=self.gfont,text=gua64[self.bguastr][i],tag='pic')
class LeftNavView(Canvas): def __init__(self, controller, parent): # prev: def __init__(self, main_window, player_, left_nav): self.controller = controller self.parent = parent self.app = self.parent.app self.enabled = False def build(self): if self.enabled: self.redraw() else: self.build_left_nav_menu() self.enabled = True def build_left_nav_menu(self): app = self.app main_window = self.app.main_controller.view player = self.app.game.player # global left_nav, left_canvas, left left_nav = Frame(main_window, height=main_window.sh, width=200, background=app.conf.left_nav_background) left_nav.place(x=0, y=0) # left = LeftNav(main_window, player, left_nav) self.selected_planet = player.selected_planet if isset(player.selected_ship): self.selected_ship_name = player.selected_ship.name else: self.selected_ship_name = "" self.main_window = main_window self.selected_ship_id = 0 self.planet_images = [] self.left_canvas = Canvas(left_nav) self.left_canvas.config(background=app.conf.left_nav_background, highlightthickness=0, height=main_window.sh, width=200) self.left_canvas.place(x=0, y=0) if app.conf.debug_lines == 1: self.left_canvas.create_line(0, 0, 200, main_window.sh, fill='red') self.left_canvas.create_line(200, 0, 0, main_window.sh, fill='red') # left nav values self.logo_image = Image.open(app.conf.title_image_path) self.logo_image.thumbnail([198, 48], Image.ANTIALIAS) self.logo_image_res = ImageTk.PhotoImage(self.logo_image) self.new_planet_image = self.logo_image_res self.planet_images.append(self.new_planet_image) self.label_logo = Label(self.left_canvas, image=self.logo_image_res) self.label_logo.config(background=app.conf.left_nav_background) self.label_logo.planet_image_res = self.logo_image_res # keep a reference! self.label_logo.place(anchor='n', x=100, y=0) # Resources Set row = 0 self.resources_start_y = 55 self.resources_canvas = Canvas(self.left_canvas) self.resources_canvas.config(background=app.conf.left_nav_background, width=198, highlightthickness=0, border=0) self.resources_canvas.grid_propagate(False) self.resources_canvas.place(anchor='nw', x=0, y=self.resources_start_y) self.label_resources = Label(self.resources_canvas, text="Resources:", fg=app.conf.main_text_color) self.label_resources.config(background=app.conf.left_nav_background) self.label_resources.grid(row=row, column=0, sticky='w') row += 1 self.label_planets = Label(self.resources_canvas, text="Planets:", fg=app.conf.second_text_color) self.label_planets.config(background=app.conf.left_nav_background) self.label_planets.grid(row=row, column=0, sticky='w') self.label_planets_val = Label(self.resources_canvas, text=str(len(player.owned_planets)) , fg=app.conf.second_text_color) self.label_planets_val.config(background=app.conf.left_nav_background) self.label_planets_val.grid(row=row, column=1, sticky='e') row += 1 self.label_ships = Label(self.resources_canvas, text="Ships:", fg=app.conf.second_text_color) self.label_ships.config(background=app.conf.left_nav_background) self.label_ships.grid(row=row, column=0, sticky='w') self.label_ships_val = Label(self.resources_canvas, text=len(player.ships), fg=app.conf.second_text_color) self.label_ships_val.config(background=app.conf.left_nav_background) self.label_ships_val.grid(row=row, column=1, sticky='e') row += 1 self.label_allies = Label(self.resources_canvas, text="Allies:", fg=app.conf.second_text_color) self.label_allies.config(background=app.conf.left_nav_background) self.label_allies.grid(row=row, column=0, sticky='w') self.label_allies_val = Label(self.resources_canvas, text=len(player.allies), fg=app.conf.second_text_color) self.label_allies_val.config(background=app.conf.left_nav_background) self.label_allies_val.grid(row=row, column=1, sticky='e') row += 1 self.label_enemies = Label(self.resources_canvas, text="Enemies:", fg=app.conf.second_text_color) self.label_enemies.config(background=app.conf.left_nav_background) self.label_enemies.grid(row=row, column=0, sticky='w') self.label_enemies_val = Label(self.resources_canvas, text=len(player.enemies), fg=app.conf.second_text_color) self.label_enemies_val.config(background=app.conf.left_nav_background) self.label_enemies_val.grid(row=row, column=1, sticky='e') row += 1 self.label_separator = Label(self.resources_canvas, text="", fg=app.conf.left_nav_background, width=24) self.label_separator.config(background=app.conf.left_nav_background) self.label_separator.grid(row=row, columnspan=2, sticky='e,w') # left nav buttons self.left_buttons_start_y = main_window.sh-112 if self.left_buttons_start_y < 500: self.left_buttons_start_y = 500 self.left_buttons_canvas = Canvas(self.left_canvas) self.left_buttons_canvas.config(background=app.conf.left_nav_background, height=200, width=200, highlightthickness=0, border=0) self.left_buttons_canvas.place(anchor='n', x=100, y=self.left_buttons_start_y) self.button_next_planet = Button(self.left_buttons_canvas, text="Next Planet", padx=60 , highlightbackground=app.conf.left_nav_background) self.button_next_ship = Button(self.left_buttons_canvas, text="Next Ship" , highlightbackground=app.conf.left_nav_background) self.button_home_planet = Button(self.left_buttons_canvas, text="Home Planet" , highlightbackground=app.conf.left_nav_background) self.button_end_turn = Button(self.left_buttons_canvas, text="End Turn" , highlightbackground=app.conf.left_nav_background) self.button_next_planet.bind("<Button-1>", self.controller.button_next_planet_clicked) self.button_next_ship.bind("<Button-1>", self.controller.button_next_ship_clicked) self.button_home_planet.bind("<Button-1>", self.controller.button_home_planet_clicked) self.button_end_turn.bind("<Button-1>", self.controller.button_end_turn_clicked) self.button_next_planet.grid(row=0, column=0, sticky='w,e') self.button_next_ship.grid(row=1, column=0, sticky='w,e') self.button_home_planet.grid(row=2, column=0, sticky='w,e') self.button_end_turn.grid(row=3, column=0, sticky='w,e') # Planet Info Set row = 0 self.planet_info_start_y = self.resources_start_y + 115 self.planet_info_canvas = Canvas(self.left_canvas) self.planet_info_canvas.config(background=app.conf.left_nav_background, width=198, highlightthickness=0, border=0) self.planet_info_canvas.grid_propagate(False) self.planet_info_canvas.place(anchor='nw', x=0, y=self.planet_info_start_y) self.label_planet_info = Label(self.planet_info_canvas, text="Planet Info:", fg=app.conf.main_text_color) self.label_planet_info.config(background=app.conf.left_nav_background) self.label_planet_info.grid(row=row, column=0, sticky='w') row += 1 self.label_planet_name = Label(self.planet_info_canvas, text="Name:", fg=app.conf.second_text_color) self.label_planet_name.config(background=app.conf.left_nav_background) self.label_planet_name.grid(row=row, column=0, sticky='w') self.label_planet_name_val = Label(self.planet_info_canvas, text=str(player.selected_planet.name) , fg=app.conf.second_text_color) self.label_planet_name_val.config(background=app.conf.left_nav_background) self.label_planet_name_val.grid(row=row, column=1, sticky='e') row += 1 self.label_planet_metals = Label(self.planet_info_canvas, text="Metals:", fg=app.conf.second_text_color) self.label_planet_metals.config(background=app.conf.left_nav_background) self.label_planet_metals.grid(row=row, column=0, sticky='w') self.label_planet_metals_val = Label(self.planet_info_canvas, text=str(player.selected_planet.metals) , fg=app.conf.second_text_color) self.label_planet_metals_val.config(background=app.conf.left_nav_background) self.label_planet_metals_val.grid(row=row, column=1, sticky='e') row += 1 self.label_planet_food = Label(self.planet_info_canvas, text="Food:", fg=app.conf.second_text_color) self.label_planet_food.config(background=app.conf.left_nav_background) self.label_planet_food.grid(row=row, column=0, sticky='w') self.label_planet_food_val = Label(self.planet_info_canvas, text=str(player.selected_planet.food) , fg=app.conf.second_text_color) self.label_planet_food_val.config(background=app.conf.left_nav_background) self.label_planet_food_val.grid(row=row, column=1, sticky='e') row += 1 self.label_planet_terrain = Label(self.planet_info_canvas, text="Terrain:", fg=app.conf.second_text_color) self.label_planet_terrain.config(background=app.conf.left_nav_background) self.label_planet_terrain.grid(row=row, column=0, sticky='w') self.label_planet_terrain_val = Label(self.planet_info_canvas, text=str(get_terrain(player.selected_planet.terrain)) , fg=app.conf.second_text_color) self.label_planet_terrain_val.config(background=app.conf.left_nav_background) self.label_planet_terrain_val.grid(row=row, column=1, sticky='e') row += 1 self.label_separator_p = Label(self.planet_info_canvas, text="", fg=app.conf.left_nav_background, width=24) self.label_separator_p.config(background=app.conf.left_nav_background) self.label_separator_p.grid(row=row, columnspan=2, sticky='e,w') # ship info row = 0 self.ship_select_start_y = self.planet_info_start_y + 115 self.ship_select_canvas = Canvas(self.left_canvas) self.ship_select_canvas.config(background=app.conf.left_nav_background, width=198, highlightthickness=0, border=0) self.ship_select_canvas.grid_propagate(False) self.ship_select_canvas.place(anchor='nw', x=0, y=self.ship_select_start_y) self.label_ship_select = Label(self.ship_select_canvas, text="Select Ship:", fg=app.conf.main_text_color) self.label_ship_select.config(background=app.conf.left_nav_background) self.label_ship_select.grid(row=row, column=0, sticky='w') # future implementation # if selected_ship.name != '': if isset(self.selected_ship_name): if app.conf.debug == 1: print "Showing Selected Ship (init)" current_ship = player.get_ship(self.selected_ship_name) row += 1 self.listbox_ship = Listbox(self.ship_select_canvas, width=198 , background=app.conf.alternate_left_nav_background, borderwidth=1) self.listbox_ship.config(selectmode=SINGLE) for ship in player.ships: self.listbox_ship.insert(END, ship.name) self.listbox_ship.selection_set(self.selected_ship_id) self.listbox_ship.grid(row=row, columnspan=4, sticky='w,e') self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list) row = 0 self.ship_info_start_y = self.ship_select_start_y + 200 self.ship_info_canvas = Canvas(self.left_canvas) self.ship_info_canvas.config(background=app.conf.left_nav_background, width=198, highlightthickness=0, border=0) self.ship_info_canvas.grid_propagate(False) self.ship_info_canvas.place(anchor='nw', x=0, y=self.ship_info_start_y) self.label_ship_info = Label(self.ship_info_canvas, text="Ship Info:", fg=app.conf.main_text_color) self.label_ship_info.config(background=app.conf.left_nav_background) self.label_ship_info.grid(row=row, column=0, sticky='w') row += 1 self.label_ship_name = Label(self.ship_info_canvas, text="Name:", fg=app.conf.second_text_color) self.label_ship_name.config(background=app.conf.left_nav_background) self.label_ship_name.grid(row=row, column=0, columnspan=2, sticky='w') self.label_ship_name_val = Label(self.ship_info_canvas, text=current_ship.name , fg=app.conf.second_text_color) self.label_ship_name_val.config(background=app.conf.left_nav_background) self.label_ship_name_val.grid(row=row, column=2, columnspan=2, sticky='e') row += 1 self.label_ship_attack = Label(self.ship_info_canvas, text="Attack:", fg=app.conf.second_text_color) self.label_ship_attack.config(background=app.conf.left_nav_background) self.label_ship_attack.grid(row=row, column=0, sticky='w') self.label_ship_attack_val = Label(self.ship_info_canvas, text=current_ship.attack , fg=app.conf.second_text_color) self.label_ship_attack_val.config(background=app.conf.left_nav_background) self.label_ship_attack_val.grid(row=row, column=1, sticky='e') self.label_ship_defense = Label(self.ship_info_canvas, text="Defense:", fg=app.conf.second_text_color) self.label_ship_defense.config(background=app.conf.left_nav_background) self.label_ship_defense.grid(row=row, column=2, sticky='w') self.label_ship_defense_val = Label(self.ship_info_canvas, text=current_ship.defense , fg=app.conf.second_text_color) self.label_ship_defense_val.config(background=app.conf.left_nav_background) self.label_ship_defense_val.grid(row=row, column=3, sticky='e') row += 1 self.label_ship_storage = Label(self.ship_info_canvas, text="Storage:", fg=app.conf.second_text_color) self.label_ship_storage.config(background=app.conf.left_nav_background) self.label_ship_storage.grid(row=row, column=0, columnspan=2, sticky='w') self.label_ship_storage_val = Label(self.ship_info_canvas, text=current_ship.storage , fg=app.conf.second_text_color) self.label_ship_storage_val.config(background=app.conf.left_nav_background) self.label_ship_storage_val.grid(row=row, column=2, columnspan=2, sticky='e') row += 1 self.label_ship_seats = Label(self.ship_info_canvas, text="Seats:", fg=app.conf.second_text_color) self.label_ship_seats.config(background=app.conf.left_nav_background) self.label_ship_seats.grid(row=row, column=0, columnspan=2, sticky='w') self.label_ship_seats_val = Label(self.ship_info_canvas, text=current_ship.seats , fg=app.conf.second_text_color) self.label_ship_seats_val.config(background=app.conf.left_nav_background) self.label_ship_seats_val.grid(row=row, column=2, columnspan=2, sticky='e') row += 1 self.label_separator_s = Label(self.ship_info_canvas, text="", fg=app.conf.left_nav_background, width=24) self.label_separator_s.config(background=app.conf.left_nav_background) self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w') else: if app.conf.debug == 1: print "No Selected Ship Detected (init)" row += 1 self.listbox_ship = Listbox(self.ship_select_canvas, width=198 , background=app.conf.alternate_left_nav_background, borderwidth=1) for ship in player.ships: self.listbox_ship.insert(END, ship.name) self.listbox_ship.grid(row=row, columnspan=4, sticky='w,e') self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list) row += 1 self.label_ship_name = Label(self.ship_select_canvas, text="No Ship Selected", fg=app.conf.second_text_color) self.label_ship_name.config(background=app.conf.left_nav_background) self.label_ship_name.grid(row=row, columnspan=4, sticky='w') row += 1 self.label_separator_s = Label(self.ship_select_canvas, text="", fg=app.conf.left_nav_background, width=24) self.label_separator_s.config(background=app.conf.left_nav_background) self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w') if app.conf.debug == 1: print "CreatedLine:", 0, " ", 0, " ", main_window.sw-200, " ", main_window.sh-200 print "CreatedLine:", main_window.sw-200, " ", 0, " ", 0, " ", main_window.sh-200 print "CurrWin0:", convert_coords_x(main_window, 0), convert_coords_y(main_window, 0) if app.conf.debug == 1: print "Displayed: left_nav,", main_window.sh, ",200" def poll_ship_list(self, event): w = event.widget index = int(w.curselection()[0]) new_ship_name = w.get(index) if isset(self.selected_ship_name): if self.selected_ship_name == "": if new_ship_name != self.selected_ship_name: self.ship_selction_has_changed(new_ship_name) self.selected_ship_name = new_ship_name self.selected_ship_id = w.curselection() if app.conf.debug == 1: print "SelectedShip:", self.selected_ship_name self.redraw(self.main_window, self.player) else: self.selected_ship_name = new_ship_name self.selected_ship_id = w.curselection() self.app.debug(("SelectedShip:", self.selected_ship_name)) self.redraw() def redraw(self): app = self.app main_window = app.main_controller.view player = app.game.player self.player = player app.debug("Redrawing Left Nav") self.label_logo.place(anchor='n', x=100, y=0) self.resources_canvas.config(background=app.conf.left_nav_background, height=main_window.sh-self.resources_start_y-202, width=198, highlightthickness=0, border=0) self.resources_canvas.place(anchor='nw', x=0, y=self.resources_start_y) row = 0 self.label_resources.grid(row=row, column=0, sticky='w') row += 1 self.label_planets.grid(row=row, column=0, sticky='w') self.label_planets_val.config(text=str(len(player.owned_planets))) self.label_planets_val.grid(row=row, column=1, sticky='e') row += 1 self.label_ships.grid(row=row, column=0, sticky='w') self.label_ships_val.config(text=len(player.ships)) self.label_ships_val.grid(row=row, column=1, sticky='e') row += 1 self.label_allies.grid(row=row, column=0, sticky='w') self.label_allies_val.config(text=len(player.allies)) self.label_allies_val.grid(row=row, column=1, sticky='e') row += 1 self.label_enemies.grid(row=row, column=0, sticky='w') self.label_enemies_val.config(text=len(player.enemies)) self.label_enemies_val.grid(row=row, column=1, sticky='e') row += 1 self.label_separator.grid(row=row, columnspan=2, sticky='e,w') # left nav buttons self.left_buttons_start_y = main_window.sh-112 if self.left_buttons_start_y < 500: self.left_buttons_start_y = 500 self.left_buttons_canvas.place(anchor='n', x=100, y=self.left_buttons_start_y) self.button_next_planet.grid(row=0, column=0, sticky='w,e') self.button_next_ship.grid(row=1, column=0, sticky='w,e') self.button_home_planet.grid(row=2, column=0, sticky='w,e') self.button_end_turn.grid(row=3, column=0, sticky='w,e') app.debug(("Left Buttons Start Y:", self.left_buttons_start_y)) # Planet Info Set row = 0 self.planet_info_start_y = self.resources_start_y + 115 self.planet_info_canvas.place(anchor='nw', x=0, y=self.planet_info_start_y) self.label_planet_info.grid(row=row, column=0, sticky='w') row += 1 self.label_planet_name.grid(row=row, column=0, sticky='w') self.label_planet_name_val.config(text=str(player.selected_planet.name)) self.label_planet_name_val.grid(row=row, column=1, sticky='e') row += 1 self.label_planet_metals.grid(row=row, column=0, sticky='w') self.label_planet_metals_val.config(text=str(player.selected_planet.metals)) self.label_planet_metals_val.grid(row=row, column=1, sticky='e') row += 1 self.label_planet_food.grid(row=row, column=0, sticky='w') self.label_planet_food_val.config(text=str(player.selected_planet.food)) self.label_planet_food_val.grid(row=row, column=1, sticky='e') row += 1 self.label_planet_terrain.grid(row=row, column=0, sticky='w') self.label_planet_terrain_val.config(text=str(get_terrain(player.selected_planet.terrain))) self.label_planet_terrain_val.grid(row=row, column=1, sticky='e') row += 1 self.label_separator_p.grid(row=row, columnspan=2, sticky='e,w') # prep for ship section if isset(self.ship_select_canvas): self.ship_select_canvas.destroy() # ship info row = 0 self.ship_select_start_y = self.planet_info_start_y + 115 self.ship_select_canvas = Canvas(self.left_canvas) self.ship_select_canvas.config(background=app.conf.left_nav_background, width=198, highlightthickness=0, border=0) self.ship_select_canvas.grid_propagate(False) self.ship_select_canvas.place(anchor='nw', x=0, y=self.ship_select_start_y) self.label_ship_select = Label(self.ship_select_canvas, text="Select Ship:", fg=app.conf.main_text_color) self.label_ship_select.config(background=app.conf.left_nav_background) self.label_ship_select.grid(row=row, column=0, sticky='w') # future implementation # if selected_ship.name != '': if self.selected_ship_name != "": app.debug("Showing Selected Ship (redraw)") current_ship = player.get_ship(self.selected_ship_name) row += 1 self.listbox_ship = Listbox(self.ship_select_canvas, width=198 , background=app.conf.alternate_left_nav_background, borderwidth=1) self.listbox_ship.config(selectmode=SINGLE) for ship in player.ships: self.listbox_ship.insert(END, ship.name) self.listbox_ship.selection_set(self.selected_ship_id) self.listbox_ship.grid(row=row, columnspan=4, sticky='w,e') self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list) row = 0 self.ship_info_start_y = self.ship_select_start_y + 200 self.ship_info_canvas = Canvas(self.left_canvas) self.ship_info_canvas.config(background=app.conf.left_nav_background, width=198, highlightthickness=0, border=0) self.ship_info_canvas.grid_propagate(False) self.ship_info_canvas.place(anchor='nw', x=0, y=self.ship_info_start_y) self.label_ship_info = Label(self.ship_info_canvas, text="Ship Info:", fg=app.conf.main_text_color) self.label_ship_info.config(background=app.conf.left_nav_background) self.label_ship_info.grid(row=row, column=0, sticky='w') row += 1 self.label_ship_name = Label(self.ship_info_canvas, text="Name:", fg=app.conf.second_text_color) self.label_ship_name.config(background=app.conf.left_nav_background) self.label_ship_name.grid(row=row, column=0, columnspan=2, sticky='w') self.label_ship_name_val = Label(self.ship_info_canvas, text=current_ship.name , fg=app.conf.second_text_color) self.label_ship_name_val.config(background=app.conf.left_nav_background) self.label_ship_name_val.grid(row=row, column=2, columnspan=2, sticky='e') row += 1 self.label_ship_attack = Label(self.ship_info_canvas, text="Attack:", fg=app.conf.second_text_color) self.label_ship_attack.config(background=app.conf.left_nav_background) self.label_ship_attack.grid(row=row, column=0, sticky='w') self.label_ship_attack_val = Label(self.ship_info_canvas, text=current_ship.attack , fg=app.conf.second_text_color) self.label_ship_attack_val.config(background=app.conf.left_nav_background) self.label_ship_attack_val.grid(row=row, column=1, sticky='e') self.label_ship_defense = Label(self.ship_info_canvas, text="Defense:", fg=app.conf.second_text_color) self.label_ship_defense.config(background=app.conf.left_nav_background) self.label_ship_defense.grid(row=row, column=2, sticky='w') self.label_ship_defense_val = Label(self.ship_info_canvas, text=current_ship.defense , fg=app.conf.second_text_color) self.label_ship_defense_val.config(background=app.conf.left_nav_background) self.label_ship_defense_val.grid(row=row, column=3, sticky='e') row += 1 self.label_ship_storage = Label(self.ship_info_canvas, text="Storage:", fg=app.conf.second_text_color) self.label_ship_storage.config(background=app.conf.left_nav_background) self.label_ship_storage.grid(row=row, column=0, columnspan=2, sticky='w') self.label_ship_storage_val = Label(self.ship_info_canvas, text=current_ship.storage , fg=app.conf.second_text_color) self.label_ship_storage_val.config(background=app.conf.left_nav_background) self.label_ship_storage_val.grid(row=row, column=2, columnspan=2, sticky='e') row += 1 self.label_ship_seats = Label(self.ship_info_canvas, text="Seats:", fg=app.conf.second_text_color) self.label_ship_seats.config(background=app.conf.left_nav_background) self.label_ship_seats.grid(row=row, column=0, columnspan=2, sticky='w') self.label_ship_seats_val = Label(self.ship_info_canvas, text=current_ship.seats , fg=app.conf.second_text_color) self.label_ship_seats_val.config(background=app.conf.left_nav_background) self.label_ship_seats_val.grid(row=row, column=2, columnspan=2, sticky='e') row += 1 self.label_separator_s = Label(self.ship_info_canvas, text="", fg=app.conf.left_nav_background, width=24) self.label_separator_s.config(background=app.conf.left_nav_background) self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w') else: app.debug("No Selected Ship Detected (redraw)") row += 1 self.listbox_ship = Listbox(self.ship_select_canvas, width=198 , background=app.conf.alternate_left_nav_background, borderwidth=1) for ship in player.ships: self.listbox_ship.insert(END, ship.name) self.listbox_ship.grid(row=row, columnspan=2, sticky='w,e') self.listbox_ship.bind('<<ListboxSelect>>', self.poll_ship_list) row += 1 self.label_ship_name = Label(self.ship_select_canvas, text="No Ship Selected", fg=app.conf.second_text_color) self.label_ship_name.config(background=app.conf.left_nav_background) self.label_ship_name.grid(row=row, columnspan=2, sticky='w') row += 1 self.label_separator_s = Label(self.ship_select_canvas, text="", fg=app.conf.left_nav_background, width=24) self.label_separator_s.config(background=app.conf.left_nav_background) self.label_separator_s.grid(row=row, columnspan=4, sticky='e,w')
class histogramWidget: BACKGROUND = "#222222" EDGE_HISTOGRAM_COLOR = "#999999" NODE_HISTOGRAM_COLOR = "#555555" TOOLTIP_COLOR="#FFFF55" PADDING = 8 CENTER_WIDTH = 1 CENTER_COLOR = "#444444" ZERO_GAP = 1 UPDATE_WIDTH = 9 UPDATE_COLOR = "#FFFFFF" HANDLE_WIDTH = 5 HANDLE_COLOR = "#FFFFFF" HANDLE_LENGTH = (HEIGHT-2*PADDING) TICK_COLOR = "#FFFFFF" TICK_WIDTH = 10 TICK_FACTOR = 2 LOG_BASE = 10.0 def __init__(self, parent, x, y, width, height, data, logScale=False, callback=None): self.canvas = Canvas(parent,background=histogramWidget.BACKGROUND, highlightbackground=histogramWidget.BACKGROUND,width=width,height=height) self.canvas.place(x=x,y=y,width=width,height=height,bordermode="inside") self.logScale = logScale self.callback = callback self.edgeBars = [] self.nodeBars = [] self.binValues = [] self.numBins = len(data) - 1 self.currentBin = self.numBins # start the slider at the highest bin edgeRange = 0.0 nodeRange = 0.0 for values in data.itervalues(): if values[0] > edgeRange: edgeRange = values[0] if values[1] > nodeRange: nodeRange = values[1] edgeRange = float(edgeRange) # ensure that it will yield floats when used in calculations... nodeRange = float(nodeRange) if logScale: edgeRange = math.log(edgeRange,histogramWidget.LOG_BASE) nodeRange = math.log(nodeRange,histogramWidget.LOG_BASE) # calculate the center line - but don't draw it yet self.center_x = histogramWidget.PADDING if self.logScale: self.center_x += histogramWidget.TICK_WIDTH+histogramWidget.PADDING self.center_y = height/2 self.center_x2 = width-histogramWidget.PADDING self.center_y2 = self.center_y + histogramWidget.CENTER_WIDTH # draw the histograms with background-colored baseline rectangles (these allow tooltips to work on very short bars with little area) self.bar_interval = float(self.center_x2 - self.center_x) / (self.numBins+1) bar_x = self.center_x edge_y2 = self.center_y-histogramWidget.PADDING edge_space = edge_y2-histogramWidget.PADDING node_y = self.center_y2+histogramWidget.PADDING node_space = (height-node_y)-histogramWidget.PADDING thresholds = sorted(data.iterkeys()) for threshold in thresholds: self.binValues.append(threshold) edgeWeight = data[threshold][0] nodeWeight = data[threshold][1] if logScale: if edgeWeight > 0: edgeWeight = math.log(edgeWeight,histogramWidget.LOG_BASE) else: edgeWeight = 0 if nodeWeight > 0: nodeWeight = math.log(nodeWeight,histogramWidget.LOG_BASE) else: nodeWeight = 0 bar_x2 = bar_x + self.bar_interval edge_y = histogramWidget.PADDING + int(edge_space*(1.0-edgeWeight/edgeRange)) edge = self.canvas.create_rectangle(bar_x,edge_y,bar_x2,edge_y2,fill=histogramWidget.EDGE_HISTOGRAM_COLOR,width=0) baseline = self.canvas.create_rectangle(bar_x,edge_y2+histogramWidget.ZERO_GAP,bar_x2,edge_y2+histogramWidget.PADDING,fill=histogramWidget.BACKGROUND,width=0) self.canvas.addtag_withtag("Threshold: %f" % threshold,edge) self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],edge) self.canvas.tag_bind(edge,"<Enter>",self.updateToolTip) self.canvas.tag_bind(edge,"<Leave>",self.updateToolTip) self.edgeBars.append(edge) self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline) self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],baseline) self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip) self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip) node_y2 = node_y + int(node_space*(nodeWeight/nodeRange)) node = self.canvas.create_rectangle(bar_x,node_y,bar_x2,node_y2,fill=histogramWidget.NODE_HISTOGRAM_COLOR,width=0) baseline = self.canvas.create_rectangle(bar_x,node_y-histogramWidget.PADDING,bar_x2,node_y-histogramWidget.ZERO_GAP,fill=histogramWidget.BACKGROUND,width=0) self.canvas.addtag_withtag("Threshold: %f" % threshold,node) self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],node) self.canvas.tag_bind(node,"<Enter>",self.updateToolTip) self.canvas.tag_bind(node,"<Leave>",self.updateToolTip) self.nodeBars.append(node) self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline) self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],baseline) self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip) self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip) bar_x = bar_x2 # now draw the center line self.centerLine = self.canvas.create_rectangle(self.center_x,self.center_y,self.center_x2,self.center_y2,fill=histogramWidget.CENTER_COLOR,width=0) # draw the tick marks if logarithmic if self.logScale: tick_x = histogramWidget.PADDING tick_x2 = histogramWidget.PADDING+histogramWidget.TICK_WIDTH start_y = edge_y2 end_y = histogramWidget.PADDING dist = start_y-end_y while dist > 1: dist /= histogramWidget.TICK_FACTOR self.canvas.create_rectangle(tick_x,end_y+dist-1,tick_x2,end_y+dist,fill=histogramWidget.TICK_COLOR,width=0) start_y = node_y end_y = height-histogramWidget.PADDING dist = end_y-start_y while dist > 1: dist /= histogramWidget.TICK_FACTOR self.canvas.create_rectangle(tick_x,end_y-dist,tick_x2,end_y-dist+1,fill=histogramWidget.TICK_COLOR,width=0) # draw the update bar bar_x = self.currentBin*self.bar_interval + self.center_x bar_x2 = self.center_x2 bar_y = self.center_y-histogramWidget.UPDATE_WIDTH/2 bar_y2 = bar_y+histogramWidget.UPDATE_WIDTH self.updateBar = self.canvas.create_rectangle(bar_x,bar_y,bar_x2,bar_y2,fill=histogramWidget.UPDATE_COLOR,width=0) # draw the handle handle_x = self.currentBin*self.bar_interval-histogramWidget.HANDLE_WIDTH/2+self.center_x handle_x2 = handle_x+histogramWidget.HANDLE_WIDTH handle_y = self.center_y-histogramWidget.HANDLE_LENGTH/2 handle_y2 = handle_y+histogramWidget.HANDLE_LENGTH self.handleBar = self.canvas.create_rectangle(handle_x,handle_y,handle_x2,handle_y2,fill=histogramWidget.HANDLE_COLOR,width=0) self.canvas.tag_bind(self.handleBar, "<Button-1>",self.adjustHandle) self.canvas.tag_bind(self.handleBar, "<B1-Motion>",self.adjustHandle) self.canvas.tag_bind(self.handleBar, "<ButtonRelease-1>",self.adjustHandle) parent.bind("<Left>",lambda e: self.nudgeHandle(e,-1)) parent.bind("<Right>",lambda e: self.nudgeHandle(e,1)) # init the tooltip as nothing self.toolTipBox = self.canvas.create_rectangle(0,0,0,0,state="hidden",fill=histogramWidget.TOOLTIP_COLOR,width=0) self.toolTip = self.canvas.create_text(0,0,state="hidden",anchor="nw") self.canvas.bind("<Enter>",self.updateToolTip) self.canvas.bind("<Leave>",self.updateToolTip) def adjustHandle(self, event): newBin = int(self.numBins*(event.x-self.center_x)/float(self.center_x2-self.center_x)+0.5) if newBin == self.currentBin or newBin < 0 or newBin > self.numBins: return self.canvas.move(self.handleBar,(newBin-self.currentBin)*self.bar_interval,0) self.currentBin = newBin if self.callback != None: self.callback(self.binValues[newBin]) def nudgeHandle(self, event, distance): temp = self.currentBin+distance if temp < 0 or temp > self.numBins: return self.canvas.move(self.handleBar,distance*self.bar_interval,0) self.currentBin += distance if self.callback != None: self.callback(self.binValues[self.currentBin]) def update(self, currentBins): currentBar = self.canvas.coords(self.updateBar) self.canvas.coords(self.updateBar,currentBins*self.bar_interval+self.center_x,currentBar[1],currentBar[2],currentBar[3]) def updateToolTip(self, event): allTags = self.canvas.gettags(self.canvas.find_overlapping(event.x,event.y,event.x+1,event.y+1)) if len(allTags) == 0: self.canvas.itemconfig(self.toolTipBox,state="hidden") self.canvas.itemconfig(self.toolTip,state="hidden") return outText = "" for t in allTags: if t == "current": continue outText += t + "\n" outText = outText[:-1] # strip the last return self.canvas.coords(self.toolTip,event.x+20,event.y) self.canvas.itemconfig(self.toolTip,state="normal",text=outText,anchor="nw") # correct if our tooltip is off screen textBounds = self.canvas.bbox(self.toolTip) if textBounds[2] >= WIDTH-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="ne") self.canvas.coords(self.toolTip,event.x-20,event.y) if textBounds[3] >= HEIGHT-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="se") elif textBounds[3] >= HEIGHT-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="sw") # draw the box behind it self.canvas.coords(self.toolTipBox,self.canvas.bbox(self.toolTip)) self.canvas.itemconfig(self.toolTipBox, state="normal")
class PigChaseHumanAgent(GuiAgent): def __init__(self, name, environment, keymap, max_episodes, max_actions, visualizer, quit): self._max_episodes = max_episodes self._max_actions = max_actions self._action_taken = 0 self._episode = 1 self._scores = [] self._rewards = [] self._episode_has_ended = False self._episode_has_started = False self._quit_event = quit super(PigChaseHumanAgent, self).__init__(name, environment, keymap, visualizer=visualizer) def _build_layout(self, root): # Left part of the GUI, first person view self._first_person_header = ttk.Label(root, text='First Person View', font=(None, 14, 'bold')) \ .grid(row=0, column=0) self._first_person_view = ttk.Label(root) self._first_person_view.grid(row=1, column=0, rowspan=10) # Right part, top self._first_person_header = ttk.Label(root, text='Symbolic View', font=(None, 14, 'bold')) \ .grid(row=0, column=1) self._symbolic_view = Canvas(root) self._symbolic_view.configure(width=ENV_BOARD_SHAPE[0]*CELL_WIDTH, height=ENV_BOARD_SHAPE[1]*CELL_WIDTH) self._symbolic_view.grid(row=1, column=1) # Bottom information self._information_panel = ttk.Label(root, text='Game stats', font=(None, 14, 'bold')) self._current_episode_lbl = ttk.Label(root, text='Episode: 0', font=(None, 12)) self._cum_reward_lbl = ttk.Label(root, text='Score: 0', font=(None, 12, 'bold')) self._last_action_lbl = ttk.Label(root, text='Previous action: None', font=(None, 12)) self._action_done_lbl = ttk.Label(root, text='Actions taken: 0', font=(None, 12)) self._action_remaining_lbl = ttk.Label(root, text='Actions remaining: 0', font=(None, 12)) self._information_panel.grid(row=2, column=1) self._current_episode_lbl.grid(row=3, column=1, sticky=W, padx=20) self._cum_reward_lbl.grid(row=4, column=1, sticky=W, padx=20) self._last_action_lbl.grid(row=5, column=1, sticky=W, padx=20) self._action_done_lbl.grid(row=6, column=1, sticky=W, padx=20) self._action_remaining_lbl.grid(row=7, column=1, sticky=W, padx=20) self._overlay = None # Main rendering callback self._pressed_binding = root.bind('<Key>', self._on_key_pressed) self._user_pressed_enter = False # UI Update callback root.after(self._tick, self._poll_frame) root.after(1000, self._on_episode_start) root.focus() def _draw_arrow(self, yaw, x, y, cell_width, colour): if yaw == 0.: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .5) * cell_width, (y + .4) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y1, x2, y3, x3, y1, x2, y2, fill=colour) elif yaw == 90.: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .6) * cell_width, (y + .5) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y2, x3, y1, x2, y2, x3, y3, fill=colour) elif yaw == 180.: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .5) * cell_width, (y + .6) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y3, x2, y1, x3, y3, x2, y2, fill=colour) else: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .4) * cell_width, (y + .5) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y3, x2, y2, x1, y1, x3, y2, fill=colour) def _poll_frame(self): """ Main callback for UI rendering. Called at regular intervals. The method will ask the environment to provide a frame if available (not None). :return: """ cell_width = CELL_WIDTH circle_radius = 10 # are we done? if self._env.done and not self._episode_has_ended: self._on_episode_end() # build symbolic view board, _ = self._env._internal_symbolic_builder.build(self._env) if board is not None: board = board.T self._symbolic_view.delete('all') # Remove all previous items from Tkinter tracking width, height = board.shape for x in range(width): for y in range(height): cell_contents = str.split(str(board[x][y]), '/') for block in cell_contents: if block == 'sand': self._symbolic_view.create_rectangle(x * cell_width, y * cell_width, (x + 1) * cell_width, (y + 1) * cell_width, outline="black", fill="orange", tags="square") elif block == 'grass': self._symbolic_view.create_rectangle(x * cell_width, y * cell_width, (x + 1) * cell_width, (y + 1) * cell_width, outline="black", fill="lawn green", tags="square") elif block == 'lapis_block': self._symbolic_view.create_rectangle(x * cell_width, y * cell_width, (x + 1) * cell_width, (y + 1) * cell_width, outline="black", fill="black", tags="square") elif block == ENV_TARGET_NAMES[0]: self._symbolic_view.create_oval((x + .5) * cell_width - circle_radius, (y + .5) * cell_width - circle_radius, (x + .5) * cell_width + circle_radius, (y + .5) * cell_width + circle_radius, fill='pink') elif block == self.name: yaw = self._env._world_obs['Yaw'] % 360 self._draw_arrow(yaw, x, y, cell_width, 'red') elif block == ENV_AGENT_NAMES[0]: # Get yaw of other agent: entities = self._env._world_obs[ENV_ENTITIES] other_agent = list( map(Entity.create, filter(lambda e: e['name'] == ENV_AGENT_NAMES[0], entities))) if len(other_agent) == 1: other_agent = other_agent.pop() yaw = other_agent.yaw % 360 self._draw_arrow(yaw, x, y, cell_width, 'blue') # display the most recent frame frame = self._env.frame if frame is not None: from PIL import ImageTk self._first_person_view.image = ImageTk.PhotoImage(image=frame) self._first_person_view.configure(image=self._first_person_view.image) self._first_person_view.update() self._first_person_view.update() # process game state (e.g., has the episode started?) if self._episode_has_started and time.time() - self._episode_start_time < 3: if not hasattr(self, "_init_overlay") or not self._init_overlay: self._create_overlay() self._init_overlay.delete("all") self._init_overlay.create_rectangle( 10, 10, 590, 290, fill="white", outline="red", width="5") self._init_overlay.create_text( 300, 80, text="Get ready to catch the pig!", font=('Helvetica', '18')) self._init_overlay.create_text( 300, 140, text=str(3 - int(time.time() - self._episode_start_time)), font=('Helvetica', '18'), fill="red") self._init_overlay.create_text( 300, 220, width=460, text="How to play: \nUse the left/right arrow keys to turn, " "forward/back to move. The pig is caught if it is " "cornered without a free block to escape to.", font=('Helvetica', '14'), fill="black") self._root.update() elif self._episode_has_ended: if not hasattr(self, "_init_overlay") or not self._init_overlay: self._create_overlay() self._init_overlay.delete("all") self._init_overlay.create_rectangle( 10, 10, 590, 290, fill="white", outline="red", width="5") self._init_overlay.create_text( 300, 80, text='Finished episode %d of %d' % (self._episode, self._max_episodes), font=('Helvetica', '18')) self._init_overlay.create_text( 300, 120, text='Score: %d' % sum(self._rewards), font=('Helvetica', '18')) if self._episode > 1: self._init_overlay.create_text( 300, 160, text='Average over %d episodes: %.2f' % (self._episode, np.mean(self._scores)), font=('Helvetica', '18')) self._init_overlay.create_text( 300, 220, width=360, text="Press RETURN to start the next episode, ESC to exit.", font=('Helvetica', '14'), fill="black") self._root.update() elif hasattr(self, "_init_overlay") and self._init_overlay: self._destroy_overlay() # trigger the next update self._root.after(self._tick, self._poll_frame) def _create_overlay(self): self._init_overlay = Canvas(self._root, borderwidth=0, highlightthickness=0, width=600, height=300, bg="gray") self._init_overlay.place(relx=0.5, rely=0.5, anchor='center') def _destroy_overlay(self): self._init_overlay.destroy() self._init_overlay = None def _on_key_pressed(self, e): """ Main callback for keyboard events :param e: :return: """ if e.keysym == 'Escape': self._quit() if e.keysym == 'Return' and self._episode_has_ended: if self._episode >= self._max_episodes: self._quit() # start the next episode self._action_taken = 0 self._rewards = [] self._episode += 1 self._env.reset() self._on_episode_start() print('Starting episode %d' % self._episode) if self._episode_has_started and time.time() - self._episode_start_time >= 3: if e.keysym in self._keymap: mapped_action = self._keymap.index(e.keysym) _, reward, done = self._env.do(mapped_action) self._action_taken += 1 self._rewards.append(reward) self._on_experiment_updated(mapped_action, reward, done) def _on_episode_start(self): self._episode_has_ended = False self._episode_has_started = True self._episode_start_time = time.time() self._on_experiment_updated(None, 0, self._env.done) def _on_episode_end(self): self._episode_has_started = False self._episode_has_ended = True self._scores.append(sum(self._rewards)) self.visualize(self._episode, 'Reward', sum(self._rewards)) def _on_experiment_updated(self, action, reward, is_done): self._current_episode_lbl.config(text='Episode: %d' % self._episode) self._cum_reward_lbl.config(text='Score: %d' % sum(self._rewards)) self._last_action_lbl.config(text='Previous action: %s' % action) self._action_done_lbl.config(text='Actions taken: {0}'.format(self._action_taken)) self._action_remaining_lbl.config(text='Actions remaining: %d' % (self._max_actions - self._action_taken)) self._first_person_view.update() def _quit(self): self._quit_event.set() self._root.quit() sys.exit()
def screen_draw(): global window, canvas_frame, canvas_play, canvas_play1, canvas_play2, canvas_future, level, point, max_point, canvas_pause level = 1 point = 0 max_point = 0 canvas_frame = Canvas(window) #,bg='red') canvas_frame.place(x=0, y=0, relwidth=1.0, relheight=1.0) global frame1, frame2 frame1 = Frame(window) frame2 = Frame(window) frame1.place(x=0, y=0, width=300, height=600) frame2.place(x=0, y=0, width=300, height=600) canvas_play1 = Canvas(frame1, bg='#000000') canvas_play1.place(x=0, y=0, width=300, height=600) for x in range(1, 10): for y in range(1, 20): canvas_play1.create_line(30 * x, 0, 30 * x, 600, fill='#111111') #,tag='play') canvas_play1.create_line(0, 30 * y, 300, 30 * y, fill='#111111') #,tag='play') canvas_play2 = Canvas(frame2, bg='#000000') canvas_play2.place(x=0, y=0, width=300, height=600) for x in range(1, 10): for y in range(1, 20): canvas_play2.create_line(30 * x, 0, 30 * x, 600, fill='#111111') canvas_play2.create_line(0, 30 * y, 300, 30 * y, fill='#111111') canvas_play = frame2 canvas_frame.create_text(370, 200, font=('Purisa', 24), text='Level', anchor='n') canvas_frame.create_text(370, 336, font=('Purisa', 24), text='Point', anchor='n') canvas_frame.create_text(370, 436, font=('Purisa', 24), text='Max', anchor='n') canvas_frame.create_text(370, 270, text=str(level), font=('', 24), fill='#0000ff', tag='level') canvas_frame.create_text(370, 400, text=str(point), font=('', 24), fill='#0000ff', tag='point') canvas_frame.create_text(370, 500, text=str(max_point), font=('', 24), fill='#ff0000', tag='max') canvas_future = Canvas(window) #,bg='#0000ff') canvas_future.place(x=310, y=10, width=120, height=120) canvas_pause = Canvas(canvas_frame) #,bg='yellow') canvas_pause.place(x=345, y=540, width=50, height=50) draw_play() canvas_pause.bind('<ButtonPress-1>', event_pause)
# plot a point # import mathplotlib.pyplot as plt from Tkinter import Tk, Canvas, PhotoImage, Label if __name__ == '__main__': root = Tk() w = Label(root, text="Draw a Point on Canvas in Python") canvas= Canvas(root, width=250, height=250, bg='#E2E2E2') canvas.place(x=20,y=26,height=250,width=250) #img= PhotoImage(width=200, height=200) # img.putpixel(1,2) w.pack() canvas.pack() root.mainloop()
class Window(Frame): def __init__(self, parent): Frame.__init__(self, parent, background="white") self.parent = parent self.initUI() home='/home/little_light/Desktop/workspace/python/data/GSTRB' modelFile=home+'/model/demo2.pkl' input_var = T.tensor4('inputs',dtype=theano.config.floatX) target_var = T.ivector('targets') network,loss,params=build_2f(input_var,target_var,regularW=0.0001) pvals=cPickle.load(open(modelFile)) [p.set_value(pval) for (p, pval) in zip(lasagne.layers.get_all_params(network), pvals)] predict=lasagne.layers.get_output(network, deterministic=True) input=lasagne.layers.get_all_layers(network)[0].input_var #lasagne.layers.input.input self.predict_fn=theano.function(inputs=[input],outputs=predict) def initUI(self): self.parent.title("Simple") self.pack(fill=BOTH, expand=1) self.tbImg=Entry(self.parent,width=50) self.tbImg.place(x=10,y=10) self.bLoad=Button(master=self,text="Load", command = self.load) self.bLoad.pack() self.bLoad.place(x=10,y=30) self.canvas = Canvas(self, width=400, height=400) self.canvas.pack() fileName='/home/little_light/Desktop/workspace/python/data/GSTRB/Final_Training/Images/00000/00004_00029.ppm' img = ImageTk.PhotoImage(Image.open(fileName)) self.canvas.image=img self.image_on_canvas=self.canvas.create_image(0,0,image=img,anchor='nw') self.canvas.place(x=10,y=60) self.v = StringVar() self.label=Label(master=self,textvariable=self.v) self.v.set("Target label:") self.label.place(x=10,y=470) def load(self): print "load" fileName=self.tbImg.get() img = ImageTk.PhotoImage(Image.open(fileName)) self.canvas.image=img #self.canvas.create_image(0,0,image=img) self.canvas.itemconfig(self.image_on_canvas, image =self.canvas.image) img=Image.open(fileName) img.load() img2=img.resize((32,32)) img2.load() data = np.asarray(img2, dtype="int32") mean=86.2111433696 data=np.transpose(data,(2,0,1)) data=np.asarray((data-mean)/256.0,dtype=theano.config.floatX) data2=np.zeros((1,3,32,32),dtype=theano.config.floatX) data2[0]=data data=data2 print np.argmax(self.predict_fn(data)[0]) self.v.set("Target label:"+str(np.argmax(self.predict_fn(data)[0])))
st_lepptcb.set(0) chooseleppt() lyes = Checkbutton(frame1, text="Choose number of charged leptons", bg="LightCyan2", variable=st_lepcb, onvalue=1, offvalue=0, command=chooseNlep) lyes.grid(row=0, column=0, sticky=W) #Define and show checkbox #Question mark to be next to "choose lep" option qlep = Canvas(frame1, width=16, height=16) qlep.place(relx=0.61, rely=0.001, anchor=N) qlep.create_image(8, 8, image=questionmark) infolep = Message(frame1, text="""The number of charged leptons in the event""", bg="White", aspect=300) #Information message def on_enterlep(event): """shows an explanation if cursor placed over question mark""" infolep.place(relx=0.625, rely=0.0155, anchor=NW) def on_leavelep(event): """hides explanation if cursor not placed over question mark""" infolep.place_forget()
class MSTM_studio: splash_time = 0.5 # time to show splash window, seconds def __init__(self, top=None): '''This class configures and populates the toplevel window. top is the toplevel containing window.''' top.withdraw() time_start = time.time() splash = sup.SplashWindow(top) self.style = ttk.Style() if sys.platform == 'win32': self.style.theme_use('winnative') self.style.configure('.', font='TkDefaultFont') #~ top.geometry('838x455+364+117') top.geometry('850x440') top.title('MSTM studio') #~ top.configure(highlightcolor='black') self.load_images() self.root_panedwin = ttk.Panedwindow(top, orient='horizontal') self.root_panedwin.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0) self.root_panedwin.configure(width=200) self.left_frame = ttk.Frame(width=220.0) self.root_panedwin.add(self.left_frame) #~ self.middle_frame = ttk.Labelframe(width=350, text='View') self.middle_frame = ttk.Frame(width=350) self.root_panedwin.add(self.middle_frame) self.right_frame = ttk.Frame() self.root_panedwin.add(self.right_frame) self.__funcid0 = self.root_panedwin.bind('<Map>', self.__adjust_sash0) self.left_panedwin = ttk.Panedwindow(self.left_frame, orient='vertical') self.left_panedwin.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0) self.left_panedwin.configure(width=200) self.materials_frame = ttk.Labelframe(height=105, text='Materials') self.left_panedwin.add(self.materials_frame) self.spheres_frame = ttk.Labelframe(text='Spheres') self.left_panedwin.add(self.spheres_frame) self.__funcid1 = self.left_panedwin.bind('<Map>', self.__adjust_sash1) self.style.configure('Treeview.Heading', font='TkDefaultFont') self.stvMaterial = ScrolledTreeView(self.materials_frame) self.stvMaterial.place(relx=0.0, y=30, relheight=0.8, relwidth=1.0) self.configure_stvMaterial() self.stvMaterial.bind('<Double-1>', sup.btChangeMatColClick) self.btAddMat = ttk.Button(self.materials_frame, command=sup.btAddMatClick, text='A', image=self.imAdd) self.btAddMat.place(x=5, y=0, height=25, width=25) self.btLoadMat = ttk.Button(self.materials_frame, command=sup.btLoadMatClick, text='L', image=self.imLoad) self.btLoadMat.place(x=30, y=0, height=25, width=25) self.btPlotMat = ttk.Button(self.materials_frame, command=sup.btPlotMatClick, text='P', image=self.imPlot) self.btPlotMat.place(x=55, y=0, height=25, width=25) self.btDelMat = ttk.Button(self.materials_frame, command=sup.btDelMatClick, text='D', image=self.imDelete) self.btDelMat.place(relx=1, x=-30, rely=0, height=25, width=25) self.stvSpheres = ScrolledTreeView(self.spheres_frame) self.stvSpheres.place(relx=0.0, y=30, relheight=0.85, relwidth=1.0) self.configure_stvSpheres() self.stvSpheres.bind('<Double-1>', sup.btEditSphClick) self.btAddSph = ttk.Button(self.spheres_frame, command=sup.btAddSphClick, text='A', image=self.imAdd) self.btAddSph.place(x=5, y=0, height=25, width=25) self.btEditSph = ttk.Button(self.spheres_frame, command=sup.btEditSphClick, text='E', image=self.imEdit) self.btEditSph.place(x=30, y=0, height=25, width=25) self.btPlotSph = ttk.Button(self.spheres_frame, command=sup.btPlotSphClick, text='R', image=self.imRefresh) self.btPlotSph.place(x=55, y=0, height=25, width=25) self.lbEnvMat = ttk.Label(self.spheres_frame, text='Matrix') self.lbEnvMat.place(relx=0.45, y=-5) self.cbEnvMat = ttk.Combobox(self.spheres_frame) self.cbEnvMat.place(relx=0.45, y=10, width=55) self.btDelSph = ttk.Button(self.spheres_frame, command=sup.btDelSphClick, text='D', image=self.imDelete) self.btDelSph.place(relx=1.0, y=0, x=-30, height=25, width=25) self.middle_panedwin = ttk.Panedwindow(self.middle_frame, orient='vertical') self.middle_panedwin.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0) #~ self.middle_panedwin.configure(relwidth=1.0) self.canvas_frame = ttk.Labelframe(height=360, text='View') self.middle_panedwin.add(self.canvas_frame) self.spectrum_frame = ttk.Labelframe(height=-40, text='Spectrum') self.middle_panedwin.add(self.spectrum_frame) self.__funcid2 = self.left_panedwin.bind('<Map>', self.__adjust_sash2) self.canvas = Canvas(self.canvas_frame) self.canvas.place(relx=0.0, rely=0, relheight=1.0, relwidth=1.0) self.canvas.configure(background='white') self.canvas.configure(borderwidth='2') self.canvas.configure(relief='ridge') self.canvas.configure(selectbackground='#c4c4c4') self.canvas.bind('<Button-4>', sup.mouse_wheel) # for Linux self.canvas.bind('<Button-5>', sup.mouse_wheel) # for Linux self.canvas.bind('<MouseWheel>', sup.mouse_wheel) # for Windowz self.canvas.bind('<Button-3>', sup.mouse_down) self.canvas.bind('<B3-Motion>', sup.mouse_move) self.canvas.bind('<ButtonRelease-3>', sup.mouse_up) self.lbZoom = ttk.Label( self.canvas, text='x1.00', background='white') #font=('courier', 18, 'bold'), width=10) self.lbZoom.place(relx=1.0, x=-50, rely=1.0, y=-25) self.lbLambdaMin = ttk.Label(self.spectrum_frame, text='min') self.lbLambdaMin.place(x=5, y=0) self.edLambdaMin = ttk.Entry(self.spectrum_frame) self.edLambdaMin.place(x=5, y=15, width=35) self.edLambdaMin.insert(0, '300') self.lbLambdaMax = ttk.Label(self.spectrum_frame, text='max') self.lbLambdaMax.place(x=45, y=0) self.edLambdaMax = ttk.Entry(self.spectrum_frame) self.edLambdaMax.place(x=45, y=15, width=35) self.edLambdaMax.insert(0, '800') self.lbLambdaCount = ttk.Label(self.spectrum_frame, text='count') self.lbLambdaCount.place(x=85, y=0) self.edLambdaCount = ttk.Entry(self.spectrum_frame) self.edLambdaCount.place(x=85, y=15, width=35) self.edLambdaCount.insert(0, '51') self.btCalcSpec = ttk.Button(self.spectrum_frame, command=sup.btCalcSpecClick, text='Calculate', image=self.imCalc, compound='left') self.btCalcSpec.place(x=130, y=10, width=90, height=25) self.lbSpecScale = ttk.Label(self.spectrum_frame, text='scale') self.lbSpecScale.place(relx=1, x=-115, y=0) self.edSpecScale = ttk.Entry(self.spectrum_frame) self.edSpecScale.place(relx=1, x=-115, y=15, width=50) self.edSpecScale.insert(0, '1') self.btSaveSpec = ttk.Button(self.spectrum_frame, command=sup.btSaveSpecClick, text='S', image=self.imSave) self.btSaveSpec.place(relx=1, x=-55, y=10, width=25, height=25) self.btPlotSpec = ttk.Button(self.spectrum_frame, command=sup.btPlotSpecClick, text='P', image=self.imPlot) self.btPlotSpec.place(relx=1, x=-30, y=10, width=25, height=25) self.right_panedwin = ttk.Panedwindow(self.right_frame, orient='vertical') self.right_panedwin.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0) self.right_panedwin.configure(width=200) self.plot_frame = ttk.Labelframe(height=200, text='Plot') self.right_panedwin.add(self.plot_frame) self.contribs_frame = ttk.Labelframe(height=150, text='Other contributions') self.right_panedwin.add(self.contribs_frame) self.fitting_frame = ttk.Labelframe(height=-50, text='Fitting') self.right_panedwin.add(self.fitting_frame) self.__funcid3 = self.right_panedwin.bind('<Map>', self.__adjust_sash3) # CONTRIBUTIONS self.btAddContrib = ttk.Button(self.contribs_frame, command=sup.btAddContribClick, text='A', image=self.imAdd) self.btAddContrib.place(x=5, y=0, height=25, width=25) self.btPlotAllContribs = ttk.Button(self.contribs_frame, command=sup.btPlotAllContribsClick, text='P', image=self.imPlot) self.btPlotAllContribs.place(x=30, y=0, height=25, width=25) self.btDelContrib = ttk.Button(self.contribs_frame, command=sup.btDelContribClick, text='D', image=self.imDelete) self.btDelContrib.place(relx=1.0, y=0, x=-30, height=25, width=25) self.cbContribs = [] self.edContribs = [] # actually, it will be the list of lists [[]] self.btPlotsContrib = [] self.contribs_list = [ 'ConstBkg', 'LinearBkg', 'LorentzBkg', 'Mie single', 'Mie LN', 'Lorentz peak', 'Gauss peak', 'Au film', 'bst-3Au/glass' ] self.cbContribMats = [] self.btContribDistribPlots = [] # Fitting frame self.edExpFileName = ttk.Entry(self.fitting_frame, text='Exp. file name') self.edExpFileName.place(x=5, y=0, height=25, relwidth=0.8) self.btLoadExp = ttk.Button(self.fitting_frame, command=sup.btLoadExpClick, text='L', image=self.imLoad) self.btLoadExp.place(relx=1.0, x=-55, y=0, height=25, width=25) self.btPlotExp = ttk.Button(self.fitting_frame, command=sup.btPlotExpClick, text='P', image=self.imPlot) self.btPlotExp.place(relx=1.0, x=-30, y=0, height=25, width=25) self.btStartFit = ttk.Button(self.fitting_frame, command=sup.btStartFitClick, text='>', image=self.imPlay) self.btStartFit.place(x=5, y=30, height=25, width=25) self.btStopFit = ttk.Button(self.fitting_frame, command=sup.btStopFitClick, text='|', image=self.imStop) self.btStopFit.place(x=30, y=30, height=25, width=25) self.lbChiSq = ttk.Label(self.fitting_frame, text='ChiSq:') self.lbChiSq.place(x=60, y=35) self.btConstraints = ttk.Button(self.fitting_frame, command=sup.btConstraintsClick, text='Constraints...') self.btConstraints.place(relx=1, x=-100, y=30, height=25, width=95) self._create_menu(top) time_delta = time.time() - time_start # in seconds if time_delta < self.splash_time: time.sleep(self.splash_time - time_delta) top.deiconify() splash.destroy() def configure_stvMaterial(self): self.stvMaterial.configure(columns='Col1') self.stvMaterial.heading('#0', text='MatID') self.stvMaterial.heading('#0', anchor='center') self.stvMaterial.column('#0', width='46') self.stvMaterial.column('#0', minwidth='20') self.stvMaterial.column('#0', stretch='1') self.stvMaterial.column('#0', anchor='w') self.stvMaterial.heading('Col1', text='Name') self.stvMaterial.heading('Col1', anchor='center') self.stvMaterial.column('Col1', width='150') self.stvMaterial.column('Col1', minwidth='20') self.stvMaterial.column('Col1', stretch='1') self.stvMaterial.column('Col1', anchor='w') def configure_stvSpheres(self): self.stvSpheres.configure(columns='Col1 Col2 Col3 Col4 Col5') self.stvSpheres.heading('#0', text='ID') self.stvSpheres.heading('#0', anchor='center') self.stvSpheres.column('#0', width='34') self.stvSpheres.column('#0', minwidth='20') self.stvSpheres.column('#0', stretch='1') self.stvSpheres.column('#0', anchor='w') self.stvSpheres.heading('Col1', text='R') self.stvSpheres.heading('Col1', anchor='center') self.stvSpheres.column('Col1', width='37') self.stvSpheres.column('Col1', minwidth='20') self.stvSpheres.column('Col1', stretch='1') self.stvSpheres.column('Col1', anchor='w') self.stvSpheres.heading('Col2', text='X') self.stvSpheres.heading('Col2', anchor='center') self.stvSpheres.column('Col2', width='31') self.stvSpheres.column('Col2', minwidth='20') self.stvSpheres.column('Col2', stretch='1') self.stvSpheres.column('Col2', anchor='w') self.stvSpheres.heading('Col3', text='Y') self.stvSpheres.heading('Col3', anchor='center') self.stvSpheres.column('Col3', width='34') self.stvSpheres.column('Col3', minwidth='20') self.stvSpheres.column('Col3', stretch='1') self.stvSpheres.column('Col3', anchor='w') self.stvSpheres.heading('Col4', text='Z') self.stvSpheres.heading('Col4', anchor='center') self.stvSpheres.column('Col4', width='34') self.stvSpheres.column('Col4', minwidth='20') self.stvSpheres.column('Col4', stretch='1') self.stvSpheres.column('Col4', anchor='w') self.stvSpheres.heading('Col5', text='mID') self.stvSpheres.heading('Col5', anchor='center') self.stvSpheres.column('Col5', width='32') self.stvSpheres.column('Col5', minwidth='20') self.stvSpheres.column('Col5', stretch='1') self.stvSpheres.column('Col5', anchor='w') def load_images(self): def tryload(fn): try: im = ImageTk.PhotoImage(file=os.path.normpath( os.path.join(os.path.dirname(__file__), 'images', fn))) except Exception as err: print('Can not load %s\n%s' % (fn, err)) return None return im self.imLoad = tryload('folder_open_icon&16.png') self.imDelete = tryload('delete_icon&16.png') self.imPlot = tryload('chart_bar_icon&16.png') self.imPlot2 = tryload('chart_bar2_icon&16.png') self.imAdd = tryload('sq_plus_icon&16.png') self.imSave = tryload('save_icon&16.png') self.imRefresh = tryload('refresh_icon&16.png') self.imExport = tryload('export_icon&16.png') self.imImport = tryload('import_icon&16.png') self.imPlay = tryload('playback_play_icon&16.png') self.imStop = tryload('playback_stop_icon&16.png') self.imCalc = tryload('cogs_icon&16.png') self.imEdit = tryload('doc_edit_icon&16.png') self.imExit = tryload('on-off_icon&16.png') self.imBrush = tryload('brush_icon&16.png') self.imZoomIn = tryload('round_plus_icon&16.png') self.imZoomOut = tryload('round_minus_icon&16.png') def __adjust_sash0( self, event): # mysterious functions left from previous civilizations paned = event.widget pos = [ 220, 575, ] i = 0 for sash in pos: paned.sashpos(i, sash) i += 1 paned.unbind('<map>', self.__funcid0) del self.__funcid0 def __adjust_sash1(self, event): paned = event.widget pos = [ 145, ] i = 0 for sash in pos: paned.sashpos(i, sash) i += 1 paned.unbind('<map>', self.__funcid1) del self.__funcid1 def __adjust_sash2(self, event): paned = event.widget pos = [ 200, ] i = 0 for sash in pos: paned.sashpos(i, sash) i += 1 paned.unbind('<map>', self.__funcid2) del self.__funcid2 def __adjust_sash3(self, event): paned = event.widget pos = [ 200, ] i = 0 for sash in pos: paned.sashpos(i, sash) i += 1 paned.unbind('<map>', self.__funcid3) del self.__funcid3 def _create_menu(self, top): self.menubar = Menu(top) self.filemenu = Menu(self.menubar, tearoff=0) self.filemenu.add_command(label='Import spheres...', command=sup.btImportSpheres, image=self.imImport, compound='left') self.filemenu.add_command(label='Export spheres...', command=sup.btExportSpheres, image=self.imExport, compound='left') self.filemenu.add_separator() self.filemenu.add_command(label='Exit', command=sup.destroy_window, image=self.imExit, compound='left') self.menubar.add_cascade(label='File', menu=self.filemenu) self.matmenu = Menu(self.menubar, tearoff=0) self.matmenu.add_command(label='Add constant...', command=sup.btAddMatClick, image=self.imAdd, compound='left') self.matmenu.add_command(label='Load function...', command=sup.btLoadMatClick, image=self.imLoad, compound='left') self.matmenu.add_separator() self.matmenu.add_command(label='Delete selected', command=sup.btDelMatClick, image=self.imDelete, compound='left') self.matmenu.add_separator() self.matmenu.add_command(label='Plot selected', command=sup.btPlotMatClick, image=self.imPlot, compound='left') self.matmenu.add_separator() self.matmenu.add_command(label='Change view color...', command=sup.btChangeMatColClick, image=self.imBrush, compound='left') self.menubar.add_cascade(label='Materials', menu=self.matmenu) self.sphmenu = Menu(self.menubar, tearoff=0) self.sphmenu.add_command(label='Add...', command=sup.btAddSphClick, image=self.imAdd, compound='left') self.sphmenu.add_separator() self.sphmenu.add_command(label='Edit selected...', command=sup.btEditSphClick, image=self.imEdit, compound='left') self.sphmenu.add_command(label='Delete selected', command=sup.btDelSphClick, image=self.imDelete, compound='left') self.sphmenu.add_separator() self.sphmenu.add_command(label='Generate on mesh...', command=sup.btGenerateSpheresClick) self.menubar.add_cascade(label='Spheres', menu=self.sphmenu) self.viewmenu = Menu(self.menubar, tearoff=0) self.viewmenu.add_command(label='Zoom in', command=lambda: sup.mouse_wheel( type('', (), { 'num': 4, 'delta': 0 })()), image=self.imZoomIn, compound='left') self.viewmenu.add_command(label='Zoom out', command=lambda: sup.mouse_wheel( type('', (), { 'num': 5, 'delta': 0 })()), image=self.imZoomOut, compound='left') self.viewmenu.add_command(label='Reset view', command=sup.btPlotSphClick, image=self.imRefresh, compound='left') self.menubar.add_cascade(label='View', menu=self.viewmenu) self.opticsmenu = Menu(self.menubar, tearoff=0) self.opticsmenu.add_command(label='Calculate', command=sup.btCalcSpecClick, image=self.imCalc, compound='left') self.menubar.add_cascade(label='Spectrum', menu=self.opticsmenu) self.fittingmenu = Menu(self.menubar, tearoff=0) self.fittingmenu.add_command(label='Load experiment...', command=sup.btLoadExpClick, image=self.imLoad, compound='left') self.fittingmenu.add_separator() self.fittingmenu.add_command(label='Constraints...', command=sup.btConstraintsClick) self.fittingmenu.add_separator() self.fittingmenu.add_command(label='Start fit', command=sup.btStartFitClick, image=self.imPlay, compound='left') self.fittingmenu.add_command(label='Stop fit', command=sup.btStopFitClick, image=self.imStop, compound='left') self.menubar.add_cascade(label='Fitting', menu=self.fittingmenu) self.helpmenu = Menu(self.menubar, tearoff=0) self.helpmenu.add_command(label='About', command=sup.btAboutClick) self.menubar.add_cascade(label='Help', menu=self.helpmenu) # display the menu top.config(menu=self.menubar)
class liuyao: def __init__(self,root,gua64): self.cntoint={u'少阳-----':'1',u'少阴-- --':'2',u'老阳--O--':'3',u'老阴--X--':'4'} self.tfont=tkFont.Font(family='Fixdsys',size=25,weight=tkFont.BOLD) self.gfont=tkFont.Font(family='Fixdsys',size=13,weight=tkFont.BOLD) self.dgua=[] #动爻 self.ygua=[] #原始卦 self.bbgua=[] #变卦 self.yguastr=[] #原始卦 self.gua=[] #只有12的卦 self.pabout=True #右键显示消失淮南标题 self.guax=200 self.guay=100 self.liushen={'甲':0,'乙':0,'丙':1,'丁':1,'戊':2,'己':3,'庚':4,'辛':4,'壬':5,'癸':5} self.liushencn=['青龙','朱雀','勾陈','腾蛇','白虎','玄武'] self.tiangan={'甲':1,'乙':2,'丙':3,'丁':4,'戊':5,'己':6,'庚':7,'辛':8,'壬':9,'癸':10} self.dizhi={'子':1,'丑':2,'寅':3,'卯':4,'辰':5,'巳':6,'午':7,'未':8,'申':9,'酉':10,'戌':11,'亥':12} self.kongwangzu=['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'] self.root=root self.root.title(u'===六爻排盘===[淮南内部专用]') self.root.minsize(550,380) self.root.maxsize(550,380) self.canvas=Canvas(root,width=460,height=380,bg='gray') self.picyang=PhotoImage(file='tk\\yang.gif') self.picyin=PhotoImage(file='tk\\yin.gif') self.canvas.place(relx=0,rely=0) self.com={} for i in xrange(6): self.com[i]=Combobox(root,state='readonly') self.com[i]['values']=(u'少阳-----',u'少阴-- --',u'老阳--O--',u'老阴--X--') self.com[i].current(0) self.com[i].place(relx=0.85,rely=0.36-0.07*i,width=80) bt1=Button(root,text=u'排盘',command=self.paipan) # bt1.place(relx=0.85,rely=0.35+0.7) bt1.pack(side='right') self.date() #干支 #=========================== self.root.bind('<Button-3>',self.about) def liushenf(self): #配六神 xu=self.liushen[self.ritian.encode('utf-8')] for i in xrange(6): self.canvas.create_text(self.guax-170,100+150-30*i,font=self.gfont,text=self.liushencn[xu],tag='liushen') xu+=1 if xu>5: xu-=6 def date(self): turl=urllib2.urlopen('http://www.nongli.com/item4/index.asp',timeout=10).read() soup=BeautifulSoup(turl) zu=soup.findAll('td',{'width':'74%','bgcolor':'#FFFFFF'})[1].text # print zu wanzu=[] #wanzu里面是完成的年月日干支 wanzu.append(zu.split(' ')[0]) wanzu.append(zu.split(' ')[2]) wanzu.append(zu.split(' ')[3]) for i in xrange(3): # print u'干支',wanzu[i] self.canvas.create_text(self.guax-90+60*i,30,text=wanzu[i],font=self.gfont,tag='riqi') ri=wanzu[2] self.ritian=list(ri)[0] self.ridi=list(ri)[1] self.kongwang() def kongwang(self): # print u'日干支:',self.ridi,self.ritian cha=self.dizhi[self.ridi.encode('utf-8')]-self.tiangan[self.ritian.encode('utf-8')] if cha<0: cha+=+10 self.canvas.create_text(self.guax-90+120+30,30,font=self.gfont,text='(',tag='riqi') self.canvas.create_text(self.guax-90+120+30+15,30,font=self.gfont,text=self.kongwangzu[cha-2],tag='riqi') self.canvas.create_text(self.guax-90+120+30+30,30,font=self.gfont,text=self.kongwangzu[cha-1],tag='riqi') self.canvas.create_text(self.guax-90+120+30+45,30,font=self.gfont,text=')',tag='riqi') def about(self,event): if self.pabout: self.canvas.create_text(self.guax,100+250,text='淮南法教专用水印',fill='tan',font=self.tfont,tag='about') self.canvas.create_text(self.guax+140,370,text='--无名',fill='tan',tag='about') self.pabout=False else: self.canvas.delete('about') self.pabout=True def paipan(self): for i in xrange(6): self.ygua.append(self.cntoint[self.com[i].get()]) #得到原始爻名,转换为1234,添加入gua self.gua=self.ygua bbgua=self.gua print '=======================' print 'sel.gua',self.gua for i in xrange(6): if self.ygua[i]=='3': self.gua[i]='1' self.dgua.append(str(i)) self.dgua.append('1') elif self.ygua[i]=='4': self.gua[i]='2' self.dgua.append(str(i)) self.dgua.append('2') self.guastr=''.join(self.gua) # print u'变卦',bbgua # print u'字符串卦数',self.guastr # print u'数列卦',self.gua # print u'动卦',self.dgua # print gua64[guastr] self.draw() self.liushenf()#六神 def draw(self): self.canvas.delete('pic') #删除所有上次产生的ITEMS self.canvas.delete('liushen') # print u'当前itme数',self.canvas.find_all() #本卦 for i in xrange(6): if self.gua[i]=='1': self.canvas.create_image(self.guax,100+150-30*i,image=self.picyang,tag='pic') else: self.canvas.create_image(self.guax,100+150-30*i,image=self.picyin,tag='pic') #下面是六亲 for i in xrange(6): self.canvas.create_text(self.guax-70,100+30*i,font=self.gfont,text=gua64[self.guastr][i],tag='pic') #动爻标记 for i in xrange(0,len(self.dgua),2): if self.dgua[i+1]=='1': self.canvas.create_text(self.guax+70,250-30*int(self.dgua[i]),font=self.gfont,text='O',tag='pic') else: self.canvas.create_text(self.guax+70,250-30*int(self.dgua[i]),font=self.gfont,text='X',tag='pic') #世 syw=gua64[self.guastr][6] self.canvas.create_text(self.guax+55,280-30*syw,font=self.gfont,text='世',tag='pic') #应 yyw=gua64[self.guastr][7] self.canvas.create_text(self.guax+55,280-30*yyw,font=self.gfont,text='应',tag='pic') #六合、冲 hc=gua64[self.guastr][8] self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=hc,tag='pic') #游魂、归魂 zg=gua64[self.guastr][9] self.canvas.create_text(self.guax-70,100-30,font=self.gfont,text=zg,tag='pic') #卦宫 gg=gua64[self.guastr][10] self.canvas.create_text(self.guax,100-30,font=self.gfont,text=gg,tag='pic') #变卦 self.biangua() self.guastr='' self.dgua=[] #动爻 self.ygua=[] #原始卦 self.bbgua=[] #变卦 self.yguastr=[] #原始卦 self.gua=[] #只有12的卦 def biangua(self): self.bbgua=self.gua # print 'biangua',self.bbgua ''' sel.gua ['4', '4', '3', '3', '4', '3'] 字符串卦数 221121 数列卦 ['2', '2', '1', '1', '2', '1'] 动卦 ['0', '2', '1', '2', '2', '1', '3', '1', '4', '2', '5', '1'] 当前itme数 (1, 2, 3, 4, 5, 6, 7) biangua ['1', '1', '2', '2', '1', '2'] bguastr 112212 ''' for i in xrange(0,len(self.dgua),2): if self.dgua[i+1]=='1': self.bbgua[int(self.dgua[i])]='2' else: self.bbgua[int(self.dgua[i])]='1' print 'biangua',self.bbgua self.bguastr=''.join(self.bbgua) print 'bguastr',self.bguastr for i in xrange(6): if self.bbgua[i]=='1': self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyang,tag='pic') else: self.canvas.create_image(self.guax+130,100+150-30*i,image=self.picyin,tag='pic') #下面是六亲 for i in xrange(6): self.canvas.create_text(self.guax+200,100+30*i,font=self.gfont,text=gua64[self.bguastr][i],tag='pic')
class PiPresents(object): def pipresents_version(self): vitems=self.pipresents_issue.split('.') if len(vitems)==2: # cope with 2 digit version numbers before 1.3.2 return 1000*int(vitems[0])+100*int(vitems[1]) else: return 1000*int(vitems[0])+100*int(vitems[1])+int(vitems[2]) def __init__(self): # gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_INSTANCES|gc.DEBUG_OBJECTS|gc.DEBUG_SAVEALL) gc.set_debug(gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_SAVEALL) self.pipresents_issue="1.3.5" self.pipresents_minorissue = '1.3.5d' # position and size of window without -f command line option self.nonfull_window_width = 0.45 # proportion of width self.nonfull_window_height= 0.7 # proportion of height self.nonfull_window_x = 0 # position of top left corner self.nonfull_window_y=0 # position of top left corner StopWatch.global_enable=False # set up the handler for SIGTERM signal.signal(signal.SIGTERM,self.handle_sigterm) # **************************************** # Initialisation # *************************************** # get command line options self.options=command_options() # get Pi Presents code directory pp_dir=sys.path[0] self.pp_dir=pp_dir if not os.path.exists(pp_dir+"/pipresents.py"): if self.options['manager'] is False: tkMessageBox.showwarning("Pi Presents","Bad Application Directory") exit(102) # Initialise logging and tracing Monitor.log_path=pp_dir self.mon=Monitor() # Init in PiPresents only self.mon.init() # uncomment to enable control of logging from within a class # Monitor.enable_in_code = True # enables control of log level in the code for a class - self.mon.set_log_level() # make a shorter list to log/trace only some classes without using enable_in_code. Monitor.classes = ['PiPresents', 'HyperlinkShow','RadioButtonShow','ArtLiveShow','ArtMediaShow','MediaShow','LiveShow','MenuShow', 'GapShow','Show','ArtShow', 'AudioPlayer','BrowserPlayer','ImagePlayer','MenuPlayer','MessagePlayer','VideoPlayer','Player', 'MediaList','LiveList','ShowList', 'PathManager','ControlsManager','ShowManager','PluginManager','IOPluginManager', 'MplayerDriver','OMXDriver','UZBLDriver', 'TimeOfDay','ScreenDriver','Animate','OSCDriver','CounterManager', 'Network','Mailer' ] # Monitor.classes=['PiPresents','MediaShow','GapShow','Show','VideoPlayer','Player','OMXDriver'] # Monitor.classes=['OSCDriver'] # get global log level from command line Monitor.log_level = int(self.options['debug']) Monitor.manager = self.options['manager'] # print self.options['manager'] self.mon.newline(3) self.mon.sched (self,None, "Pi Presents is starting, Version:"+self.pipresents_minorissue + ' at '+time.strftime("%Y-%m-%d %H:%M.%S")) self.mon.log (self, "Pi Presents is starting, Version:"+self.pipresents_minorissue+ ' at '+time.strftime("%Y-%m-%d %H:%M.%S")) # self.mon.log (self," OS and separator:" + os.name +' ' + os.sep) self.mon.log(self,"sys.path[0] - location of code: "+sys.path[0]) # log versions of Raspbian and omxplayer, and GPU Memory with open("/boot/issue.txt") as ifile: self.mon.log(self,'\nRaspbian: '+ifile.read()) self.mon.log(self,'\n'+check_output(["omxplayer", "-v"])) self.mon.log(self,'\nGPU Memory: '+check_output(["vcgencmd", "get_mem", "gpu"])) if os.geteuid() == 0: print 'Do not run Pi Presents with sudo' self.mon.log(self,'Do not run Pi Presents with sudo') self.mon.finish() sys.exit(102) if "DESKTOP_SESSION" not in os.environ: print 'Pi Presents must be run from the Desktop' self.mon.log(self,'Pi Presents must be run from the Desktop') self.mon.finish() sys.exit(102) else: self.mon.log(self,'Desktop is '+ os.environ['DESKTOP_SESSION']) # optional other classes used self.root=None self.ppio=None self.tod=None self.animate=None self.ioplugin_manager=None self.oscdriver=None self.osc_enabled=False self.tod_enabled=False self.email_enabled=False user=os.getenv('USER') if user is None: tkMessageBox.showwarning("You must be logged in to run Pi Presents") exit(102) if user !='pi': self.mon.warn(self,"You must be logged as pi to use GPIO") self.mon.log(self,'User is: '+ user) # self.mon.log(self,"os.getenv('HOME') - user home directory (not used): " + os.getenv('HOME')) # does not work # self.mon.log(self,"os.path.expanduser('~') - user home directory: " + os.path.expanduser('~')) # does not work # check network is available self.network_connected=False self.network_details=False self.interface='' self.ip='' self.unit='' # sets self.network_connected and self.network_details self.init_network() # start the mailer and send email when PP starts self.email_enabled=False if self.network_connected is True: self.init_mailer() if self.email_enabled is True and self.mailer.email_at_start is True: subject= '[Pi Presents] ' + self.unit + ': PP Started on ' + time.strftime("%Y-%m-%d %H:%M") message = time.strftime("%Y-%m-%d %H:%M") + '\nUnit: ' + self.unit + ' Profile: '+ self.options['profile']+ '\n ' + self.interface + '\n ' + self.ip self.send_email('start',subject,message) # get profile path from -p option if self.options['profile'] != '': self.pp_profile_path="/pp_profiles/"+self.options['profile'] else: self.mon.err(self,"Profile not specified in command ") self.end('error','Profile not specified with the commands -p option') # get directory containing pp_home from the command, if self.options['home'] == "": home = os.sep+ 'home' + os.sep + user + os.sep+"pp_home" else: home = self.options['home'] + os.sep+ "pp_home" self.mon.log(self,"pp_home directory is: " + home) # check if pp_home exists. # try for 10 seconds to allow usb stick to automount found=False for i in range (1, 10): self.mon.log(self,"Trying pp_home at: " + home + " (" + str(i)+')') if os.path.exists(home): found=True self.pp_home=home break time.sleep (1) if found is True: self.mon.log(self,"Found Requested Home Directory, using pp_home at: " + home) else: self.mon.err(self,"Failed to find pp_home directory at " + home) self.end('error',"Failed to find pp_home directory at " + home) # check profile exists self.pp_profile=self.pp_home+self.pp_profile_path if os.path.exists(self.pp_profile): self.mon.sched(self,None,"Running profile: " + self.pp_profile_path) self.mon.log(self,"Found Requested profile - pp_profile directory is: " + self.pp_profile) else: self.mon.err(self,"Failed to find requested profile: "+ self.pp_profile) self.end('error',"Failed to find requested profile: "+ self.pp_profile) self.mon.start_stats(self.options['profile']) if self.options['verify'] is True: self.mon.err(self,"Validation option not supported - use the editor") self.end('error','Validation option not supported - use the editor') # initialise and read the showlist in the profile self.showlist=ShowList() self.showlist_file= self.pp_profile+ "/pp_showlist.json" if os.path.exists(self.showlist_file): self.showlist.open_json(self.showlist_file) else: self.mon.err(self,"showlist not found at "+self.showlist_file) self.end('error',"showlist not found at "+self.showlist_file) # check profile and Pi Presents issues are compatible if self.showlist.profile_version() != self.pipresents_version(): self.mon.err(self,"Version of showlist " + self.showlist.profile_version_string + " is not same as Pi Presents") self.end('error',"Version of showlist " + self.showlist.profile_version_string + " is not same as Pi Presents") # get the 'start' show from the showlist index = self.showlist.index_of_start_show() if index >=0: self.showlist.select(index) self.starter_show=self.showlist.selected_show() else: self.mon.err(self,"Show [start] not found in showlist") self.end('error',"Show [start] not found in showlist") # ******************** # SET UP THE GUI # ******************** # turn off the screenblanking and saver if self.options['noblank'] is True: call(["xset","s", "off"]) call(["xset","s", "-dpms"]) self.root=Tk() self.title='Pi Presents - '+ self.pp_profile self.icon_text= 'Pi Presents' self.root.title(self.title) self.root.iconname(self.icon_text) self.root.config(bg=self.starter_show['background-colour']) self.mon.log(self, 'monitor screen dimensions are ' + str(self.root.winfo_screenwidth()) + ' x ' + str(self.root.winfo_screenheight()) + ' pixels') if self.options['screensize'] =='': self.screen_width = self.root.winfo_screenwidth() self.screen_height = self.root.winfo_screenheight() else: reason,message,self.screen_width,self.screen_height=self.parse_screen(self.options['screensize']) if reason =='error': self.mon.err(self,message) self.end('error',message) self.mon.log(self, 'forced screen dimensions (--screensize) are ' + str(self.screen_width) + ' x ' + str(self.screen_height) + ' pixels') # set window dimensions and decorations if self.options['fullscreen'] is False: self.window_width=int(self.root.winfo_screenwidth()*self.nonfull_window_width) self.window_height=int(self.root.winfo_screenheight()*self.nonfull_window_height) self.window_x=self.nonfull_window_x self.window_y=self.nonfull_window_y self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y)) else: self.window_width=self.screen_width self.window_height=self.screen_height self.root.attributes('-fullscreen', True) os.system('unclutter &') self.window_x=0 self.window_y=0 self.root.geometry("%dx%d%+d%+d" % (self.window_width,self.window_height,self.window_x,self.window_y)) self.root.attributes('-zoomed','1') # canvas cover the whole screen whatever the size of the window. self.canvas_height=self.screen_height self.canvas_width=self.screen_width # make sure focus is set. self.root.focus_set() # define response to main window closing. self.root.protocol ("WM_DELETE_WINDOW", self.handle_user_abort) # setup a canvas onto which will be drawn the images or text self.canvas = Canvas(self.root, bg=self.starter_show['background-colour']) if self.options['fullscreen'] is True: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=0) else: self.canvas.config(height=self.canvas_height, width=self.canvas_width, highlightthickness=1, highlightcolor='yellow') self.canvas.place(x=0,y=0) # self.canvas.config(bg='black') self.canvas.focus_set() # **************************************** # INITIALISE THE TOUCHSCREEN DRIVER # **************************************** # each driver takes a set of inputs, binds them to symboic names # and sets up a callback which returns the symbolic name when an input event occurs self.sr=ScreenDriver() # read the screen click area config file reason,message = self.sr.read(pp_dir,self.pp_home,self.pp_profile) if reason == 'error': self.end('error','cannot find, or error in screen.cfg') # create click areas on the canvas, must be polygon as outline rectangles are not filled as far as find_closest goes # click areas are made on the Pi Presents canvas not the show canvases. reason,message = self.sr.make_click_areas(self.canvas,self.handle_input_event) if reason == 'error': self.mon.err(self,message) self.end('error',message) # **************************************** # INITIALISE THE APPLICATION AND START # **************************************** self.shutdown_required=False self.reboot_required=False self.terminate_required=False self.exitpipresents_required=False # initialise the I/O plugins by importing their drivers self.ioplugin_manager=IOPluginManager() reason,message=self.ioplugin_manager.init(self.pp_dir,self.pp_profile,self.root,self.handle_input_event) if reason == 'error': # self.mon.err(self,message) self.end('error',message) # kick off animation sequencer self.animate = Animate() self.animate.init(pp_dir,self.pp_home,self.pp_profile,self.canvas,200,self.handle_output_event) self.animate.poll() #create a showmanager ready for time of day scheduler and osc server show_id=-1 self.show_manager=ShowManager(show_id,self.showlist,self.starter_show,self.root,self.canvas,self.pp_dir,self.pp_profile,self.pp_home) # first time through set callback to terminate Pi Presents if all shows have ended. self.show_manager.init(self.canvas,self.all_shows_ended_callback,self.handle_command,self.showlist) # Register all the shows in the showlist reason,message=self.show_manager.register_shows() if reason == 'error': self.mon.err(self,message) self.end('error',message) # Init OSCDriver, read config and start OSC server self.osc_enabled=False if self.network_connected is True: if os.path.exists(self.pp_profile + os.sep + 'pp_io_config'+ os.sep + 'osc.cfg'): self.oscdriver=OSCDriver() reason,message=self.oscdriver.init(self.pp_profile, self.unit,self.interface,self.ip, self.handle_command,self.handle_input_event,self.e_osc_handle_animate) if reason == 'error': self.mon.err(self,message) self.end('error',message) else: self.osc_enabled=True self.root.after(1000,self.oscdriver.start_server()) # initialise ToD scheduler calculating schedule for today self.tod=TimeOfDay() reason,message,self.tod_enabled = self.tod.init(pp_dir,self.pp_home,self.pp_profile,self.showlist,self.root,self.handle_command) if reason == 'error': self.mon.err(self,message) self.end('error',message) # warn if the network not available when ToD required if self.tod_enabled is True and self.network_connected is False: self.mon.warn(self,'Network not connected so Time of Day scheduler may be using the internal clock') # init the counter manager self.counter_manager=CounterManager() self.counter_manager.init() # warn about start shows and scheduler if self.starter_show['start-show']=='' and self.tod_enabled is False: self.mon.sched(self,None,"No Start Shows in Start Show and no shows scheduled") self.mon.warn(self,"No Start Shows in Start Show and no shows scheduled") if self.starter_show['start-show'] !='' and self.tod_enabled is True: self.mon.sched(self,None,"Start Shows in Start Show and shows scheduled - conflict?") self.mon.warn(self,"Start Shows in Start Show and shows scheduled - conflict?") # run the start shows self.run_start_shows() # kick off the time of day scheduler which may run additional shows if self.tod_enabled is True: self.tod.poll() # start the I/O plugins input event generation self.ioplugin_manager.start() # start Tkinters event loop self.root.mainloop( ) def parse_screen(self,size_text): fields=size_text.split('*') if len(fields)!=2: return 'error','do not understand --screensize comand option',0,0 elif fields[0].isdigit() is False or fields[1].isdigit() is False: return 'error','dimensions are not positive integers in --screensize',0,0 else: return 'normal','',int(fields[0]),int(fields[1]) # ********************* # RUN START SHOWS # ******************** def run_start_shows(self): self.mon.trace(self,'run start shows') # parse the start shows field and start the initial shows show_refs=self.starter_show['start-show'].split() for show_ref in show_refs: reason,message=self.show_manager.control_a_show(show_ref,'open') if reason == 'error': self.mon.err(self,message) # ********************* # User inputs # ******************** def e_osc_handle_animate(self,line): #jump out of server thread self.root.after(1, lambda arg=line: self.osc_handle_animate(arg)) def osc_handle_animate(self,line): self.mon.log(self,"animate command received: "+ line) #osc sends output events as a string reason,message,delay,name,param_type,param_values=self.animate.parse_animate_fields(line) if reason == 'error': self.mon.err(self,message) self.end(reason,message) self.handle_output_event(name,param_type,param_values,0) # output events are animate commands def handle_output_event(self,symbol,param_type,param_values,req_time): reason,message=self.ioplugin_manager.handle_output_event(symbol,param_type,param_values,req_time) if reason =='error': self.mon.err(self,message) self.end(reason,message) # all input events call this callback providing a symbolic name. # handle events that affect PP overall, otherwise pass to all active shows def handle_input_event(self,symbol,source): self.mon.log(self,"event received: "+symbol + ' from '+ source) if symbol == 'pp-terminate': self.handle_user_abort() elif symbol == 'pp-shutdown': self.mon.err(self,'pp-shutdown removed in version 1.3.3a, see Release Notes') self.end('error','pp-shutdown removed in version 1.3.3a, see Release Notes') elif symbol == 'pp-shutdownnow': # need root.after to grt out of st thread self.root.after(1,self.shutdownnow_pressed) return elif symbol == 'pp-exitpipresents': self.exitpipresents_required=True if self.show_manager.all_shows_exited() is True: # need root.after to grt out of st thread self.root.after(1,self.e_all_shows_ended_callback) return reason,message= self.show_manager.exit_all_shows() else: # pass the input event to all registered shows for show in self.show_manager.shows: show_obj=show[ShowManager.SHOW_OBJ] if show_obj is not None: show_obj.handle_input_event(symbol) # commands are generaed by tracks and shows # they can open or close shows, generate input events and do special tasks # commands also generate osc outputs to other computers # handles one command provided as a line of text def handle_command(self,command_text,source='',show=''): # print 'PIPRESENTS ',command_text,'\n Source',source,'from',show self.mon.log(self,"command received: " + command_text) if command_text.strip()=="": return fields= command_text.split() if fields[0] in ('osc','OSC'): if self.osc_enabled is True: status,message=self.oscdriver.parse_osc_command(fields[1:]) if status=='warn': self.mon.warn(self,message) if status=='error': self.mon.err(self,message) self.end('error',message) return if fields[0] =='counter': status,message=self.counter_manager.parse_counter_command(fields[1:]) if status=='error': self.mon.err(self,message) self.end('error',message) return show_command=fields[0] if len(fields)>1: show_ref=fields[1] else: show_ref='' if show_command in ('open','close','closeall','openexclusive'): self.mon.sched(self, TimeOfDay.now,command_text + ' received from show:'+show) if self.shutdown_required is False and self.terminate_required is False: reason,message=self.show_manager.control_a_show(show_ref,show_command) else: return elif show_command =='monitor': self.handle_monitor_command(show_ref) return elif show_command =='cec': self.handle_cec_command(show_ref) return elif show_command == 'event': self.handle_input_event(show_ref,'Show Control') return elif show_command == 'exitpipresents': self.exitpipresents_required=True if self.show_manager.all_shows_exited() is True: # need root.after to get out of st thread self.root.after(1,self.e_all_shows_ended_callback) return else: reason,message= self.show_manager.exit_all_shows() elif show_command == 'shutdownnow': # need root.after to get out of st thread self.root.after(1,self.shutdownnow_pressed) return elif show_command == 'reboot': # need root.after to get out of st thread self.root.after(1,self.reboot_pressed) return else: reason='error' message = 'command not recognised: '+ show_command if reason=='error': self.mon.err(self,message) return def handle_monitor_command(self,command): if command == 'on': os.system('vcgencmd display_power 1 >/dev/null') elif command == 'off': os.system('vcgencmd display_power 0 >/dev/null') def handle_cec_command(self,command): if command == 'on': os.system('echo "on 0" | cec-client -s') elif command == 'standby': os.system('echo "standby 0" | cec-client -s') elif command == 'scan': os.system('echo scan | cec-client -s -d 1') # deal with differnt commands/input events def shutdownnow_pressed(self): self.shutdown_required=True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal','no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def reboot_pressed(self): self.reboot_required=True if self.show_manager.all_shows_exited() is True: self.all_shows_ended_callback('normal','no shows running') else: # calls exit method of all shows, results in all_shows_closed_callback self.show_manager.exit_all_shows() def handle_sigterm(self,signum,fframe): self.mon.log(self,'SIGTERM received - '+ str(signum)) self.terminate() def handle_user_abort(self): self.mon.log(self,'User abort received') self.terminate() def terminate(self): self.mon.log(self, "terminate received") self.terminate_required=True needs_termination=False for show in self.show_manager.shows: # print show[ShowManager.SHOW_OBJ], show[ShowManager.SHOW_REF] if show[ShowManager.SHOW_OBJ] is not None: needs_termination=True self.mon.log(self,"Sent terminate to show "+ show[ShowManager.SHOW_REF]) # call shows terminate method # eventually the show will exit and after all shows have exited all_shows_callback will be executed. show[ShowManager.SHOW_OBJ].terminate() if needs_termination is False: self.end('killed','killed - no termination of shows required') # ****************************** # Ending Pi Presents after all the showers and players are closed # ************************** def e_all_shows_ended_callback(self): self.all_shows_ended_callback('normal','no shows running') # callback from ShowManager when all shows have ended def all_shows_ended_callback(self,reason,message): self.canvas.config(bg=self.starter_show['background-colour']) if reason in ('killed','error') or self.shutdown_required is True or self.exitpipresents_required is True or self.reboot_required is True: self.end(reason,message) def end(self,reason,message): self.mon.log(self,"Pi Presents ending with reason: " + reason) if self.root is not None: self.root.destroy() self.tidy_up() if reason == 'killed': if self.email_enabled is True and self.mailer.email_on_terminate is True: subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Terminated' message = time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip self.send_email(reason,subject,message) self.mon.sched(self, None,"Pi Presents Terminated, au revoir\n") self.mon.log(self, "Pi Presents Terminated, au revoir") # close logging files self.mon.finish() print 'Uncollectable Garbage',gc.collect() # objgraph.show_backrefs(objgraph.by_type('Monitor')) sys.exit(101) elif reason == 'error': if self.email_enabled is True and self.mailer.email_on_error is True: subject= '[Pi Presents] ' + self.unit + ': PP Exited with reason: Error' message_text = 'Error message: '+ message + '\n'+ time.strftime("%Y-%m-%d %H:%M") + '\n ' + self.unit + '\n ' + self.interface + '\n ' + self.ip self.send_email(reason,subject,message_text) self.mon.sched(self,None, "Pi Presents closing because of error, sorry\n") self.mon.log(self, "Pi Presents closing because of error, sorry") # close logging files self.mon.finish() print 'uncollectable garbage',gc.collect() sys.exit(102) else: self.mon.sched(self,None,"Pi Presents exiting normally, bye\n") self.mon.log(self,"Pi Presents exiting normally, bye") # close logging files self.mon.finish() if self.reboot_required is True: # print 'REBOOT' call (['sudo','reboot']) if self.shutdown_required is True: # print 'SHUTDOWN' call (['sudo','shutdown','now','SHUTTING DOWN']) print 'uncollectable garbage',gc.collect() sys.exit(100) # tidy up all the peripheral bits of Pi Presents def tidy_up(self): self.handle_monitor_command('on') self.mon.log(self, "Tidying Up") # turn screen blanking back on if self.options['noblank'] is True: call(["xset","s", "on"]) call(["xset","s", "+dpms"]) # tidy up animation if self.animate is not None: self.animate.terminate() # tidy up i/o plugins if self.ioplugin_manager != None: self.ioplugin_manager.terminate() if self.osc_enabled is True: self.oscdriver.terminate() # tidy up time of day scheduler if self.tod_enabled is True: self.tod.terminate() # ******************************* # Connecting to network and email # ******************************* def init_network(self): timeout=int(self.options['nonetwork']) if timeout== 0: self.network_connected=False self.unit='' self.ip='' self.interface='' return self.network=Network() self.network_connected=False # try to connect to network self.mon.log (self, 'Waiting up to '+ str(timeout) + ' seconds for network') success=self.network.wait_for_network(timeout) if success is False: self.mon.warn(self,'Failed to connect to network after ' + str(timeout) + ' seconds') # tkMessageBox.showwarning("Pi Presents","Failed to connect to network so using fake-hwclock") return self.network_connected=True self.mon.sched (self, None,'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S")) self.mon.log (self, 'Time after network check is '+ time.strftime("%Y-%m-%d %H:%M.%S")) # Get web configuration self.network_details=False network_options_file_path=self.pp_dir+os.sep+'pp_config'+os.sep+'pp_web.cfg' if not os.path.exists(network_options_file_path): self.mon.warn(self,"pp_web.cfg not found at "+network_options_file_path) return self.mon.log(self, 'Found pp_web.cfg in ' + network_options_file_path) self.network.read_config(network_options_file_path) self.unit=self.network.unit # get interface and IP details of preferred interface self.interface,self.ip = self.network.get_preferred_ip() if self.interface == '': self.network_connected=False return self.network_details=True self.mon.log (self, 'Network details ' + self.unit + ' ' + self.interface + ' ' +self.ip) def init_mailer(self): self.email_enabled=False email_file_path = self.pp_dir+os.sep+'pp_config'+os.sep+'pp_email.cfg' if not os.path.exists(email_file_path): self.mon.log(self,'pp_email.cfg not found at ' + email_file_path) return self.mon.log(self,'Found pp_email.cfg at ' + email_file_path) self.mailer=Mailer() self.mailer.read_config(email_file_path) # all Ok so can enable email if config file allows it. if self.mailer.email_allowed is True: self.email_enabled=True self.mon.log (self,'Email Enabled') def try_connect(self): tries=1 while True: success, error = self.mailer.connect() if success is True: return True else: self.mon.log(self,'Failed to connect to email SMTP server ' + str(tries) + '\n ' +str(error)) tries +=1 if tries >5: self.mon.log(self,'Failed to connect to email SMTP server after ' + str(tries)) return False def send_email(self,reason,subject,message): if self.try_connect() is False: return False else: success,error = self.mailer.send(subject,message) if success is False: self.mon.log(self, 'Failed to send email: ' + str(error)) success,error=self.mailer.disconnect() if success is False: self.mon.log(self,'Failed disconnect after send:' + str(error)) return False else: self.mon.log(self,'Sent email for ' + reason) success,error=self.mailer.disconnect() if success is False: self.mon.log(self,'Failed disconnect from email server ' + str(error)) return True