class CheckbuttonEntry(BaseWiget): def __init__(self, parent, **kw): BaseWiget.__init__(self,parent, **kw) self.old_value = "" self.var = IntVar() self.cbtn = Checkbutton(self, text=self.caption, variable=self.var) self.cbtn.grid(row=1, column=0) self.var.trace("w", self._onChangeVariable) self.old_value = self.getValue() self.onEndSetupContent() #------------- интерфейс -------------# def setValue(self, value): print "setValue", value if self.old_value == value: return self.old_value = value self.var.set(value) def getValue(self): return self.var.get() def getDictValue(self): raise NotImplementedError def forceSave(self): """принудительное сохранение""" self._onEndInput() #------------- внутренние методы -------------# def _onEndInput(self): value = self.getValue() if self.old_value != value: self.onValueChangeEndByUser(self.old_value, value) self.old_value = value def _onChangeVariable(self, *event): value = self.getValue() if self.old_value == value: return self._onEndInput()
result = [] for i in range(3): result.append(StringVar()) result[i].set("") label = Label(root, textvariable=result[i]) label.grid(row=1, column=i) label.bind("<Button-1>", lambda e, j=i: insert_text(j)) # the n-gram size options (choice of n-1) this allows you to choose how many words the dict is keyed on sizeOptions = [1, 2, 3, 4, 5] # set up the int variable that holds the size of n-1, and set its default value to the first option in sizeOptions size = IntVar() size.set(sizeOptions[0]) # set a trace on this variable that calls load_n_gram_dict on any change size.trace("w", load_n_gram_dict) # directory which contain texts textDirectory = "text_sources" # get files in directory for options fileNameOptions = os.listdir(textDirectory) fileNameOptions = convert_to_readable_format(fileNameOptions) # set up the variable that holds the domain file, and set its default value to the first option in fileNameOptions fileName = StringVar() fileName.set(fileNameOptions[1]) # set a trace on this variable that calls load_n_gram_dict on any change fileName.trace("w", load_n_gram_dict)
class GUI: def run(self): self.maxSentries = 15 if len(Connector.getPorts()) == 0: tkMessageBox.showerror(Local('Error'), Local('Serial port not found')) os._exit(0) self.reload = False self.protScanTask = None self.tempWindow = None self.histWindow = None #window root = self.root = Tkinter.Tk() root.resizable(False, False) root.title('GSMguard Configuration v.' + appVersion) root.iconbitmap(resource_path('./gg-icon.ico')) fleft = ttk.Frame(root) fleft.pack(side = 'left', anchor = 'n') fright = ttk.LabelFrame(root, text = Local('Schedule')) fright.pack(side = 'right', anchor = 'n', padx = 3, pady = 3, fill = 'y') self.makeLocaleSettings(fleft) self.makePortSettings(fleft) self.makeMainSettings(fleft) self.makeScheduleSettings(fright) self.updPortList() root.mainloop() return self.reload #------------------ GUI CONSTRUCTION ----------------------- def makeLocaleSettings(self, root): localeFrame = ttk.LabelFrame(root, text = Local('Localization')) localeFrame.pack(side = 'top', fill = 'x', padx = 3, pady = 3) langFrame = ttk.Frame(localeFrame) langFrame.pack(side = 'top', fill = 'x') ttk.Label(langFrame, text = Local('Language:')).pack(side = 'left', padx = 3, pady = 3) def changeLang(x): setLocale(x) self.reload = True if self.protScanTask is not None: self.root.after_cancel(self.protScanTask) self.root.destroy() ttk.OptionMenu(langFrame, StringVar(), getCurrentLocale(), *getLocales(), command = changeLang).pack(side = 'left', padx = 3, pady = 3) def makePortSettings(self, root): connFrame = ttk.LabelFrame(root, text = Local('Connection')) connFrame.pack(side = 'top', fill = 'x', padx = 3, pady = 3) portFrame = ttk.Frame(connFrame) portFrame.pack(side = 'top') ttk.Label(portFrame, text = Local('Port')).pack(side = 'left', padx = 3, pady = 3) self.port = StringVar() self.portOpt = ttk.OptionMenu(portFrame, self.port) self.portOpt.pack(side = 'left', padx = 3, pady = 3) ttk.Button(portFrame, text = Local('Read'), command = lambda: self.readButton()).pack(side = 'left', padx = 3, pady = 3) ttk.Button(portFrame, text = Local('Write'), command = lambda: self.writeButton()).pack(side = 'left', padx = 3, pady = 3) self.readEventHist = IntVar(value = 1) ttk.Checkbutton(connFrame, text = Local('Read event history'), variable=self.readEventHist).pack(side = 'top', anchor = 'w', padx = 3, pady = 3) self.readTempStat = IntVar(value = 1) ttk.Checkbutton(connFrame, text = Local('Read temperature statistics'), variable=self.readTempStat).pack(side = 'top', anchor = 'w', padx = 3, pady = 3) self.infoLbl = StringVar() ttk.Label(connFrame, textvariable=self.infoLbl, foreground = 'red').pack(side = 'top') def makeMainSettings(self, root): mainConfFrame = ttk.LabelFrame(root, text = Local('Alarms')) mainConfFrame.pack(side = 'top', fill = 'x', padx = 3, pady = 3) #phone number phoneFrame = ttk.Frame(mainConfFrame) phoneFrame.pack(side = 'top', padx = 3, pady = 3, anchor="w") ttk.Label(phoneFrame, text = Local('Tel.')).pack(side = 'left', padx = 3, pady = 3) self.phone = StringVar(value = '+12225566123') ttk.Entry(phoneFrame, width=20, textvariable=self.phone).pack(side = 'left', padx = 3, pady = 3) #Max one report in 20min maxOneRepFrame = ttk.Frame(mainConfFrame) maxOneRepFrame.pack(side = 'top', padx = 3, pady = 3, anchor="w") self.maxOneRepOn = IntVar(value = 0) ttk.Checkbutton(maxOneRepFrame, text = Local('Max one report in 20min'), variable=self.maxOneRepOn).pack(side = 'left', padx = 3, pady = 3) #daily report time dRepFrame = ttk.Frame(mainConfFrame) dRepFrame.pack(side = 'top', padx = 3, pady = 3, anchor="w") self.repOn = IntVar(value = 1) ttk.Checkbutton(dRepFrame, text = Local('Daily report'), variable=self.repOn).pack(side = 'left', padx = 3, pady = 3) self.repOn.trace('w', lambda *args: drepEn(self.repOn.get())) self.repHr = StringVar(value = '20') rm = ttk.Entry(dRepFrame, width=2, textvariable=self.repHr) rm.pack(side = 'left') ttk.Label(dRepFrame, text = ":").pack(side = 'left') self.repMin = StringVar(value = '00') rh = ttk.Entry(dRepFrame, width=2, textvariable=self.repMin) rh.pack(side = 'left') def drepEn(v): if v: rm.config(state='enabled') rh.config(state='enabled') else: rm.config(state='disabled') rh.config(state='disabled') #temperature report tempFrame = ttk.Frame(mainConfFrame) tempFrame.pack(side = 'top', padx = 3, pady = 3, anchor="w") self.tempRepOn = IntVar(value = 1) ttk.Checkbutton(tempFrame, text = Local('Temperature alarm'), variable=self.tempRepOn).pack(side = 'left', padx = 3, pady = 3) self.tempRepOn.trace('w', lambda *args: trepEn(self.tempRepOn.get())) #ttk.Label(tempFrame, text = Local('Temperature alarm')).pack(side = 'top', padx = 3, pady = 3) ttk.Label(tempFrame, text = Local('min.')).pack(side = 'left') self.tempMin = StringVar(value = '-30') tmin = ttk.Entry(tempFrame, width=4, textvariable=self.tempMin) tmin.pack(side = 'left') ttk.Label(tempFrame, text = "°С " + Local('max.')).pack(side = 'left') self.tempMax = StringVar(value = '40') tmax = ttk.Entry(tempFrame, width=4, textvariable=self.tempMax) tmax.pack(side = 'left') ttk.Label(tempFrame, text = "°С").pack(side = 'left') def trepEn(v): if v: tmin.config(state='enabled') tmax.config(state='enabled') else: tmin.config(state='disabled') tmax.config(state='disabled') def makeScheduleSettings(self, root): self.sEntries = [] self.sEntryCnt = 4 self.addSEntry = lambda: self.addScheduleEntry(root) ScheduleEntry.labels(root, self.addSEntry) self.sEntries.append(ScheduleEntry(root, 3)) def addScheduleEntry(self, root): if len(self.sEntries) >= self.maxSentries: return self.sEntries.append(ScheduleEntry(root, self.sEntryCnt, lambda v: self.sEntries.remove(v))) self.sEntryCnt += 1 #------------------ LOGIC ----------------------- def updPortList(self): ports = Connector.getPorts() tmp = self.port.get() self.portOpt.set_menu(tmp if tmp else ports[0] if len(ports) else '', *ports) self.protScanTask = self.root.after(2000, lambda: self.updPortList()) def readButton(self): self.infoLbl.set(Local('Please wait...')) self.root.update() try: conf = Connector.read(self.port.get(), self.readEventHist.get(), self.readTempStat.get()) self.spreadData(conf) if self.histWindow: self.histWindow.destroy() self.histWindow = None if self.tempWindow: self.tempWindow.destroy() self.tempWindow = None if self.readEventHist.get(): self.histWindow = Tkinter.Toplevel() x = self.root.winfo_x() y = self.root.winfo_y() + self.root.winfo_height() + 40 self.histWindow.geometry('+%d+%d' % (x,y)) EventHistory(self.histWindow, conf['eventHist']) if self.readTempStat.get(): self.tempWindow = Tkinter.Toplevel() x = self.root.winfo_x() + self.root.winfo_width() + 10 y = self.root.winfo_y() self.tempWindow.geometry('+%d+%d' % (x,y)) TempPlot(self.tempWindow, conf['tempHist']) except Exception as e: tkMessageBox.showerror(Local('Error'), str(e)) traceback.print_exc() finally: self.infoLbl.set('') def writeButton(self): self.infoLbl.set(Local('Please wait...')) self.root.update() try: self.validate() conf = self.gatherData() Connector.write(self.port.get(), conf) tkMessageBox.showinfo('Info', Local('Success!')) except Exception as e: tkMessageBox.showerror(Local('Error'), str(e)) traceback.print_exc() finally: self.infoLbl.set('') #print(self.gatherData()) def gatherData(self): data = {} data['numb'] = self.phone.get() if self.repOn.get(): data['dRep'] = self.repHr.get()+':'+self.repMin.get() else: data['dRep'] = 'none' data['minT'] = int(self.tempMin.get()) data['maxT'] = int(self.tempMax.get()) data['flags'] = ((self.tempRepOn.get()&1) << 1) | (self.maxOneRepOn.get()&1) data['time'] = datetime.now().strftime("%d-%m-%Y %H:%M:%S") data['sched'] = [] for e in self.sEntries: data['sched'].append(e.get()) return data def spreadData(self, data): self.phone.set(data['numb']) if data['dRep'] == 'none': self.repOn.set(False) else: self.repOn.set(True) t = data['dRep'].split(':') self.repHr.set(t[0]) self.repMin.set(t[1]) self.tempMin.set(data['minT']) self.tempMax.set(data['maxT']) self.maxOneRepOn.set(data['flags'] & 0x01) self.tempRepOn.set(bool(data['flags'] & 0x02)) #make enties while len(self.sEntries) < len(data['sched']): self.addSEntry() while len(self.sEntries) > len(data['sched']): self.sEntries[len(self.sEntries)-1].delete() for i in range(0, len(self.sEntries)): self.sEntries[i].set(data['sched'][i]) def validate(self): if not re.match(r'^\+?\d{5,12}$', self.phone.get()): raise Exception(Local('Incorrect phone number')) if self.repOn.get() and ( not self.repHr.get().isdigit() or not self.repMin.get().isdigit() or int(self.repHr.get()) > 23 or int(self.repMin.get()) > 59 ): raise Exception(Local('Incorrect phone number')) try: min = int(self.tempMin.get()) max = int(self.tempMax.get()) except: raise Exception(Local('Incorrect report time')) if (min < -80 or min > 80 or max < -80 or max > 80 or not min < max ): raise Exception(Local('Incorrect temperature range')) for e in self.sEntries: e.validate()