class DlgDelay(Dialog): def body(self, master, cfg={}): "place user dialog widgets" self.config = cfg self.config["OK button"] = False self.delay = StringVar() self.delay.set(cfg.get("delay", "")) self.edelay = Entry(master, width=15, textvariable=self.delay) self.edelay.grid(column=1, row=0, sticky="e") Label(master, text=_("Delay:")).grid(column=0, row=0, sticky="w") self.resizable(width=0, height=0) return self.edelay def validate(self): try: flt = float(self.delay.get()) except ValueError: return self.edelay if flt < 0 or flt > 5: return self.edelay return None def apply(self): "On ok button pressed" self.config["delay"] = self.delay.get() self.config["OK button"] = True
def add_file_info_box(self, mainframe, name, labeldict, btncallback, fvar): """ Create and add a infobox containing the info about a loaded savegame. """ title = {'source':'Copy face from source file:', 'target':'To target file:'} frame = LabelFrame(mainframe, text=title[name]) frame.pack(anchor=N, fill=X, expand=1, side=TOP, padx=0, pady=0) frame.columnconfigure(1, weight=1) btn = Button(frame, text='Browse', command=btncallback) btn.grid(column=0, row=0, padx=2, pady=2) field = Entry(frame, width=50, textvariable=fvar) field.grid(column=1, row=0, columnspan=2, padx=2, pady=2, sticky=W+E) l = ('name','gender','level','race','location','save number','playing time') for n, (i, j) in enumerate([(x.capitalize()+':', x) for x in l]): Label(frame, text=i, state=DISABLED).grid(column=0, row=n+1, padx=4, pady=3, sticky=E) labeldict[j] = StringVar() Label(frame, textvariable=labeldict[j]).grid(column=1, row=n+1, padx=4, pady=3, sticky=W) self.screenshot[name] = Label(frame) self.screenshot[name].grid(column=2, row=1, rowspan=len(l), padx=4, pady=4)
def __init__(self, parent, url=None, buttonSEC=False, buttonRSS=False): super(DialogURL, self).__init__(parent) self.parent = parent parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.accepted = False self.url = None self.transient(self.parent) self.title("Enter URL") self.urlVar = StringVar() self.urlVar.set(url if url is not None else "http://") frame = Frame(self) urlLabel = Label(frame, text=_("URL:"), underline=0) urlEntry = Entry(frame, textvariable=self.urlVar, width=60) urlEntry.focus_set() okButton = Button(frame, text=_("OK"), command=self.ok) cancelButton = Button(frame, text=_("Cancel"), command=self.close) if buttonSEC: usSecButton = Button(frame, text=_("SEC search"), command=self.usSec) usSecButton.grid(row=1, column=1, sticky=W, pady=3) ToolTip(usSecButton, text=_("Opens US SEC Edgar Company Search (in web browser)\n\n" "(1) Find the company in web browser,\n" "(2) Click 'documents' button for desired filing,\n" "(3) Find 'data files' panel, instance document row, 'document' column,\n" "(4) On instance document file name, right-click browser menu: 'copy shortcut',\n" "(5) Come back to this dialog window,\n" "(6) Ctrl-v (paste) shortcut into above URL text box,\n" "(7) Click ok button to load instance document"), wraplength=480) if buttonRSS: rssButton = Button(frame, text=_("SEC RSS"), command=self.rssFeed) rssButton.grid(row=1, column=1, pady=3) ToolTip(rssButton, text=_("Opens current US SEC Edgar RSS feed"), wraplength=480) urlLabel.grid(row=0, column=0, sticky=W, pady=3, padx=3) urlEntry.grid(row=0, column=1, columnspan=3, sticky=EW, pady=3, padx=3) okButton.grid(row=1, column=2, sticky=E, pady=3) ToolTip(okButton, text=_("Opens above URL from web cache, downloading to cache if necessary"), wraplength=240) cancelButton.grid(row=1, column=3, sticky=EW, pady=3, padx=3) ToolTip(cancelButton, text=_("Cancel operation")) frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(1, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100)) self.bind("<Alt-u>", lambda *ignore: urlEntry.focus_set()) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self)
def make_entry(self, label_text, var): '''Return (entry, label), . entry - gridded labeled Entry for text entry. label - Label widget, returned for testing. ''' label = Label(self.top, text=label_text) label.grid(row=self.row, column=0, sticky="nw") entry = Entry(self.top, textvariable=var, exportselection=0) entry.grid(row=self.row, column=1, sticky="nwe") self.row = self.row + 1 return entry, label
class MyTestDialog( ModalDialog ): def body( self, master ): """ Override the empty ModalDialog.body function to set up the dialog how we want it. """ from tkinter.ttk import Label, Entry Label( master, text="First:" ).grid( row=0 ) Label( master, text="Second:" ).grid( row=1 ) self.e1 = Entry( master ) self.e2 = Entry( master ) self.e1.grid( row=0, column=1 ) self.e2.grid( row=1, column=1 ) return self.e1 # initial focus # end of MyTestDialog.apply def validate( self ): """ Override the empty ModalDialog.validate function to check that the results are how we need them. """ try: int( self.e1.get() ) and int( self.e2.get() ) except ValueError: print( "ERROR: We need two valid integers!" ) return False return True # end of MyTestDialog.validate def apply( self ): """ Override the empty ModalDialog.apply function to process the results how we need them. """ first = int( self.e1.get() ) second = int( self.e2.get() ) print( first, second ) # or something self.result = (first, second,)
def createRow(self,rowNumber): isopach_L = Label(self.innerFrame, text=str(rowNumber+1), width=2) isopach_L.grid(column=0, row=rowNumber+2, padx=(0,5), pady=5) thicknessVar = tkinter.StringVar() thicknessM_E = Entry(self.innerFrame,width=self.entryWidth,textvariable=thicknessVar, justify="right") thicknessM_E.grid(column=1, row=rowNumber+2, pady=5) areaVar = tkinter.StringVar() sqrtAreaKM_E = Entry(self.innerFrame,width=self.entryWidth,textvariable=areaVar, justify="right") sqrtAreaKM_E.grid(column=2, row=rowNumber+2, pady=5) includeVar = tkinter.IntVar() includeCB = tkinter.Checkbutton(self.innerFrame,variable=includeVar, selectimage=self.tickImage) includeCB.grid(column=3,row=rowNumber+2,pady=5) includeCB.invoke() includeCB.bind("<Leave>",self.calculationTimeEstimationFunction) return (isopach_L,None),(thicknessM_E,thicknessVar),(sqrtAreaKM_E,areaVar),(includeCB,includeVar)
def text_query(self, query_lable, original_text=None, accept_func=None): if self._query is not None: return frame = Frame(self.menubar) label = Label(frame, text=query_lable) label.grid(column=0, row=0, sticky=(N, S)) self._accept_func = accept_func entry = Entry(frame) if original_text is not None: entry.insert(0, original_text) entry.original_value = original_text entry.grid(column=1, row=0, sticky=(N,S,W,E)) kb.make_bindings(kb.text_query, {'accept': self.accept_query, 'cancel': lambda e: self.close_query()}, entry.bind) frame.grid(column=self._menucolumn, row=0) self._menucolumn += 1 entry.focus_set() self._query = frame
def body(self, master, cfg={}): "place user dialog widgets" self.config = cfg self.config["OK button"] = False self.site = StringVar() self.site.set(cfg.get("site", "")) self.login = StringVar() self.login.set(cfg.get("user", "")) self.password = StringVar() self.password.set(str(cfg.get("password", ""))) site = Entry(master, width=15, textvariable=self.site) site.grid(column=1, row=0, sticky="e") Label(master, text=_("Site:")).grid(column=0, row=0, sticky="w") loge = Entry(master, width=15, textvariable=self.login) loge.grid(column=1, row=1, sticky="e") Label(master, text=_("Username:"******"w") pase = Entry(master, width=15, textvariable=self.password, show="*") pase.grid(column=1, row=2, sticky="e") Label(master, text=_("Password:"******"w") self.to_remember = IntVar() self.to_remember.set(cfg.get("remember_passwd", 1)) chk1 = Checkbutton(master, text="Remember", variable=self.to_remember) chk1.grid(column=0, row=3, sticky="w", columnspan=2) self.resizable(width=0, height=0) return loge
class Tampil(Tk): def __init__(self): super().__init__() self.dekPrev = myDek() self.dekNext = myDek() self.dekHistory = myDek() self.current = "" #Windows self.title("Stack Using Deque") self.geometry("400x160") #Label self.lblTitle = Label(self, text="Bejjo Parse Browser", foreground="blue") self.lblTitle.grid(row=0, column=2, pady=5, padx=2) self.lblBody = Label(self, text="Welcome") self.lblBody.grid(row=2, column=0, columnspan=4, pady=5, padx=2) #Button self.btnPrev = Button(self, text="<", width=5, state="disabled", command=self.prev) self.btnPrev.grid(row=1, column=0, pady=5, padx=2) self.btnNext = Button(self, text=">", width=5, state="disabled", command=self.next) self.btnNext.grid(row=1, column=1, pady=5, padx=2) self.btnSearch = Button(self, text="Search", width=8, command=self.search) self.btnSearch.grid(row=1, column=3, pady=5, padx=2) self.btnHistory = Button(self, text="History", width=12, command=self.history) self.btnHistory.grid(row=0, column=0, columnspan=2, pady=5, padx=2) self.btnParse = Button(self, text="Parse", width=8, command=self.parse) self.btnParse.grid(row=0, column=3, pady=5, padx=2) #Entry self.txtSearch = Entry(self, width=40) self.txtSearch.grid(row=1, column=2, pady=5, padx=2) def parse(self): if self.btnParse["text"] == "Parse": teks = "Welcome" if self.current != "": teks = "" url = Url(self.current) for x in url: teks += x + "\n" self.lblBody["text"] = teks self.btnParse["text"] = "Close" self.btnHistory["text"] = "History" else: self.btnParse["text"] = "Parse" self.switch_attr() def history(self): if self.btnHistory["text"] == "History": self.lblBody["text"] = self.dekHistory self.btnHistory["text"] = "Close" self.btnParse["text"] = "Parse" else: self.btnHistory["text"] = "History" self.switch_attr() def data(self): teks = "Welcome" if self.current != "": url = Url(self.current) teks = url.title() return teks def switch_attr(self): if len(self.dekPrev) == 0: self.btnPrev["state"] = "disabled" else: self.btnPrev["state"] = "normal" if len(self.dekNext) == 0: self.btnNext["state"] = "disabled" else: self.btnNext["state"] = "normal" self.txtSearch.delete(0, "end") self.txtSearch.insert(0, self.current) teks = self.data() self.lblBody["text"] = teks def prev(self): self.dekNext + self.current self.current = self.dekPrev.back() self.btnHistory["text"] = "History" self.btnParse["text"] = "Parse" self.switch_attr() def next(self): self.dekPrev + self.current self.current = self.dekNext.back() self.btnHistory["text"] = "History" self.btnParse["text"] = "Parse" self.switch_attr() def search(self): url = self.txtSearch.get().strip() if self.current == url and url: self.btnHistory["text"] = "History" self.btnParse["text"] = "Parse" self.switch_attr() elif "http" == url[:4] and len(url.replace( "http", "", 1).strip()) > 5 and "." in url: self.dekPrev + self.current self.current = url self.dekNext = myDek() self.dekHistory.history(self.current) self.btnHistory["text"] = "History" self.btnParse["text"] = "Parse" self.switch_attr() else: messagebox.showinfo("Warning", "Incorrect URL")
def initUI(self): self.master.title("Calculator") # padding (left, top, right, bottom) Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10') self.columnconfigure(0, pad=3) self.columnconfigure(1, pad=3) self.columnconfigure(2, pad=3) self.columnconfigure(3, pad=3) self.rowconfigure(0, pad=3) self.rowconfigure(1, pad=3) self.rowconfigure(2, pad=3) self.rowconfigure(3, pad=3) self.rowconfigure(4, pad=3) entry = Entry(self) entry.grid(row=0, columnspan=4, sticky=W + E) cls = Button(self, text="Cls") cls.grid(row=1, column=0) bck = Button(self, text="Back") bck.grid(row=1, column=1) lbl = Button(self) lbl.grid(row=1, column=2) clo = Button(self, text="Close") clo.grid(row=1, column=3) sev = Button(self, text="7") sev.grid(row=2, column=0) eig = Button(self, text="8") eig.grid(row=2, column=1) nin = Button(self, text="9") nin.grid(row=2, column=2) div = Button(self, text="/") div.grid(row=2, column=3) fou = Button(self, text="4") fou.grid(row=3, column=0) fiv = Button(self, text="5") fiv.grid(row=3, column=1) six = Button(self, text="6") six.grid(row=3, column=2) mul = Button(self, text="*") mul.grid(row=3, column=3) one = Button(self, text="1") one.grid(row=4, column=0) two = Button(self, text="2") two.grid(row=4, column=1) thr = Button(self, text="3") thr.grid(row=4, column=2) mns = Button(self, text="-") mns.grid(row=4, column=3) zer = Button(self, text="0") zer.grid(row=5, column=0) dot = Button(self, text=".") dot.grid(row=5, column=1) equ = Button(self, text="=") equ.grid(row=5, column=2) pls = Button(self, text="+") pls.grid(row=5, column=3) self.pack()
class Sync(Tk): def __init__(self): Tk.__init__(self) self.title("FolderSync") self.geometry("%ix%i" % (self.winfo_screenwidth(), self.winfo_screenheight())) self.protocol("WM_DELETE_WINDOW", self.quitter) self.icon = PhotoImage(master=self, file=IM_ICON) self.iconphoto(True, self.icon) self.rowconfigure(2, weight=1) self.columnconfigure(0, weight=1) # --- icons self.img_about = PhotoImage(master=self, file=IM_ABOUT) self.img_open = PhotoImage(master=self, file=IM_OPEN) self.img_plus = PhotoImage(master=self, file=IM_PLUS) self.img_moins = PhotoImage(master=self, file=IM_MOINS) self.img_sync = PhotoImage(master=self, file=IM_SYNC) self.img_prev = PhotoImage(master=self, file=IM_PREV) self.img_expand = PhotoImage(master=self, file=IM_EXPAND) self.img_collapse = PhotoImage(master=self, file=IM_COLLAPSE) self.original = "" self.sauvegarde = "" # liste des fichiers/dossiers à supprimer avant de lancer la copie car # ils sont de nature différente sur l'original et la sauvegarde self.pb_chemins = [] self.err_copie = False self.err_supp = False # --- init log files l = [ f for f in listdir('/tmp') if re.match(r"foldersync[0-9]+.pid", f) ] nbs = [] for f in l: with open(join('/tmp', f)) as fich: old_pid = fich.read().strip() if exists("/proc/%s" % old_pid): nbs.append(int(re.search(r"[0-9]+", f).group())) else: remove(f) if not nbs: i = 0 else: nbs.sort() i = 0 while i in nbs: i += 1 self.pidfile = PID_FILE % i open(self.pidfile, 'w').write(str(getpid())) self.log_copie = LOG_COPIE % i self.log_supp = LOG_SUPP % i self.logger_copie = setup_logger("copie", self.log_copie) self.logger_supp = setup_logger("supp", self.log_supp) date = datetime.now().strftime('%d/%m/%Y %H:%M') self.logger_copie.info("\n### %s ###\n" % date) self.logger_supp.info("\n### %s ###\n" % date) # --- filenames and extensions that will not be copied exclude_list = split(r'(?<!\\) ', CONFIG.get("Defaults", "exclude_copie")) self.exclude_names = [] self.exclude_ext = [] for elt in exclude_list: if elt: if elt[:2] == "*.": self.exclude_ext.append(elt[1:]) else: self.exclude_names.append(elt.replace("\ ", " ")) # --- paths that will not be deleted self.exclude_path_supp = [ ch.replace("\ ", " ") for ch in split( r'(?<!\\) ', CONFIG.get("Defaults", "exclude_supp")) if ch ] # while "" in self.exclude_path_supp: # self.exclude_path_supp.remove("") self.q_copie = Queue() self.q_supp = Queue() # True si une copie / suppression est en cours self.is_running_copie = False self.is_running_supp = False self.style = Style(self) self.style.theme_use("clam") self.style.configure("TProgressbar", troughcolor='lightgray', background='#387EF5', lightcolor="#5D95F5", darkcolor="#2758AB") self.style.map("TProgressbar", lightcolor=[("disabled", "white")], darkcolor=[("disabled", "gray")]) self.style.configure("folder.TButton", padding=1) # --- menu self.menu = Menu(self, tearoff=False) self.configure(menu=self.menu) # emplacements récents self.menu_recent = Menu(self.menu, tearoff=False) if RECENT: for ch_o, ch_s in RECENT: self.menu_recent.add_command( label="%s -> %s" % (ch_o, ch_s), command=lambda o=ch_o, s=ch_s: self.open(o, s)) else: self.menu.entryconfigure(0, state="disabled") # emplacements favoris self.menu_fav = Menu(self.menu, tearoff=False) self.menu_fav_del = Menu(self.menu_fav, tearoff=False) self.menu_fav.add_command(label="Ajouter", image=self.img_plus, compound="left", command=self.add_fav) self.menu_fav.add_cascade(label="Supprimer", image=self.img_moins, compound="left", menu=self.menu_fav_del) for ch_o, ch_s in FAVORIS: label = "%s -> %s" % (ch_o, ch_s) self.menu_fav.add_command( label=label, command=lambda o=ch_o, s=ch_s: self.open(o, s)) self.menu_fav_del.add_command( label=label, command=lambda nom=label: self.del_fav(nom)) if not FAVORIS: self.menu_fav.entryconfigure(1, state="disabled") # accès aux fichiers log menu_log = Menu(self.menu, tearoff=False) menu_log.add_command(label="Copie", command=self.open_log_copie) menu_log.add_command(label="Suppression", command=self.open_log_suppression) # paramètres, préférences menu_params = Menu(self.menu, tearoff=False) self.copy_links = BooleanVar(self, value=CONFIG.getboolean( "Defaults", "copy_links")) menu_params.add_checkbutton(label="Copier les liens", variable=self.copy_links, command=self.toggle_copy_links) menu_params.add_command(label="Exclusions copie", command=self.exclusion_copie) menu_params.add_command(label="Exclusions supp", command=self.exclusion_supp) self.menu.add_cascade(label="Récents", menu=self.menu_recent) self.menu.add_cascade(label="Favoris", menu=self.menu_fav) self.menu.add_cascade(label="Log", menu=menu_log) self.menu.add_cascade(label="Paramètres", menu=menu_params) self.menu.add_command(image=self.img_prev, compound="center", command=self.list_files_to_sync) self.menu.add_command(image=self.img_sync, compound="center", state="disabled", command=self.synchronise) self.menu.add_command(image=self.img_about, compound="center", command=lambda: About(self)) # sélection chemins frame_paths = Frame(self) frame_paths.grid(row=0, sticky="ew", pady=(10, 0)) frame_paths.columnconfigure(0, weight=1) frame_paths.columnconfigure(1, weight=1) f1 = Frame(frame_paths, height=26) f2 = Frame(frame_paths, height=26) f1.grid(row=0, column=0, sticky="ew") f2.grid(row=0, column=1, sticky="ew") f1.grid_propagate(False) f2.grid_propagate(False) f1.columnconfigure(1, weight=1) f2.columnconfigure(1, weight=1) ## chemin vers original Label(f1, text="Original").grid(row=0, column=0, padx=(10, 4)) self.entry_orig = Entry(f1) self.entry_orig.grid(row=0, column=1, sticky="ew", padx=(4, 2)) self.b_open_orig = Button(f1, image=self.img_open, style="folder.TButton", command=self.open_orig) self.b_open_orig.grid(row=0, column=2, padx=(1, 8)) ## chemin vers sauvegarde Label(f2, text="Sauvegarde").grid(row=0, column=0, padx=(8, 4)) self.entry_sauve = Entry(f2) self.entry_sauve.grid(row=0, column=1, sticky="ew", padx=(4, 2)) self.b_open_sauve = Button(f2, image=self.img_open, width=2, style="folder.TButton", command=self.open_sauve) self.b_open_sauve.grid(row=0, column=5, padx=(1, 10)) # self.b_prev = Button(frame_paths, image=self.img_prev, # command=self.list_files_to_sync) # self.b_prev.grid(row=1, column=4, padx=4) # # self.b_sync = Button(frame_paths, image=self.img_sync, # command=self.synchronise) # self.b_sync.grid(row=1, column=5, padx=(4, 10)) # self.b_sync.state(("disabled", )) # self.b_prev = Button(self, image=self.img_prev, # command=self.list_files_to_sync) # self.b_prev.grid(row=1, sticky="ew", pady=(4, 10), padx=10) paned = PanedWindow(self, orient='horizontal') paned.grid(row=2, sticky="eswn") paned.rowconfigure(0, weight=1) paned.columnconfigure(1, weight=1) paned.columnconfigure(0, weight=1) # --- côté gauche frame_left = Frame(paned) paned.add(frame_left, weight=1) frame_left.rowconfigure(3, weight=1) frame_left.columnconfigure(0, weight=1) # fichiers à copier f_left = Frame(frame_left) f_left.columnconfigure(2, weight=1) f_left.grid(row=2, columnspan=2, pady=(4, 2), padx=(10, 4), sticky="ew") Label(f_left, text="À copier").grid(row=0, column=2) frame_copie = Frame(frame_left) frame_copie.rowconfigure(0, weight=1) frame_copie.columnconfigure(0, weight=1) frame_copie.grid(row=3, column=0, sticky="eswn", columnspan=2, pady=(2, 4), padx=(10, 4)) self.tree_copie = CheckboxTreeview(frame_copie, selectmode='none', show='tree') self.b_expand_copie = Button(f_left, image=self.img_expand, style="folder.TButton", command=self.tree_copie.expand_all) self.b_expand_copie.grid(row=0, column=0) self.b_expand_copie.state(("disabled", )) self.b_collapse_copie = Button(f_left, image=self.img_collapse, style="folder.TButton", command=self.tree_copie.collapse_all) self.b_collapse_copie.grid(row=0, column=1, padx=4) self.b_collapse_copie.state(("disabled", )) self.tree_copie.tag_configure("warning", foreground="red") self.tree_copie.tag_configure("link", font="tkDefaultFont 9 italic", foreground="blue") self.tree_copie.tag_bind("warning", "<Button-1>", self.show_warning) self.tree_copie.grid(row=0, column=0, sticky="eswn") self.scroll_y_copie = Scrollbar(frame_copie, orient="vertical", command=self.tree_copie.yview) self.scroll_y_copie.grid(row=0, column=1, sticky="ns") self.scroll_x_copie = Scrollbar(frame_copie, orient="horizontal", command=self.tree_copie.xview) self.scroll_x_copie.grid(row=1, column=0, sticky="ew") self.tree_copie.configure(yscrollcommand=self.scroll_y_copie.set, xscrollcommand=self.scroll_x_copie.set) self.pbar_copie = Progressbar(frame_left, orient="horizontal", mode="determinate") self.pbar_copie.grid(row=4, columnspan=2, sticky="ew", padx=(10, 4), pady=4) self.pbar_copie.state(("disabled", )) # --- côté droit frame_right = Frame(paned) paned.add(frame_right, weight=1) frame_right.rowconfigure(3, weight=1) frame_right.columnconfigure(0, weight=1) # fichiers à supprimer f_right = Frame(frame_right) f_right.columnconfigure(2, weight=1) f_right.grid(row=2, columnspan=2, pady=(4, 2), padx=(4, 10), sticky="ew") Label(f_right, text="À supprimer").grid(row=0, column=2) frame_supp = Frame(frame_right) frame_supp.rowconfigure(0, weight=1) frame_supp.columnconfigure(0, weight=1) frame_supp.grid(row=3, columnspan=2, sticky="eswn", pady=(2, 4), padx=(4, 10)) self.tree_supp = CheckboxTreeview(frame_supp, selectmode='none', show='tree') self.b_expand_supp = Button(f_right, image=self.img_expand, style="folder.TButton", command=self.tree_supp.expand_all) self.b_expand_supp.grid(row=0, column=0) self.b_expand_supp.state(("disabled", )) self.b_collapse_supp = Button(f_right, image=self.img_collapse, style="folder.TButton", command=self.tree_supp.collapse_all) self.b_collapse_supp.grid(row=0, column=1, padx=4) self.b_collapse_supp.state(("disabled", )) self.tree_supp.grid(row=0, column=0, sticky="eswn") self.scroll_y_supp = Scrollbar(frame_supp, orient="vertical", command=self.tree_supp.yview) self.scroll_y_supp.grid(row=0, column=1, sticky="ns") self.scroll_x_supp = Scrollbar(frame_supp, orient="horizontal", command=self.tree_supp.xview) self.scroll_x_supp.grid(row=1, column=0, sticky="ew") self.tree_supp.configure(yscrollcommand=self.scroll_y_supp.set, xscrollcommand=self.scroll_x_supp.set) self.pbar_supp = Progressbar(frame_right, orient="horizontal", mode="determinate") self.pbar_supp.grid(row=4, columnspan=2, sticky="ew", padx=(4, 10), pady=4) self.pbar_supp.state(("disabled", )) # # lancer synchronisation # self.b_sync = Button(self, image=self.img_sync, # command=self.synchronise) # self.b_sync.grid(row=3, sticky="ew", pady=(4, 10), padx=10) # self.b_sync.state(("disabled", )) # bindings self.entry_orig.bind("<Key-Return>", self.list_files_to_sync) self.entry_sauve.bind("<Key-Return>", self.list_files_to_sync) def exclusion_supp(self): excl = ExclusionsSupp(self) self.wait_window(excl) # paths that will not be deleted self.exclude_path_supp = [ ch.replace("\ ", " ") for ch in split( r'(?<!\\) ', CONFIG.get("Defaults", "exclude_supp")) if ch ] def exclusion_copie(self): excl = ExclusionsCopie(self) self.wait_window(excl) exclude_list = CONFIG.get("Defaults", "exclude_copie").split(" ") self.exclude_names = [] self.exclude_ext = [] for elt in exclude_list: if elt: if elt[:2] == "*.": self.exclude_ext.append(elt[2:]) else: self.exclude_names.append(elt) def toggle_copy_links(self): CONFIG.set("Defaults", "copy_links", str(self.copy_links.get())) def open_log_copie(self): run(["xdg-open", self.log_copie]) def open_log_suppression(self): run(["xdg-open", self.log_supp]) def quitter(self): rep = True if self.is_running_copie or self.is_running_supp: rep = askokcancel( "Confirmation", "Une synchronisation est en cours, êtes-vous sur de vouloir quitter ?" ) if rep: self.destroy() def del_fav(self, nom): self.menu_fav.delete(nom) self.menu_fav_del.delete(nom) FAVORIS.remove(tuple(nom.split(" -> "))) save_config() if not FAVORIS: self.menu_fav.entryconfigure(1, state="disabled") def add_fav(self): sauvegarde = self.entry_sauve.get() original = self.entry_orig.get() if original != sauvegarde and original and sauvegarde: if exists(original) and exists(sauvegarde): if not (original, sauvegarde) in FAVORIS: FAVORIS.append((original, sauvegarde)) save_config() label = "%s -> %s" % (original, sauvegarde) self.menu_fav.entryconfigure(1, state="normal") self.menu_fav.add_command(label=label, command=lambda o=original, s= sauvegarde: self.open(o, s)) self.menu_fav_del.add_command( label=label, command=lambda nom=label: self.del_fav(nom)) def open(self, ch_o, ch_s): self.entry_orig.delete(0, "end") self.entry_orig.insert(0, ch_o) self.entry_sauve.delete(0, "end") self.entry_sauve.insert(0, ch_s) self.list_files_to_sync() def open_sauve(self): sauvegarde = askdirectory(self.entry_sauve.get()) if sauvegarde: self.entry_sauve.delete(0, "end") self.entry_sauve.insert(0, sauvegarde) def open_orig(self): original = askdirectory(self.entry_orig.get()) if original: self.entry_orig.delete(0, "end") self.entry_orig.insert(0, original) def sync(self, original, sauvegarde): """ peuple tree_copie avec l'arborescence des fichiers d'original à copier vers sauvegarde et tree_supp avec celle des fichiers de sauvegarde à supprimer """ errors = [] copy_links = self.copy_links.get() excl_supp = [ path for path in self.exclude_path_supp if commonpath([path, sauvegarde]) == sauvegarde ] def arbo(tree, parent, n): """ affiche l'arborescence complète de parent et renvoie la longueur maximale des items (pour gérer la scrollbar horizontale) """ m = 0 if isdir(parent): try: l = listdir(parent) except Exception as e: errors.append(str(e)) l = [] l.sort(key=lambda x: x.lower()) for item in l: chemin = join(parent, item) if islink(chemin): if copy_links: tree.insert(parent, 'end', chemin, text=item, tags=("whole", "link")) m = max(m, len(item) * 9 + 20 * (n + 1)) elif ((item not in self.exclude_names) and (splitext(item)[-1] not in self.exclude_ext)): tree.insert(parent, 'end', chemin, text=item, tags=("whole", )) m = max(m, len(item) * 9 + 20 * (n + 1)) if isdir(chemin): m = max(m, arbo(tree, chemin, n + 1)) return m def aux(orig, sauve, n, search_supp): m_copie = 0 m_supp = 0 try: lo = listdir(orig) ls = listdir(sauve) except Exception as e: errors.append(str(e)) lo = [] ls = [] lo.sort(key=lambda x: x.lower()) ls.sort(key=lambda x: x.lower()) supp = False copie = False if search_supp: for item in ls: chemin_s = join(sauve, item) if chemin_s not in excl_supp and item not in lo: supp = True self.tree_supp.insert(sauve, 'end', chemin_s, text=item, tags=("whole", )) m_supp = max(m_supp, int(len(item) * 9 + 20 * (n + 1)), arbo(self.tree_supp, chemin_s, n + 1)) for item in lo: chemin_o = join(orig, item) chemin_s = join(sauve, item) if ((item not in self.exclude_names) and (splitext(item)[-1] not in self.exclude_ext)): if item not in ls: # le dossier / fichier n'est pas dans la sauvegarde if islink(chemin_o): if copy_links: copie = True self.tree_copie.insert(orig, 'end', chemin_o, text=item, tags=("whole", "link")) m_copie = max( m_copie, (int(len(item) * 9 + 20 * (n + 1)))) else: copie = True self.tree_copie.insert(orig, 'end', chemin_o, text=item, tags=("whole", )) m_copie = max( m_copie, (int(len(item) * 9 + 20 * (n + 1))), arbo(self.tree_copie, chemin_o, n + 1)) elif islink(chemin_o) and exists(chemin_o): # checking the existence prevent from copying broken links if copy_links: if not islink(chemin_s): self.pb_chemins.append(chemin_o) tags = ("whole", "warning", "link") else: tags = ("whole", "link") self.tree_copie.insert(orig, 'end', chemin_o, text=item, tags=tags) m_copie = max(m_copie, int(len(item) * 9 + 20 * (n + 1))) copie = True elif isfile(chemin_o): # first check if chemin_s is also a file if isfile(chemin_s): if getmtime(chemin_o) // 60 > getmtime( chemin_s) // 60: # le fichier f a été modifié depuis la dernière sauvegarde copie = True self.tree_copie.insert(orig, 'end', chemin_o, text=item, tags=("whole", )) else: self.pb_chemins.append(chemin_o) self.tree_copie.insert(orig, 'end', chemin_o, text=item, tags=("whole", "warning")) elif isdir(chemin_o): # to avoid errors due to unrecognized item types (neither file nor folder nor link) if isdir(chemin_s): self.tree_copie.insert(orig, 'end', chemin_o, text=item) self.tree_supp.insert(sauve, 'end', chemin_s, text=item) c, s, mc, ms = aux( chemin_o, chemin_s, n + 1, search_supp and (chemin_s not in excl_supp)) supp = supp or s copie = copie or c if not c: # nothing to copy self.tree_copie.delete(chemin_o) else: m_copie = max( m_copie, mc, int(len(item) * 9 + 20 * (n + 1))) if not s: # nothing to delete self.tree_supp.delete(chemin_s) else: m_supp = max(m_supp, ms, int(len(item) * 9 + 20 * (n + 1))) else: copie = True self.pb_chemins.append(chemin_o) self.tree_copie.insert(orig, 'end', chemin_o, text=item, tags=("whole", "warning")) m_copie = max( m_copie, (int(len(item) * 9 + 20 * (n + 1))), arbo(self.tree_copie, chemin_o, n + 1)) return copie, supp, m_copie, m_supp self.tree_copie.insert("", 0, original, text=original, tags=("checked", ), open=True) self.tree_supp.insert("", 0, sauvegarde, text=sauvegarde, tags=("checked", ), open=True) c, s, mc, ms = aux(original, sauvegarde, 1, True) if not c: self.tree_copie.delete(original) self.tree_copie.column("#0", minwidth=0, width=0) else: mc = max(len(original) * 9 + 20, mc) self.tree_copie.column("#0", minwidth=mc, width=mc) if not s: self.tree_supp.delete(sauvegarde) self.tree_supp.column("#0", minwidth=0, width=0) else: ms = max(len(sauvegarde) * 9 + 20, mc) self.tree_supp.column("#0", minwidth=ms, width=ms) return errors def show_warning(self, event): x, y = event.x, event.y elem = event.widget.identify("element", x, y) if elem == "padding": orig = self.tree_copie.identify_row(y) sauve = orig.replace(self.original, self.sauvegarde) showwarning( "Attention", "%s et %s ne sont pas de même nature (dossier/fichier/lien)" % (orig, sauve), master=self) def list_files_to_sync(self, event=None): """ display in a treeview the file to copy and the one to delete """ self.pbar_copie.configure(value=0) self.pbar_supp.configure(value=0) self.sauvegarde = self.entry_sauve.get() self.original = self.entry_orig.get() if self.original != self.sauvegarde and self.original and self.sauvegarde: if exists(self.original) and exists(self.sauvegarde): o_s = (self.original, self.sauvegarde) if o_s in RECENT: RECENT.remove(o_s) self.menu_recent.delete("%s -> %s" % o_s) RECENT.insert(0, o_s) self.menu_recent.insert_command( 0, label="%s -> %s" % o_s, command=lambda o=self.original, s=self.sauvegarde: self. open(o, s)) if len(RECENT) == 10: del (RECENT[-1]) self.menu_recent.delete(9) save_config() self.menu.entryconfigure(0, state="normal") self.configure(cursor="watch") self.toggle_state_gui() self.update_idletasks() self.update() self.efface_tree() err = self.sync(self.original, self.sauvegarde) self.configure(cursor="") self.toggle_state_gui() c = self.tree_copie.get_children("") s = self.tree_supp.get_children("") if not (c or s): self.menu.entryconfigure(5, state="disabled") self.b_collapse_copie.state(("disabled", )) self.b_expand_copie.state(("disabled", )) self.b_collapse_supp.state(("disabled", )) self.b_expand_supp.state(("disabled", )) elif not c: self.b_collapse_copie.state(("disabled", )) self.b_expand_copie.state(("disabled", )) elif not s: self.b_collapse_supp.state(("disabled", )) self.b_expand_supp.state(("disabled", )) if err: showerror("Erreurs", "\n".join(err)) run([ "notify-send", "-i", IM_ICON, "FolderSync", "Scan is finished." ]) warnings = self.tree_copie.tag_has('warning') if warnings: showwarning( "Attention", "Certains éléments à copier (en rouge) ne sont pas de même nature sur l'original et la sauvegarde" ) else: showerror("Erreur", "Chemin invalide !") def efface_tree(self): c = self.tree_copie.get_children("") for item in c: self.tree_copie.delete(item) s = self.tree_supp.get_children("") for item in s: self.tree_supp.delete(item) self.b_collapse_copie.state(("disabled", )) self.b_expand_copie.state(("disabled", )) self.b_collapse_supp.state(("disabled", )) self.b_expand_supp.state(("disabled", )) def toggle_state_gui(self): """ toggle the state (normal/disabled) of key elements of the GUI """ if "disabled" in self.b_open_orig.state(): state = "!disabled" for i in range(7): self.menu.entryconfigure(i, state="normal") else: state = "disabled" for i in range(7): self.menu.entryconfigure(i, state="disabled") self.tree_copie.state((state, )) self.tree_supp.state((state, )) self.entry_orig.state((state, )) self.entry_sauve.state((state, )) # self.b_sync.state((state, )) # self.b_prev.state((state, )) self.b_expand_copie.state((state, )) self.b_collapse_copie.state((state, )) self.b_expand_supp.state((state, )) self.b_collapse_supp.state((state, )) self.b_open_orig.state((state, )) self.b_open_sauve.state((state, )) def update_pbar(self): """ dislay the progress of the copy and deletion and put the GUI back in normal state once both processes are done. """ if not self.is_running_copie and not self.is_running_supp: run([ "notify-send", "-i", IM_ICON, "FolderSync", "Sync is finished." ]) self.toggle_state_gui() self.pbar_copie.configure(value=self.pbar_copie.cget("maximum")) self.pbar_supp.configure(value=self.pbar_supp.cget("maximum")) # self.b_sync.state(("disabled", )) self.menu.entryconfigure(5, state="disabled") self.configure(cursor="") self.efface_tree() msg = "" if self.err_copie: msg += "Il y a eu des erreurs lors de la copie, voir %s pour plus de détails.\n" % self.log_copie if self.err_supp: msg += "Il y a eu des erreurs lors de la suppression, voir %s pour plus de détails.\n" % self.log_supp if msg: showerror("Erreur", msg, master=self) else: if not self.q_copie.empty(): self.pbar_copie.configure(value=self.q_copie.get()) if not self.q_supp.empty(): self.pbar_supp.configure(value=self.q_supp.get()) self.update() self.after(50, self.update_pbar) @staticmethod def get_list(tree): """ return the list of files/folders to copy/delete (depending on the tree)""" selected = [] def aux(item): tags = tree.item(item, "tags") if "checked" in tags and "whole" in tags: selected.append(item) elif "checked" in tags or "tristate" in tags: ch = tree.get_children(item) for c in ch: aux(c) ch = tree.get_children("") for c in ch: aux(c) return selected def synchronise(self): """ display the list of files/folders that will be copied / deleted and launch the copy and deletion if the user validates the sync. """ # get files to delete and folder to delete if they are empty a_supp = self.get_list(self.tree_supp) # get files to copy a_copier = self.get_list(self.tree_copie) a_supp_avant_cp = [] for ch in self.pb_chemins: if ch in a_copier: a_supp_avant_cp.append( ch.replace(self.original, self.sauvegarde)) if a_supp or a_copier: Confirmation(self, a_copier, a_supp, a_supp_avant_cp, self.original, self.sauvegarde) def copie_supp(self, a_copier, a_supp, a_supp_avant_cp): """ launch sync """ self.toggle_state_gui() self.configure(cursor="watch") self.update() self.pbar_copie.state(("!disabled", )) self.pbar_supp.state(("!disabled", )) nbtot_copie = len(a_copier) + len(a_supp_avant_cp) self.pbar_copie.configure(maximum=nbtot_copie, value=0) nbtot_supp = len(a_supp) self.pbar_supp.configure(maximum=nbtot_supp, value=0) self.is_running_copie = True self.is_running_supp = True process_copie = Thread(target=self.copie, name="copie", daemon=True, args=(a_copier, a_supp_avant_cp)) process_supp = Thread(target=self.supp, daemon=True, name="suppression", args=(a_supp, )) process_copie.start() process_supp.start() self.update_pbar() def copie(self, a_copier, a_supp_avant_cp): """ copie tous les fichiers/dossiers de a_copier de original vers sauvegarde en utilisant la commande système cp. Les erreurs rencontrées au cours du processus sont inscrites dans ~/.foldersync/copie.log """ self.err_copie = False orig = abspath(self.original) + "/" sauve = abspath(self.sauvegarde) + "/" chdir(orig) self.logger_copie.info("\nCopie: %s -> %s\n" % (self.original, self.sauvegarde)) n = len(a_supp_avant_cp) self.logger_copie.info("\nSuppression avant copie:") for i, ch in zip(range(1, n + 1), a_supp_avant_cp): self.logger_copie.info(ch) p_copie = run(["rm", "-r", ch], stderr=PIPE) self.q_copie.put(i) err = p_copie.stderr.decode() if err: self.err_copie = True self.logger_copie.error(err.strip()) self.logger_copie.info("\nCopie:") for i, ch in zip(range(n + 1, n + 1 + len(a_copier)), a_copier): ch_o = ch.replace(orig, "") self.logger_copie.info("%s -> %s" % (ch_o, sauve)) p_copie = run(["cp", "-ra", "--parents", ch_o, sauve], stderr=PIPE) self.q_copie.put(i) err = p_copie.stderr.decode() if err: self.err_copie = True self.logger_copie.error(err.strip()) self.is_running_copie = False def supp(self, a_supp): """ supprime tous les fichiers/dossiers de a_supp de original vers sauvegarde en utilisant la commande système rm. Les erreurs rencontrées au cours du processus sont inscrites dans ~/.foldersync/suppression.log """ self.err_supp = False self.logger_supp.info("\nSuppression: %s -> %s\n" % (self.original, self.sauvegarde)) for i, ch in enumerate(a_supp): self.logger_supp.info(ch) p_supp = run(["rm", "-r", ch], stderr=PIPE) self.q_supp.put(i + 1) err = p_supp.stderr.decode() if err: self.logger_supp.error(err.strip()) self.err_supp = True self.is_running_supp = False def unlink(self): """Unlink pidfile.""" unlink(self.pidfile)
class TextFrameTry02(Frame): def __init__(self, parent, q): Frame.__init__(self, parent) # self.queue = q self.parent = parent # Status XInitThreads(void) # XInitThreads(void) self.initUI() def callback(self): self.root.quit() def initUI(self): # self.root = tk.Tk() # self.root = Tk() # self.root.protocol("WM_DELETE_WINDOW", self.callback) self.parent.title("TextFrameTry02 init title only") #self.title("TextFrameTry02 init title only") self.pack(fill=BOTH, expand=True) self.grid_columnconfigure(4, weight=1) self.grid_rowconfigure(3, weight=1) lbl1 = Label(self, text="Digits:") lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10) self.ent1 = Entry(self, width=10) self.ent1.insert(END, "4000") self.ent1.grid(row=0, column=1, sticky=W) lbl2 = Label(self, text="Accuracy:") lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10) self.ent2 = Entry(self, width=10) self.ent2.insert(END, "100") self.ent2.grid(row=0, column=3, sticky=W) self.startBtn = Button(self, text="Start", command=self.onStart) self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W) self.pbar = Progressbar(self, mode='indeterminate') self.pbar.grid(row=1, column=1, columnspan=3, sticky=W + E) # self.txt = st.ScrolledText(win) self.txt = st.ScrolledText(self) self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5, columnspan=5, sticky=E + W + S + N) self.txt.insert(INSERT, "\nJust set up this txt.\n") self.txt.insert(INSERT, "Just set up this txt.\n") self.txt.insert(INSERT, "Just set up this txt.\n") self.txt.insert(INSERT, "Just set up this txt.\n") self.txt.insert(INSERT, "Just set up this txt.\n\n") # aKeyStrk = keyboard.read_key() # aKeyStrk = input() aComment = ''' st.insert(tkinter.INSERT, 'Following Ports are open\n' ) st.insert(tkinter.INSERT, str(portlist)) # Creating scrolled text # area widget text_area = st.ScrolledText(win, wrap = tk.WORD, width = 40, height = 10, font = ("Times New Roman", 15)) text_area.grid(column = 0, pady = 10, padx = 10) # Placing cursor in the text area text_area.focus() ''' # self.txt = st.ScrolledText(self.root, wrap = tk.WORD, width = 40, height = 10, font = ("Times New Roman", 15), grid=(row=2, column=0, rowspan=4, padx=10, pady=5, columnspan=5, sticky=E+W+S+N)) # self.txt = st.ScrolledText(width = 40, height = 10, font = ("Times New Roman", 15), grid.row(2), grid.column(0), grid.rowspan(4), grid.padx(10), grid.pady(5), grid.columnspan(5), grid.sticky(E+W+S+N), wrap(tk.WORD)) # self.txt = st.ScrolledText(self) # self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5, columnspan=5, sticky=E+W+S+N) # text_area = st.ScrolledText(win, #wrap = tk.WORD, #width = 40, #height = 10, #font = ("Times New Roman", #15)) # self.root.mainloop() def onStart(self): self.startBtn.config(state=DISABLED) self.txt.delete("1.0", END) self.txt.insert(INSERT, "\n\nNow onStart method is running.\n\n") print(self.onStart, "\nNow onStart method is running.\n") self.digits = int(self.ent1.get()) self.accuracy = int(self.ent2.get()) print("\nonStart, start to process generatePi is next.\n") self.txt.insert( INSERT, "\n\nonStart, start to process to generatePi is next.\n\n") self.parent_conn, self.child_conn = multiprocessing.Pipe() # creating new processes # p1 = multiprocessing.Process(target=sender, args=(parent_conn,msgs)) # p2 = multiprocessing.Process(target=receiver, args=(child_conn,)) msgs = "" # self.p1 = Process(target=self.generatePi) # self.p1 = Process(target=self.generatePi, args=(self.queue, )) self.p1 = Process(target=self.generatePi, args=(self.parent_conn, msgs)) self.p1.start() print("\nonStart, start to parallel process to generatePi started.\n") self.txt.insert( INSERT, "\n\nonStart, start to parallel process to generatePi started.\n\n" ) self.pbar.start(DELAY2) self.after(DELAY1, self.onGetValue(self.child_conn, msgs)) def onGetValue(self, conn, msgs): # if (self.p1.is_alive()): while self.p1.is_alive(): print( "\nonGetValue finds ------------------------- generatePi Process is alive" ) self.txt.insert( INSERT, "\nonGetValue finds ---------------------- generatePi Process is alive\n" ) # self.after(DELAY1, self.onGetValue(conn, msgs)) # self.onGetValue) # return # msg = conn.recv() # self.txt.insert( msg ) time.sleep(0.1) # else: # while 1: # msg = conn.recv() # if msg == "END": # break # print("Received the message: {}".format(msg)) # try: msg = "msg" msg = conn.recv() print("This should be a pi: ", msg) self.txt.insert(END, "\nThis should be a pi: ") # self.queue.get(0)) self.txt.insert(END, msg) # self.queue.get(0)) self.txt.insert(END, "\n") self.txt.insert(INSERT, "\n\nNow running onGetValue else section.\n\n") print("\nNow running onGetValue else section.\n") self.pbar.stop() self.startBtn.config(state=NORMAL) # except conn.Empty: # queue.Empty: # print("\nqueue is PLACEKEEPER empty\n") # self.txt.insert("\nqueue is PLACEKEEPER empty\n") def generatePi(self, conn, msgs): # def generatePi(self, queue): # def generatePi(self): self.queue, , self.parent_conn, msgs # def sender(conn, msgs): getcontext().prec = self.digits pi = Decimal(0) # pi=999 k = 0 n = self.accuracy # self.txt.delete('1.0', END) # clear the outputtext text widget. 1.0 and # self.txt.delete("1.0", "end-1c") #self.txt.focus() # self.txt.delete(1.0,tk.END) # clear the outputtext text widget. 1.0 and tk.END are neccessary. tk implies the tkinter module. If you just want to add text dont incude that line print("\nNow running generatePi section.\n") ##### self.text.put("---------------") self.txt.insert(INSERT, "\n\n---------------\n\n") self.txt.insert(INSERT, "\n\nNow running generatePi section.\n\n") # aComment=''' while k < n: pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - \ (Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5))- \ (Decimal(1)/(8*k+6))) k += 1 # self.txt.insert(INSERT, 'Following Ports are open\n' ) #st.insert(tkinter.INSERT, 'Following Ports are open\n' ) #st.insert(tkinter.INSERT, str(portlist)) # myvar = "the answer is {}".format(answer) # myvar = "the answer is " + str(answer) insertToTxtfr = ("\nTextFrameTry02 is still alive = " + str(self.p1.is_alive()) + "") # insertToTxtfr = ('TextFrameTry02 is still alive = {}'.format(self.p1.is_alive()) # insertToTxtfr = ('TextFrameTry02 is still alive = XXX') print(insertToTxtfr) # queue.put("TextFrameTry02 is still alive = ", self.p1.is_alive()) # queue.put(" ") # outputtext.insert(tk.END,entryvar) # insert the entry widget contents in the text widget. tk.END is necessary. #self.txt.insert(INSERT, insertToTxtfr) # insert the entry widget contents in the text widget. tk.END is necessary. ##### self.txt.update_idletasks() # XInitThreads # self.txt.pack # conn.send( insertToTxtfr ) time.sleep(0.01) # ''' #### self.txt.update_idletasks() # self.txt.pack print("\nNow running print out pi section.\n") self.txt.insert(INSERT, "\n\nNow running print out pi section.\n\n") print(pi) print(self.parent.title(), " frame end") self.txt.insert(INSERT, "\n\nNow running INSERT out pi section.\n\n") self.txt.insert(INSERT, pi) self.txt.insert(INSERT, "\n\nDone INSERTING and printing out pi.\n\n") print("\nDone INSERTING and printing out pi.\n") conn.send(pi) #queue.put(" ") #queue.put("Putting Pi from generatePi function.\n") #queue.put(pi) #queue.put("Done putting Pi from generatePi function.\n") # queue.put(" ") # self.txt.pack print("Returning from generatePi.") return pi
class Query(Toplevel): """Base class for getting verified answer from a user. For this base class, accept any non-blank string. """ def __init__(self, parent, title, message, *, text0='', used_names={}, _htest=False, _utest=False): """Create popup, do not return until tk widget destroyed. Additional subclass init must be done before calling this unless _utest=True is passed to suppress wait_window(). title - string, title of popup dialog message - string, informational message to display text0 - initial value for entry used_names - names already in use _htest - bool, change box location when running htest _utest - bool, leave window hidden and not modal """ Toplevel.__init__(self, parent) self.withdraw() # Hide while configuring, especially geometry. self.parent = parent self.title(title) self.message = message self.text0 = text0 self.used_names = used_names self.transient(parent) self.grab_set() windowingsystem = self.tk.call('tk', 'windowingsystem') if windowingsystem == 'aqua': try: self.tk.call('::tk::unsupported::MacWindowStyle', 'style', self._w, 'moveableModal', '') except: pass self.bind("<Command-.>", self.cancel) self.bind('<Key-Escape>', self.cancel) self.protocol("WM_DELETE_WINDOW", self.cancel) self.bind('<Key-Return>', self.ok) self.bind("<KP_Enter>", self.ok) self.resizable(height=False, width=False) self.create_widgets() self.update_idletasks() # Needed here for winfo_reqwidth below. self.geometry( # Center dialog over parent (or below htest box). "+%d+%d" % ( parent.winfo_rootx() + (parent.winfo_width()/2 - self.winfo_reqwidth()/2), parent.winfo_rooty() + ((parent.winfo_height()/2 - self.winfo_reqheight()/2) if not _htest else 150) ) ) if not _utest: self.deiconify() # Unhide now that geometry set. self.wait_window() def create_widgets(self): # Call from override, if any. # Bind to self widgets needed for entry_ok or unittest. self.frame = frame = Frame(self, padding=10) frame.grid(column=0, row=0, sticky='news') frame.grid_columnconfigure(0, weight=1) entrylabel = Label(frame, anchor='w', justify='left', text=self.message) self.entryvar = StringVar(self, self.text0) self.entry = Entry(frame, width=30, textvariable=self.entryvar) self.entry.focus_set() self.error_font = Font(name='TkCaptionFont', exists=True, root=self.parent) self.entry_error = Label(frame, text=' ', foreground='red', font=self.error_font) self.button_ok = Button( frame, text='OK', default='active', command=self.ok) self.button_cancel = Button( frame, text='Cancel', command=self.cancel) entrylabel.grid(column=0, row=0, columnspan=3, padx=5, sticky=W) self.entry.grid(column=0, row=1, columnspan=3, padx=5, sticky=W+E, pady=[10,0]) self.entry_error.grid(column=0, row=2, columnspan=3, padx=5, sticky=W+E) self.button_ok.grid(column=1, row=99, padx=5) self.button_cancel.grid(column=2, row=99, padx=5) def showerror(self, message, widget=None): #self.bell(displayof=self) (widget or self.entry_error)['text'] = 'ERROR: ' + message def entry_ok(self): # Example: usually replace. "Return non-blank entry or None." self.entry_error['text'] = '' entry = self.entry.get().strip() if not entry: self.showerror('blank line.') return None return entry def ok(self, event=None): # Do not replace. '''If entry is valid, bind it to 'result' and destroy tk widget. Otherwise leave dialog open for user to correct entry or cancel. ''' entry = self.entry_ok() if entry is not None: self.result = entry self.destroy() else: # [Ok] moves focus. (<Return> does not.) Move it back. self.entry.focus_set() def cancel(self, event=None): # Do not replace. "Set dialog result to None and destroy tk widget." self.result = None self.destroy()
class MemberChecker(PanedWindow): def __init__(self, parent): PanedWindow.__init__(self, parent, background="white") self.parent = parent self.init_data() self.init_log() self.init_ui() self.update_status() def init_data(self): self.data_store = api.DataStore() def init_log(self): self.entrance_log = entrance_log.EntranceLog() def init_ui(self): self.parent.title("Member Checker") self.columnconfigure(3, weight=3) self.pack(fill=BOTH, expand=True) self.input = StringVar() self.input_entry = Entry(self, textvariable=self.input) self.input_entry.bind('<Return>', self.submit) self.input_entry.grid(row=0, column=0, columnspan=3, sticky=E + W) self.result = StringVar() self.result_label = Label(self, textvariable=self.result) self.result_label.grid(row=3, column=0, columnspan=3, sticky=E + W) self.name = StringVar() name_label = Label(self, textvariable=self.name) name_label.grid(row=2, column=0, columnspan=3, sticky=E + W) self.status = StringVar() status_label = Label(self, textvariable=self.status) status_label.grid(row=4, column=0, columnspan=4, sticky=E + W) submit_button = Button(self, text="Submit", command=self.submit) submit_button.grid(row=1, column=2) enter_without_card_button = Button(self, text="Enter without card", command=self.enter_without_card) enter_without_card_button.grid(row=1, column=0) enter_member_without_card_button = Button(self, text="Enter member without card", command=self.enter_member_without_card) enter_member_without_card_button.grid(row=1, column=1) self.entrance_log_list = Listbox(self) self.entrance_log_list.grid(row=0, column=3, rowspan=4, sticky=E + W + S + N) self.input_entry.focus() def load_data(self): if messagebox.askyesno("Load new API Data", "Are you sure you want to load the new API data? All previous data will be removed. The program might be unresponsive for a few seconds, but don't kill it, please! It has feelings too."): self.data_store.load_api_data() def enter_by_identification(self, identification): member = self.data_store.find_member_by_identification(identification) if member is None: if messagebox.askyesno("Not a member", "This university identification is not registered as a member. Do you want to let them in as a non-member?"): self.enter_non_member_by_identification(identification) else: self.enter_member(member) def enter_by_barcode(self, barcode): member = self.data_store.find_member_by_barcode(barcode) if member is None: if messagebox.askyesno("Not a member", "This barcode is not registered as a member. Do you want to let them in as a non-member?"): self.enter_non_member_by_barcode(barcode) else: self.enter_member(member) def enter_non_member_by_identification(self, identification): self.entrance_log.enter_non_member_by_identification(identification) self.enter_non_member() def enter_non_member_by_barcode(self, barcode): self.entrance_log.enter_non_member_by_barcode(barcode) self.enter_non_member() def enter_without_card(self): self.clear_result() self.entrance_log.enter_without_card() self.enter_non_member() self.input_entry.focus() def enter_member(self, member): inside_result = self.entrance_log.is_member_inside(member) if inside_result[0]: if not messagebox.askyesno("Already inside", "This membership card has already been used to enter at {}. Are you sure you want to register it again? Normally you should let this person enter without card (and bill them accordingly).".format( inside_result[1])): return self.entrance_log.enter_member(member) self.result.set('Member!') self.result_label.configure(background='green') self.name.set(member['firstName'] + ' ' + member['lastName']) self.update_status() def enter_non_member(self): self.result.set('Not a member!') self.result_label.configure(background='red') self.name.set('Not in the database') self.update_status() def enter_member_without_card(self): name = self.input.get() if len(name) == 0: messagebox.showinfo('Name required', 'Please enter the name of this person!') return self.entrance_log.enter_member_without_card(name) self.result.set('Member without card!') self.result_label.configure(background="orange") self.name.set('') self.input.set('') self.update_status() def clear_result(self): self.result.set('') self.result_label.configure(background='white') self.name.set('') def submit(self, event=None): self.clear_result() entry = self.input.get() if helpers.is_valid_identification(entry): self.enter_by_identification(entry) elif helpers.is_valid_barcode(entry): self.enter_by_barcode(entry) else: messagebox.showinfo('Invalid entry', 'The data entered was not recognized as a valid bar code or a valid university identification. You should click \'enter without card\' to let this person in.') return self.input.set('') self.input_entry.focus() def clear_log(self): if messagebox.askyesno("Clear log", "Are you sure you want to clear the log of all people who entered?"): self.entrance_log.clear_log() self.update_status() def update_status(self): self.status.set("{} members inside. Total: {}".format(self.entrance_log.members_inside_count(), self.entrance_log.inside_count())) logs = self.entrance_log.get_latest_logs(15) self.entrance_log_list.delete(0, 15) for l in logs: s = l['timestamp'] + ": " data = l['data'] if 'member_id' in data: member = self.data_store.find_member(data['member_id']) s += member['firstName'] + " " + member['lastName'] elif 'barcode' in data: s += data['barcode'] elif 'identification' in data: s += data['identification'] elif 'name' in data: s += '[no card]' + data['name'] else: s += "-" self.entrance_log_list.insert(0, s)
class FrameDownload(Frame): def __init__(self, master=None, option=()): super().__init__(master=master) self.master = master self.master.title('Download information') self.option = option self.setupUI() def setupUI(self): # build UI base on URLS if self.option[2] == SEARCH: # title window label_title = Label(self, text='Search Photos') label_title.config(anchor='center', foreground='white', background='#8e44ad') label_title.grid(row=0, column=0, columnspan=6, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=5, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config(textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=5, sticky='w') # query self.label_query = Label(self, text='Query') self.label_query.grid(row=1, column=0, sticky='e') self.var_entry_query = StringVar() self.entry_query = Entry(self) self.entry_query.config(textvariable=self.var_entry_query, state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # total self.var_total = StringVar() self.var_total.set('Total') self.label_total = Label(self, textvariable=self.var_total) self.label_total.grid(row=1, column=2, sticky='e') self.var_entry_total = IntVar() self.entry_total = Entry(self) self.entry_total.config(textvariable=self.var_entry_total, state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # total pages self.label_total_page = Label(self, text='Total pages:') self.label_total_page.grid(row=1, column=4, sticky='e') self.var_entry_total_pages = IntVar() self.entry_total_page = Entry(self) self.entry_total_page.config(textvariable=self.var_entry_total_pages, state='readonly') self.entry_total_page.grid(row=1, column=5, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid(row=3, column=0, columnspan=6, sticky='wesn') # self.change_ui() elif self.option[2] == LIST: # title window label_title = Label(self, text='List of Photos') label_title.config( anchor='center', foreground='white', background='#2c3e50') label_title.grid(row=0, column=0, columnspan=4, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=3, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config( textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=3, sticky='w') # query self.label_query = Label(self, text='Query:') self.label_query.grid(row=1, column=0, sticky='e') self.entry_query = Entry(self) self.entry_query.insert(0,'LIST') self.entry_query.config(state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # amount self.label_total = Label(self, text='Amount:') self.label_total.grid(row=1, column=2, sticky='e') self.entry_total = Entry(self) self.entry_total.insert(0,self.option[3]['per_page']) self.entry_total.config(state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid( row=3, column=0, columnspan=4, sticky='wesn') # self.change_ui() elif self.option[2] == RANDOM: # title window label_title = Label(self, text='Random Photos') label_title.config( anchor='center', foreground='white', background='#16a085') label_title.grid(row=0, column=0, columnspan=4, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=3, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config( textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=3, sticky='w') # query self.label_query = Label(self, text='Query') self.label_query.grid(row=1, column=0, sticky='e') self.entry_query = Entry(self) self.entry_query.insert(0,'RANDOM') self.entry_query.config(state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # amount self.label_total = Label(self, text='Amount') self.label_total.grid(row=1, column=2, sticky='e') self.var_entry_total = IntVar() if self.option[3]['count'] > 30: self.var_entry_total.set(30) else: self.var_entry_total.set(self.option[3]['count']) self.entry_total = Entry(self) self.entry_total.config(textvariable=self.var_entry_total, state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid( row=3, column=0, columnspan=4, sticky='wesn') def change_ui(self): if self.option[2] == SEARCH: r = requests.get(self.option[2], params=self.option[3]) if r.status_code == 200: # get urls based on quality j = json.loads(r.text) total = j['total'] total_pages = j['total_pages'] results = j['results'] self.var_entry_query.set(self.option[3]['query']) self.var_entry_total.set(total) self.var_entry_total_pages.set(total_pages) self.entry_query.update_idletasks() self.entry_total.update_idletasks() self.entry_total_page.update_idletasks() # random photos elif self.option[2] == RANDOM: r = requests.get(self.option[2], params=self.option[3]) if r.status_code == 200: # get result j = json.loads(r.text) results = j elif self.option[2] == LIST: r = requests.get(self.option[2], params=self.option[3]) if r.status_code == 200: # get result j = json.loads(r.text) results = j self.download(results) def download(self, results): for i in results: name = i['id'] url = i['urls'][self.option[1]] time.sleep(1) # delay time to send request try: request.urlretrieve(url, self.option[0]+'/'+name+'.jpg') except Exception as x: # re download if have a problem print('have problem', x) time.sleep(1) self.progress['value'] += 100/len(results) self.var_progress.set('{}%'.format(self.progress['value'])) # show image downloaded image = Image.open(self.option[0]+'/'+name+'.jpg') width = int(self.winfo_width()) height = int(width*image.height/image.width) self.photo = ImageTk.PhotoImage( image.resize((width, height), Image.ANTIALIAS)) self.label_image_downloaded.config(image=self.photo) self.label_image_downloaded.image = self.photo self.progress.update_idletasks() self.message_done = messagebox.showinfo('Info', 'Done') self.master.destroy()
class StreamFrame(Frame): def __init__(self, master): super(StreamFrame, self).__init__(master) self.root = master # check if user has saved the training sentiment analyzers pol_checkfile = os.path.exists('files/sa_polarity.pickle') subj_checkfile = os.path.exists('files/sa_subjectivity.pickle') if not (pol_checkfile and subj_checkfile): # if we cant find the SA files # These frames will hold the widgets nofiles_frm = Frame( self ) # this for the the warning message and the back and exit buttons nofiles_frm.grid(row=3, column=0, pady=5) exit_frm = Frame(self) # exit frame, contains back and exit button exit_frm.grid(row=4, column=0, pady=5) message = "SA files not found." read_write.log_message("[WARN] (frames.StreamFrame) : " + message) message += "\nClick Start Training first to train the NLTK classifiers." Label(nofiles_frm, text=message).grid(row=0, column=0, padx=10, pady=5) self.mng_stream_btn = Button( nofiles_frm, text="Start Stream") # ignore this, if there are no tweets # Build the widgets for nofiles_frm self.back_btn = Button(exit_frm, text="Back") self.back_btn.grid(row=1, column=1, ipadx=5, ipady=3, pady=15) self.exit_btn = Button(exit_frm, text="Exit", command=self.safe_exit) self.exit_btn.grid(row=1, column=3, ipadx=5, ipady=3, padx=15, pady=10) else: # These frames will hold the widgets label_frm = Frame(self) # this for the label and entry label_frm.grid(row=0, column=2, padx=10, pady=10, ipady=20, ipadx=20) # Frame for keywords self.keywords_frm = Frame( self ) # this will be hidden until user wants to see previous keywords self.keywords_frm.grid(row=0, column=3, rowspan=3, pady=15) # Build the widgets for label_frm Label(label_frm, text="Keyword:").grid(row=0, column=0, padx=20) self.keyword_entry = Entry(label_frm, width=30) self.keyword_entry.grid(row=0, column=1, columnspan=3) # Build the widgets for button_frm self.mng_stream_btn = Button( label_frm, text="Start Stream") # this will change from start to stop self.mng_stream_btn.grid(row=1, column=1, ipadx=5, ipady=3, pady=20) self.pause_stream_btn = Button( label_frm, text="Pause Stream") # if user starts stream, show this button self.pause_stream_btn.grid(row=1, column=3, ipadx=5, ipady=3, padx=10, pady=20) self.pause_stream_btn.grid_remove() # Build the widgets for keywords_frm self.manage_keywords_btn = Button( self.keywords_frm, command=self.show_keywords, text=">>>") # this will change into "<<<" when user clicks it self.manage_keywords_btn.grid(row=0, column=0, ipadx=5, ipady=3, padx=10) # Build the widgets for exit_frm self.back_btn = Button(label_frm, text="Back") self.back_btn.grid(row=2, column=1, ipadx=5, ipady=3, pady=15) self.exit_btn = Button(label_frm, text="Exit", command=self.safe_exit) self.exit_btn.grid(row=2, column=3, ipadx=5, ipady=3, padx=15, pady=10) # this method creates a new list box and populates it with the data from keywords.json def show_keywords(self): # first re-configure the button to show the desired text and change the command into hiding method self.manage_keywords_btn.config(text="<<<", command=self.hide_keywords) self.previous_keywords = read_write.read_keywords( ) # get any previous keywords # if there are keywords and the list is not empty if len(self.previous_keywords) > 0: # build the list box self.keyword_lb = Listbox(self.keywords_frm, height=10) self.keyword_lb.grid(column=1, row=0, pady=10, padx=5, sticky=(N, S, E, W)) # add a binding method self.keyword_lb.bind('<Double-1>', self.select_keyword) # and add the OK button. This happens here, because we don'w want a button without a list box self.select_keyword_btn = Button(self.keywords_frm, text="OK", command=self.select_keyword) self.select_keyword_btn.grid(row=3, column=1, ipady=3, ipadx=5, pady=10) # adding the keywords to the list box counter = 0 for keyword in self.previous_keywords: self.keyword_lb.insert(counter, keyword) counter += 1 # Colorize alternating lines of the listbox for i in range(0, len(self.previous_keywords), 2): self.keyword_lb.itemconfigure(i, background='#f0f0ff') # this method changes the button again and it is called to hide the list box def hide_keywords(self): self.manage_keywords_btn.config(text=">>>", command=self.show_keywords) try: # this may result to an error, because we can call hide_keywords before we initialize # the list box. This happening if no keywords are present in keywords.json self.keyword_lb.destroy() self.select_keyword_btn.destroy() except AttributeError: pass def select_keyword(self, *args): idxs = self.keyword_lb.curselection() if len(idxs) == 1: idx = int(idxs[0]) name = self.previous_keywords[idx] self.keyword_entry.delete(0, "end") self.keyword_entry.insert(0, name) def safe_exit(self): x = messagebox.askyesno(title="Exit", message="Are you sure you want to exit?", icon="question") if x: stream_util.stream_controller.stop() read_write.log_message("[INFO]" + stream_util.LOG_NAME + "Exiting...") self.root.destroy()
class DbFrame(Frame): def __init__(self, master): super(DbFrame, self).__init__(master) self.root = master self.client = db_utils.get_client() # get any previous data on last.json previous_data = read_write.read_last() # Two frames will hold the widgets label_frm = Frame(self) # the labels and entries label_frm.grid(row=0, pady=10, padx=50) button_frm = Frame(self) # the buttons button_frm.grid(row=1, pady=5, padx=50) # Build the widgets for label_frm Label(label_frm, text="Database:").grid(column=2, row=0, pady=10, padx=5) Label(label_frm, text="Collection:").grid(column=2, row=1, padx=5) self.db_entry = Entry(label_frm, width=30) self.db_entry.grid(column=3, row=0, pady=10) self.collection_entry = Entry(label_frm, width=30) self.collection_entry.grid(column=3, row=1) # Add data to entries if any data on last.json try: if previous_data["database"] is not "": self.db_entry.insert(0, previous_data["database"]) except KeyError as e: message = "[ERROR] (frames.DbFrame) : KeyError: " + str(e) read_write.log_message(message) try: if previous_data["collection"] is not "": self.collection_entry.insert(0, previous_data["collection"]) except KeyError as e: message = "[ERROR] (frames.DbFrame) : KeyError: " + str(e) read_write.log_message(message) # Build the widgets for button_frm self.next_btn = Button(button_frm, text="Next") self.next_btn.grid(column=2, row=0, pady=10, padx=4, ipadx=2, ipady=2) self.back_btn = Button(button_frm, text="Back") self.back_btn.grid(column=4, row=0, pady=10, padx=4, ipadx=2, ipady=2) self.previous_dbs_btn = Button(button_frm, text="Show databases", command=self.show_dbs) self.previous_dbs_btn.grid(column=2, row=1, ipadx=2, ipady=2) self.previous_collection_btn = Button(button_frm, text="Show collections", command=self.show_collections) self.previous_collection_btn.grid(column=4, row=1, ipadx=2, ipady=2) # Build the widgets for dbs_frm self.selected_db_var = StringVar() self.selected_collection_var = StringVar() # this method populates the dbs radio-buttons. This happen every time, show_dbs method runs def populate_dbs(self): def select_db(): self.selected_db_var = db_var selected_db = str(db_var.get()) self.db_entry.delete(0, "end") self.db_entry.insert(0, selected_db) # we add the drop button, only if a radio-button is pressed self.drop_db_btn = Button(self.dbs_frm, text="Drop database", command=self.drop_db) self.drop_db_btn.grid(row=db_counter, column=2, pady=10, ipadx=5, ipady=2) db_var = StringVar() db_list = self.client.database_names( ) # we get the available database names of this connection db_counter = 0 read_write.log_message("[INFO] (frames.DbFrame) : DBs found: " + str(db_list)) for name in db_list: r = Radiobutton(self.dbs_frm, text=name, variable=db_var, value=name, command=select_db) r.grid(row=db_counter, column=2, pady=2) db_counter += 1 # this method populates the collection radio-buttons. This happen every time, show_collections method runs def populate_collections(self): def select_collection(): self.selected_collection_var = collection_var selected_collection = str(collection_var.get()) self.collection_entry.delete(0, "end") self.collection_entry.insert(0, selected_collection) # we add the drop button, only if a radio-button is pressed self.drop_collection_btn = Button(self.collections_frm, text="Drop collection", command=self.drop_collection) self.drop_collection_btn.grid(row=collection_counter, column=2, pady=10, ipadx=5, ipady=2) collection_var = StringVar() collection_list = [ ] # we get the available collection names of this connection but # only if a database name already exists if self.db_entry.get() is not "": collection_list = self.client[self.db_entry.get( )].collection_names(include_system_collections=False) collection_counter = 0 # this counter is responsible to place the radio-buttons into correct row for name in collection_list: r = Radiobutton(self.collections_frm, text=name, variable=collection_var, value=name, command=select_collection) r.grid(row=collection_counter, column=2, pady=2) collection_counter += 1 def show_dbs(self): # create the frame self.dbs_frm = Frame(self) # the frame that will show the dbs self.dbs_frm.grid(row=2, pady=5, padx=50) try: self.populate_dbs() except ServerSelectionTimeoutError as e: read_write.log_message("[ERROR]" + LOG_NAME + "ServerSelectionTimeoutError: " + str(e)) messagebox.showerror("Error", "Lost Connection to the DB") except AutoReconnect as e: read_write.log_message("[ERROR]" + LOG_NAME + "AutoReconnect: " + str(e)) messagebox.showerror("Error", "Lost Connection to the DB") try: # if collections already shown, we need to hide them, but if not, this will raise an exception self.hide_collections() except AttributeError: pass # change the button's text and grid the frame self.previous_dbs_btn.config(command=self.hide_dbs, text="Hide databases") self.dbs_frm.grid() def hide_dbs(self): self.previous_dbs_btn.config(command=self.show_dbs, text="Show databases") self.dbs_frm.grid_remove() def show_collections(self): # create the frame self.collections_frm = Frame( self) # the frame that will show the collections self.collections_frm.grid(row=2, pady=5, padx=50) try: self.populate_collections() except ServerSelectionTimeoutError as e: read_write.log_message("[ERROR]" + LOG_NAME + "ServerSelectionTimeoutError: " + str(e)) messagebox.showerror("Error", "Lost Connection to the DB") except AutoReconnect as e: read_write.log_message("[ERROR]" + LOG_NAME + "AutoReconnect: " + str(e)) messagebox.showerror("Error", "Lost Connection to the DB") try: # if dbs already shown, we need to hide them, but if not, this will raise an exception self.hide_dbs() except AttributeError: pass # change the button's text and grid the frame self.previous_collection_btn.config(command=self.hide_collections, text="Hide collections") self.collections_frm.grid() def hide_collections(self): self.previous_collection_btn.config(command=self.show_collections, text="Show collections") self.collections_frm.grid_remove() def drop_db(self): name = self.selected_db_var.get() answer = messagebox.askokcancel( title="Are you sure?", message="Are you sure you want to delete " + name, default="cancel", parent=self.root) if answer: read_write.log_message( "[INFO] (frames.DbFrame) : Dropping database '" + name + "'") try: self.client.drop_database(name) except ServerSelectionTimeoutError as e: read_write.log_message("[ERROR]" + LOG_NAME + "ServerSelectionTimeoutError: " + str(e)) messagebox.showerror("Error", "Lost Connection to the DB") return self.hide_dbs() self.show_dbs() def drop_collection(self): name = self.selected_collection_var.get() answer = messagebox.askokcancel( title="Are you sure?", message="Are you sure you want to delete " + name, default="cancel", parent=self.root) if answer: read_write.log_message( "[INFO] (frames.DbFrame) : Dropping collection '" + name + "'") db_name = self.db_entry.get() try: self.client[db_name].drop_collection(name) except ServerSelectionTimeoutError as e: read_write.log_message("[ERROR]" + LOG_NAME + "ServerSelectionTimeoutError: " + str(e)) messagebox.showerror("Error", "Lost Connection to the DB") return self.hide_collections() self.show_collections()
class qbtConvertor(Tk): """ GUI Application for migration from uTorrent to qBittorrent """ def __init__(self): Tk.__init__(self) self.title("uT to qBt convertor") #main frame self.main_frame = Frame(self, padding="3 3 12 12") self.main_frame.grid(column=0, row=0, sticky=(N, W, E, S)) self.main_frame.columnconfigure(0, weight=1) self.main_frame.rowconfigure(0, weight=1) #uT part self.ut_data = StringVar() self.ut_label = Label(self.main_frame, text="uT data") self.ut_label.grid(column=0, row=1, sticky=(W)) self.ut_entry = Entry(self.main_frame, width=100, textvariable=self.ut_data) self.ut_entry.grid(column=1, row=1, sticky=(W)) self.ut_button = Button(self.main_frame, text="Browse", command=self.load_file) self.ut_button.grid(column=2, row=1) #qBt part self.qbt_folder = StringVar() self.qbt_label = Label(self.main_frame, text="qBt folder") self.qbt_label.grid(column=0, row=4, sticky=(W)) self.qbt_entry = Entry(self.main_frame, width=100, textvariable=self.qbt_folder) self.qbt_entry.grid(column=1, row=4, sticky=(W)) self.qbt_button = Button(self.main_frame, text="Browse", command=self.open_dir) self.qbt_button.grid(column=2, row=4, sticky=(W, E)) #convertor self.convertor_button = Button(self.main_frame, text="Convert", command=self.convert, width=50) self.convertor_button.grid(column=1, columnspan=2, row=5) self.progress_bar = Progressbar(self.main_frame, orient=HORIZONTAL, length=300, mode="indeterminate") self.progress_bar.grid(column=1, columnspan=3, row=6) #set padding for each element for child in self.main_frame.winfo_children(): child.grid_configure(padx=5, pady=5) def convert(self): message = messagebox if not self.qbt_folder.get() or not self.ut_data.get(): message.showerror("ERROR", "Specify paths!") return self.progress_bar.start() convertor(self.ut_data.get(), self.qbt_folder.get()) self.progress_bar.stop() def load_file(self): file_name = filedialog.askopenfilename(filetypes=(("UT resume file", "*.dat"), ("All", "*"))) if file_name: self.ut_data.set(file_name) def open_dir(self): dir_name = filedialog.askdirectory() if dir_name: self.qbt_folder.set(dir_name)
class Example(Frame): def __init__(self, parent, q): Frame.__init__(self, parent) self.queue = q self.parent = parent self.initUI() def initUI(self): self.parent.title("Pi computation") self.pack(fill=BOTH, expand=True) self.grid_columnconfigure(4, weight=1) self.grid_rowconfigure(3, weight=1) lbl1 = Label(self, text="Digits:") lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10) self.ent1 = Entry(self, width=10) self.ent1.insert(END, "4000") self.ent1.grid(row=0, column=1, sticky=W) lbl2 = Label(self, text="Accuracy:") lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10) self.ent2 = Entry(self, width=10) self.ent2.insert(END, "100") self.ent2.grid(row=0, column=3, sticky=W) self.startBtn = Button(self, text="Start", command=self.onStart) self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W) self.pbar = Progressbar(self, mode='indeterminate') self.pbar.grid(row=1, column=1, columnspan=3, sticky=W+E) self.txt = scrolledtext.ScrolledText(self) self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5, columnspan=5, sticky=E+W+S+N) def onStart(self): self.startBtn.config(state=DISABLED) self.txt.delete("1.0", END) self.digits = int(self.ent1.get()) self.accuracy = int(self.ent2.get()) self.p1 = Process(target=self.generatePi, args=(self.queue,)) self.p1.start() self.pbar.start(DELAY2) self.after(DELAY1, self.onGetValue) def onGetValue(self): if (self.p1.is_alive()): self.after(DELAY1, self.onGetValue) return else: try: self.txt.insert('end', self.queue.get(0)) self.txt.insert('end', "\n") self.pbar.stop() self.startBtn.config(state=NORMAL) except queue.Empty: print("queue is empty") def generatePi(self, queue): getcontext().prec = self.digits time.sleep(10) pi = Decimal(0) k = 0 n = self.accuracy while k < n: pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - (Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5)) - (Decimal(1)/(8*k+6))) k += 1 print(self.p1.is_alive()) queue.put(pi) print("end")
class BookManagerUi(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() self.db = dao('blist') #데이터베이스 관리 클래스 생성 def initUI(self): self.parent.title("Book Manager") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) self.columnconfigure(0, pad=3) self.columnconfigure(1, pad=3) self.columnconfigure(2, pad=3) self.rowconfigure(0, pad=3) self.rowconfigure(1, pad=3) self.rowconfigure(2, pad=3) self.rowconfigure(3, pad=3) self.rowconfigure(4, pad=3) self.rowconfigure(5, pad=3) self.rowconfigure(6, pad=3) self.input_bname='' self.input_aname='' self.input_price=0 self.delete='' lb_bookname = Label(self, text="bookname:") lb_bookname.grid(row=0, column =0 ,sticky=W, pady=4, padx=5) self.entry_bookname = Entry(self) self.entry_bookname.grid(row=0, column = 1 ) lb_author = Label(self, text="author:") lb_author.grid(row=0, column =2,sticky=W, pady=4, padx=5) self.entry_author = Entry(self) self.entry_author.grid(row=0, column = 3 ) lb_price = Label(self, text="price:") lb_price.grid(row=0, column =4 ,sticky=W, pady=4, padx=5) self.entry_price = Entry(self) self.entry_price.grid(row=0, column = 5 ,padx=15) abtn = Button(self, text="Add", command=lambda:self.clicked_add()) abtn.grid(row=0, column=6) sbtn = Button(self, text="Serach", command = lambda:self.clicked_search()) sbtn.grid(row=1, column=6, pady=4) dbtn = Button(self, text="Delete", command = lambda:self.clicked_delete()) dbtn.grid(row=2, column=6, pady=4) self.lb = Listbox(self) self.lb.grid(row=3,column = 0, columnspan = 6,rowspan= 4, sticky = E+W+S+N) self.lb.bind("<<ListboxSelect>>", self.onSelect) #삭제를 위한 select부분 def onSelect(self,val): sender = val.widget idx = sender.curselection() value = sender.get(idx) self.delete = value # 데이터 추가 버튼 def clicked_add(self): bname =self.entry_bookname.get() aname = self.entry_author.get() price = self.entry_price.get() self.lb.delete(0,END) # 입력받을 데이터가 모자란지 검사 if(len(bname) >0 and len(aname)>0 and len(price)>0 ): #가격에 문자를 입력했을 경우 처리 try: priceI = eval(price) except: self.lb.insert(END,"you input wrong price. it must be integer") #사용자가 입력한 내용중 중복된 책이름이 있을 경우(저자는 책이 여러가지일 수 있으니 제외) rec = self.db.excute_select(bname,'') if ( len(rec) >0): self.lb.insert(END,bname +" is already in the database") else: self.db.insert_data(bname,aname,priceI) # 모든 조건 만족시 데이터 입력 수행 r =self.db.excute_select(bname,aname) for rs in r: self.lb.insert(END,str(rs)) else: s = StringVar() self.entry_price.config(textvariable = s) self.lb.insert(END,"you have to input more values") #검색버튼 def clicked_search(self): bname =self.entry_bookname.get() aname = self.entry_author.get() self.lb.delete(0,END) #책이름 또는 저자이름 둘중 하나만입력 되어도 검색 가능하도록 if(len(bname)>0 or len(aname)>0 ): rec = self.db.excute_select(bname,aname) for r in rec: self.lb.insert(END,str(r)) else: self.lb.insert(END,"you have to input more values(bookname or author") #삭제 버튼 def clicked_delete(self): self.lb.delete(0,END) q = self.db.excute_delete(self.delete) self.lb.insert(END,q+' is delete from database')
class MarkovDemo(Frame): "MarkovDemo(master=None, **kw) -> MarkovDemo instance" TEXT = dict(height=2, width=46, wrap=WORD) # Text Options GRID = dict(padx=5, pady=5) # Grid Options # Initialize a MarkovDemo instance with a GUI for interaction. def __init__(self, master=None, **kw): "Initialize the MarkovDemo instance's widgets and settings." super().__init__(master, **kw) self.build_widgets() self.place_widgets() self.setup_widgets() self.grid_rowconfigure(2, weight=1) self.grid_rowconfigure(3, weight=1) self.grid_columnconfigure(0, weight=1) self.key = self.primer = None def build_widgets(self): "Build the various widgets that will be used in the program." # Create processing frame widgets. self.processing_frame = LabelFrame(self, text='Processing Mode:') self.mode_var = StringVar(self, 'encode') self.decode_button = Radiobutton(self.processing_frame, text='Decode Cipher-Text', command=self.handle_radiobuttons, value='decode', variable=self.mode_var) self.encode_button = Radiobutton(self.processing_frame, text='Encode Plain-Text', command=self.handle_radiobuttons, value='encode', variable=self.mode_var) self.freeze_var = BooleanVar(self, False) self.freeze_button = Checkbutton(self.processing_frame, text='Freeze Key & Primer', command=self.handle_checkbutton, offvalue=False, onvalue=True, variable=self.freeze_var) # Create encoding frame widgets. self.encoding_frame = LabelFrame(self, text='Encoding Options:') self.chain_size_label = Label(self.encoding_frame, text='Chain Size:') self.chain_size_entry = Entry(self.encoding_frame) self.plain_text_label = Label(self.encoding_frame, text='Plain-Text:') self.plain_text_entry = Entry(self.encoding_frame) # Create input frame widgets. self.input_frame = LabelFrame(self, text='Input Area:') self.input_text = ScrolledText(self.input_frame, **self.TEXT) # Create output frame widgets. self.output_frame = LabelFrame(self, text='Output Area:') self.output_text = ScrolledText(self.output_frame, **self.TEXT) def place_widgets(self): "Place the widgets where they belong in the MarkovDemo frame." # Locate processing frame widgets. self.processing_frame.grid(sticky=EW, **self.GRID) self.decode_button.grid(row=0, column=0, **self.GRID) self.encode_button.grid(row=0, column=1, **self.GRID) self.freeze_button.grid(row=0, column=2, **self.GRID) # Locate encoding frame widgets. self.encoding_frame.grid(sticky=EW, **self.GRID) self.chain_size_label.grid(row=0, column=0, sticky=W, **self.GRID) self.chain_size_entry.grid(row=0, column=1, sticky=EW, **self.GRID) self.plain_text_label.grid(row=1, column=0, sticky=W, **self.GRID) self.plain_text_entry.grid(row=1, column=1, sticky=EW, **self.GRID) self.encoding_frame.grid_columnconfigure(1, weight=1) # Locate input frame widgets. self.input_frame.grid(sticky=NSEW, **self.GRID) self.input_text.grid(sticky=NSEW, **self.GRID) self.input_frame.grid_rowconfigure(0, weight=1) self.input_frame.grid_columnconfigure(0, weight=1) # Locate output frame widgets. self.output_frame.grid(sticky=NSEW, **self.GRID) self.output_text.grid(sticky=NSEW, **self.GRID) self.output_frame.grid_rowconfigure(0, weight=1) self.output_frame.grid_columnconfigure(0, weight=1) def setup_widgets(self): "Setup each widget's configuration for the events they handle." self.input_text.bind('<Key>', self.handle_key_events) self.input_text.bind('<Control-Key-a>', self.handle_control_a) self.input_text.bind('<Control-Key-/>', lambda event: 'break') self.output_text['state'] = DISABLED self.output_text.bind('<Control-Key-a>', self.handle_control_a) self.output_text.bind('<Control-Key-/>', lambda event: 'break') ######################################################################## # Take care of any special event needing dedicated processing. def handle_radiobuttons(self): "Change the interface based on the encoding / decoding setting." if self.encrypting: self.freeze_button.grid() if not self.freeze_var.get(): self.encoding_frame.grid() else: self.freeze_button.grid_remove() if not self.freeze_var.get(): self.encoding_frame.grid_remove() self.handle_key_events(None) def handle_checkbutton(self): "Change the interface based on the key / primer freeze setting." if self.freeze_var.get(): self.encoding_frame.grid_remove() else: self.encoding_frame.grid() def handle_key_events(self, event): "Schedule refreshing the output area after an input area event." if event is None or event.char and event.state | 0o11 == 0o11: self.after_idle(self.refresh) @staticmethod def handle_control_a(event): "Select all text in the widget associated with the given event." event.widget.tag_add(SEL, 1.0, END + '-1c') return 'break' ######################################################################## # Handle interface's updates when either encoding or decoding. def refresh(self): "Refresh the output based on the value of the input." text = self.input_text.get(1.0, END + '-1c') if not text: self.output = text elif self.encrypting: self.encode(text) else: self.decode(text) def output(self, value): "Set the text in the output area to the string value." self.output_text['state'] = NORMAL self.output_text.delete(1.0, END) self.output_text.insert(END, value) if self.encrypting and self.freeze_var.get(): self.output_text.see(END) self.output_text['state'] = DISABLED output = property(fset=output, doc='Output area property.') @property def chain_size(self): "Chain size for the Markov chains used when encrypting." try: value = ast.literal_eval(self.chain_size_entry.get()) assert isinstance(value, int) and 2 <= value <= 256 return value except: self.chain_size_entry.delete(0, END) self.chain_size_entry.insert(0, '2') return 2 @property def plain_text(self): "Plain text or ignored characters in encryption process." try: value = self.repr_to_obj(self.plain_text_entry.get(), '') assert isinstance(value, str) return value except: self.plain_text_entry.delete(0, END) return '' ######################################################################## # Encrypt a string for display in the interface's output area. def encode(self, string): "Encode the string and show the cipher-text in the output." try: cipher = self.build_cipher(string) except ValueError: self.output = '' except: self.output = traceback.format_exc() else: self.output = self.build_header() + '\n\n' + cipher def build_cipher(self, string): "Build cipher-text based on plain-text and return answer." if self.key and self.freeze_var.get(): cipher, primer = me.encrypt_str(string, self.key, self.primer) else: args = string, self.chain_size, self.plain_text cipher, self.key, self.primer = me.auto_encrypt_str(*args) return cipher def build_header(self): "Build header from key and primer values in current use." header = '\n'.join(map(self.bytes_to_repr, self.key.data)) header += '\n' + self.bytes_to_repr(self.primer.data) return header ######################################################################## # Decrypt a string for display in the interface's output area. def decode(self, string): "Decode encrypted message and display plain-text in output." try: cipher = self.extract_keys(string) text = self.extract_text(cipher) except ValueError: self.output = '' except: self.output = traceback.format_exc() else: self.output = text def extract_keys(self, string): "Extract keys to decryption and return the cipher-text area." header, cipher = string.split('\n\n', 1) *key, primer = map(self.repr_to_obj, header.split('\n')) self.key, self.primer = me.Key(tuple(key)), me.Primer(primer) return cipher def extract_text(self, string): "Extract text message from string using built key and primer." text, primer = me.decrypt_str(string, self.key, self.primer) return text ######################################################################## # Provide some special methods to simplify the program's code. @property def encrypting(self): "Encrypting boolean stating current operations mode." return {'encode': True, 'decode': False}[self.mode_var.get()] @staticmethod def bytes_to_repr(obj): "Convert bytes object into suitable representation." if not isinstance(obj, bytes): raise TypeError('Object must be a bytes instance!') return repr(obj)[2:-1] @staticmethod def repr_to_obj(string, prefix='b'): "Convert representation into an equivalent object." for template in '{}"{}"', "{}'{}'": try: return ast.literal_eval(template.format(prefix, string)) except: pass raise ValueError('Cannot convert {!r} to object!'.format(string)) @classmethod def main(cls): "Create context for demo and run a test instance." NoDefaultRoot() root = Tk() root.minsize(420, 330) root.title('Markov Demo 2') test = cls(root) test.grid(sticky=NSEW) root.grid_rowconfigure(0, weight=1) root.grid_columnconfigure(0, weight=1) root.mainloop()
class HelpSource(Query): "Get menu name and help source for Help menu." # Used in ConfigDialog.HelpListItemAdd/Edit, (941/9) def __init__(self, parent, title, *, menuitem='', filepath='', used_names={}, _htest=False, _utest=False): """Get menu entry and url/local file for Additional Help. User enters a name for the Help resource and a web url or file name. The user can browse for the file. """ self.filepath = filepath message = 'Name for item on Help menu:' super().__init__(parent, title, message, text0=menuitem, used_names=used_names, _htest=_htest, _utest=_utest) def create_widgets(self): super().create_widgets() frame = self.frame pathlabel = Label(frame, anchor='w', justify='left', text='Help File Path: Enter URL or browse for file') self.pathvar = StringVar(self, self.filepath) self.path = Entry(frame, textvariable=self.pathvar, width=40) browse = Button(frame, text='Browse', width=8, command=self.browse_file) self.path_error = Label(frame, text=' ', foreground='red', font=self.error_font) pathlabel.grid(column=0, row=10, columnspan=3, padx=5, pady=[10, 0], sticky=W) self.path.grid(column=0, row=11, columnspan=2, padx=5, sticky=W + E, pady=[10, 0]) browse.grid(column=2, row=11, padx=5, sticky=W + S) self.path_error.grid(column=0, row=12, columnspan=3, padx=5, sticky=W + E) def askfilename(self, filetypes, initdir, initfile): # htest # # Extracted from browse_file so can mock for unittests. # Cannot unittest as cannot simulate button clicks. # Test by running htest, such as by running this file. return filedialog.Open(parent=self, filetypes=filetypes)\ .show(initialdir=initdir, initialfile=initfile) def browse_file(self): filetypes = [("HTML Files", "*.htm *.html", "TEXT"), ("PDF Files", "*.pdf", "TEXT"), ("Windows Help Files", "*.chm"), ("Text Files", "*.txt", "TEXT"), ("All Files", "*")] path = self.pathvar.get() if path: dir, base = os.path.split(path) else: base = None if platform[:3] == 'win': dir = os.path.join(os.path.dirname(executable), 'Doc') if not os.path.isdir(dir): dir = os.getcwd() else: dir = os.getcwd() file = self.askfilename(filetypes, dir, base) if file: self.pathvar.set(file) item_ok = SectionName.entry_ok # localize for test override def path_ok(self): "Simple validity check for menu file path" path = self.path.get().strip() if not path: #no path specified self.showerror('no help file path specified.', self.path_error) return None elif not path.startswith(('www.', 'http')): if path[:5] == 'file:': path = path[5:] if not os.path.exists(path): self.showerror('help file path does not exist.', self.path_error) return None if platform == 'darwin': # for Mac Safari path = "file://" + path return path def entry_ok(self): "Return apparently valid (name, path) or None" self.entry_error['text'] = '' self.path_error['text'] = '' name = self.item_ok() path = self.path_ok() return None if name is None or path is None else (name, path)
class HostFrame(Frame): def __init__(self, master): super(HostFrame, self).__init__(master) self.root = master # get any previous data on last.json previous_data = read_write.read_last() # Three frames will hold the widgets label_frm = Frame(self) # this will hold the labels label_frm.grid(row=0, pady=10, padx=50) button_frm = Frame(self) # this will hold the buttons button_frm.grid(row=1, pady=5, padx=50) self.hosts_frm = Frame(self) # this will hold the previous hosts self.hosts_frm.grid(row=2, pady=5, padx=50) self.hosts_frm.grid_remove( ) # but we need to show it, only if user wants # Build the widgets for label_frm Label(label_frm, text="Host:").grid(column=2, row=0, pady=10, padx=5) Label(label_frm, text="Port:").grid(column=2, row=1, padx=5) self.host_entry = Entry(label_frm, width=30) self.host_entry.grid(column=3, row=0, pady=10) self.port_entry = Entry(label_frm, width=30) self.port_entry.grid(column=3, row=1) # Add data to entries if any data on last.json try: if previous_data["host"] is not "": self.host_entry.insert(0, previous_data["host"]) self.port_entry.insert(0, previous_data["port"]) except KeyError as e: message = "[ERROR] (frames.HostFrame): KeyError: " + str(e) read_write.log_message(message) # Build the widgets for button_frm self.next_btn = Button(button_frm, text="Next") self.next_btn.grid(column=2, row=0, pady=10, padx=4, ipadx=2, ipady=2) self.exit_btn = Button(button_frm, text="Exit", command=self.root.destroy) self.exit_btn.grid(column=4, row=0, pady=10, padx=4, ipadx=2, ipady=2) self.show_previous_btn = Button(button_frm, text="Show previous hosts", command=self.show_hosts) self.show_previous_btn.grid(column=2, row=1, columnspan=3, ipadx=2, ipady=2) # Build the widgets for hosts_frm def select_host(): selected_data = str(var.get()).split(":") self.host_entry.delete(0, "end") self.host_entry.insert(0, selected_data[0]) self.port_entry.delete(0, "end") self.port_entry.insert(0, selected_data[1]) # populate the hosts_frm with Radio-buttons that show previous connections data = read_write.read_mongo() var = StringVar() counter = 0 # this will show in which row each radio-button will be on the frame for json_object in data: if json_object["host"] is not "": option = json_object["host"] + ":" + str( json_object["port"]) # format host:port r = Radiobutton(self.hosts_frm, text=option, variable=var, value=option, command=select_host) r.grid(row=counter, column=2, pady=2) counter += 1 # these 2 methods, will show or hide the populated hosts on hosts_frm radio-buttons def show_hosts(self): self.show_previous_btn.config(command=self.hide_hosts, text="Hide previous hosts") self.hosts_frm.grid() def hide_hosts(self): self.show_previous_btn.config(command=self.show_hosts, text="Show previous hosts") self.hosts_frm.grid_remove()
class MainWindow(mp.Process): """Defines the main control window and all its control logic. As Tkinter only allows to create root windwo (Tk()) in the main process, this is implemented as its own subprocess that will open the window with a call to self.run() Args: connector_dict: Dictionary create by calling multiprocessing.Manger().dict() message_q: Queue that will be polled every few seconds. Elements in queue will be plotted to the internal text field. start_analysis_e: Event signaling if analysis can be started connected_e: Event signaling that LSL streams are connected ready_for_connection_e: Event signaling that LSL streams have been selected in GUI save_e: Event signaling that data should be saved. """ def __init__(self, connector_dict: Dict, message_q: mp.Queue, start_recording_e: mp.Event, start_analysis_e: mp.Event, connected_e: mp.Event, ready_for_connection_e: mp.Event, save_e: mp.Event): super().__init__() self.connector_dict = connector_dict self.message_q = message_q self.start_recording_e = start_recording_e self.start_analysis_e = start_analysis_e self.ready_for_connection_e = ready_for_connection_e self.connected_e = connected_e self.save_e = save_e self.master = None # Parameters self.eeg_stream = None self.eeg_streams_dict = None self.marker_stream = None self.marker_streams_dict = None self.channel_select = None self.update_interval = None self.record_time = None self.y_min = None self.y_max = None self.save_filename = None self.filter_check = None self.squared_check = None self.connected = None # Widgets self.eeg_stream_label = None self.eeg_stream_combobox = None self.eeg_stream_button = None self.marker_stream_label = None self.marker_stream_combobox = None self.marker_stream_button = None self.filter_checkbutton_label = None self.filter_checkbutton = None self.connect_button = None self.seperator = None self.start_recording_btn = None self.record_time_label = None self.Separator_2 = None self.update_interval_label = None self.update_interval_combobox = None self.start_analysis_btn = None self.channel_select_label = None self.channel_select_combobox = None self.squared_label = None self.squared_checkbtn = None self.update_ylim_btn = None self.y_min_label = None self.y_min_entry = None self.y_max_label = None self.y_max_entry = None self.seperator = None self.save_label = None self.save_entry = None self.save_btn = None self.text_console = None def build_main_window(self): # Hack to make tkinter work in other process than main from tkinter import Tk, StringVar, Text, HORIZONTAL, EW, IntVar from tkinter.ttk import Separator, Combobox, Button, Label, Entry, Checkbutton self.master = Tk() # Parameters self.eeg_stream = StringVar() self.eeg_streams_dict = {} self.marker_stream = StringVar() self.marker_streams_dict = {} self.channel_select = IntVar() self.channel_select.set(0) self.update_interval = IntVar() self.update_interval.set(0) self.record_time = StringVar() self.record_time.set("00:00 minutes recorded") self.y_min = IntVar() self.y_min.set(-10) self.y_max = IntVar() self.y_max.set(10) self.save_filename = StringVar() self.save_filename.set("1") self.filter_check = IntVar() self.filter_check.set(1) self.squared_check = IntVar() self.squared_check.set(0) self.connected = False self.print_from_queue() # Widgets self.eeg_stream_label = Label(self.master, text='EEG LSL-stream:') self.eeg_stream_label.grid(row=0, column=0) self.eeg_stream_combobox = Combobox(self.master, textvariable=self.eeg_stream) self.eeg_stream_combobox.configure(state='disabled') self.eeg_stream_combobox.grid(row=0, column=1) self.eeg_stream_button = Button( self.master, text='Refresh', command=lambda: self.find_streams('EEG', self.eeg_stream_combobox, self.eeg_streams_dict, self. eeg_stream)) self.eeg_stream_button.grid(row=0, column=2) self.marker_stream_label = Label(self.master, text='Marker LSL-stream:') self.marker_stream_label.grid(row=1, column=0) self.marker_stream_combobox = Combobox(self.master, textvariable=self.marker_stream) self.marker_stream_combobox.configure(state='disabled') self.marker_stream_combobox.grid(row=1, column=1) self.marker_stream_button = Button( self.master, text='Refresh', command=lambda: self.find_streams( 'P300_Marker', self.marker_stream_combobox, self. marker_streams_dict, self.marker_stream)) self.marker_stream_button.grid(row=1, column=2) self.filter_checkbutton_label = Label( self.master, text='Filter (Butter, Order 4, Cutoff: 1, 30):') self.filter_checkbutton_label.grid(row=2, column=0) self.filter_checkbutton = Checkbutton(self.master, variable=self.filter_check, text='') self.filter_checkbutton.grid(row=2, column=1) self.connect_button = Button(self.master, text='Connect', command=self.connect_streams) self.connect_button.grid(row=2, column=2) self.connect_button.configure(state='disabled') self.seperator = Separator(self.master, orient=HORIZONTAL) self.seperator.grid(row=3, column=0, columnspan=3, sticky=EW) self.start_recording_btn = Button(self.master, text='Start recoding', command=self.start_recording) self.start_recording_btn.grid(row=4, column=2) self.start_recording_btn.configure(state='disabled') self.record_time_label = Label(self.master, textvariable=self.record_time) self.record_time_label.grid(row=4, column=1) self.Separator_2 = Separator(self.master) self.Separator_2.grid(row=5, column=0, columnspan=3, sticky=EW) self.update_interval_label = Label(self.master, text='Update interval (seconds):') self.update_interval_label.grid(row=6, column=0) self.update_interval_combobox = Combobox( self.master, textvariable=self.update_interval) self.update_interval_combobox.bind('<<ComboboxSelected>>', self.update_connector_dict) self.update_interval_combobox.grid(row=6, column=1) self.update_interval_combobox['values'] = list(range(10)) self.update_interval_combobox.configure(state='disabled') self.start_analysis_btn = Button(self.master, text='Start analysis', command=self.start_analysis) self.start_analysis_btn.grid(row=6, column=2) self.start_analysis_btn.configure(state='disabled') self.channel_select_label = Label(self.master, text='Channel to display:') self.channel_select_label.grid(row=7, column=0) self.channel_select_combobox = Combobox( self.master, textvariable=self.channel_select) self.channel_select_combobox.bind('<<ComboboxSelected>>', self.update_connector_dict) self.channel_select_combobox.grid(row=7, column=1) self.channel_select_combobox.configure(state='disabled') self.squared_label = Label(self.master, text='squared') self.squared_label.grid(row=8, column=0) self.squared_checkbtn = Checkbutton(self.master, variable=self.squared_check) self.squared_checkbtn.grid(row=8, column=1) self.squared_checkbtn.configure(state='disabled') self.update_ylim_btn = Button(self.master, text='Update', command=self.update_connector_dict) self.update_ylim_btn.grid(row=8, column=2) self.update_ylim_btn.configure(state='disabled') self.y_min_label = Label(self.master, text='Y min:') self.y_min_label.grid(row=9, column=0) self.y_min_entry = Entry(self.master, textvariable=self.y_min) self.y_min_entry.grid(row=9, column=1) self.y_min_entry.configure(state='disabled') self.y_max_label = Label(self.master, text='Y max:') self.y_max_label.grid(row=10, column=0) self.y_max_entry = Entry(self.master, textvariable=self.y_max) self.y_max_entry.grid(row=10, column=1) self.y_max_entry.configure(state='disabled') self.seperator = Separator(self.master, orient=HORIZONTAL) self.seperator.grid(row=11, column=0, columnspan=3, sticky=EW) self.save_label = Label(self.master, text='Filename:') self.save_label.grid(row=12, column=0) self.save_entry = Entry(self.master, textvariable=self.save_filename) self.save_entry.grid(row=12, column=1) self.save_entry.configure(state='disabled') self.save_btn = Button(self.master, text='Save', command=self.save) self.save_btn.grid(row=12, column=2) self.save_btn.configure(state='disabled') self.text_console = Text(self.master) self.text_console.grid(row=15, column=0, rowspan=3, columnspan=3) self.text_console.configure(state='disabled') def save(self): self.update_connector_dict() self.save_e.set() def update_channel_select(self): num_channels = self.connector_dict['number of channels'] self.channel_select_combobox['values'] = list(range(num_channels)) def start_recording(self): self.connect_button.configure(state='disabled') self.start_recording_btn.configure(state='disabled') self.channel_select_combobox.configure(state='normal') self.update_interval_combobox.configure(state='normal') self.y_min_entry.configure(state='normal') self.y_max_entry.configure(state='normal') self.update_ylim_btn.configure(state='normal') self.squared_checkbtn.configure(state='normal') self.update_channel_select() self.update_recording_time() self.start_recording_e.set() self.start_analysis_btn.configure(state='normal') def update_recording_time(self): num_samples = self.connector_dict['sample count'] samplerate = self.connector_dict['samplerate'] number_of_seconds = int(num_samples / samplerate) minutes = number_of_seconds // 60 remaining_seconds = number_of_seconds % 60 result_string = '{:02}:{:02} minutes recorded'.format( minutes, remaining_seconds) self.record_time.set(result_string) self.master.after(1000, self.update_recording_time) def start_analysis(self): self.start_analysis_btn.configure(state='disabled') self.save_btn.configure(state='normal') self.save_entry.configure(state='normal') self.update_connector_dict() self.start_analysis_e.set() def find_streams(self, stream_type, widget, stream_dict, var): stream_dict.clear() timeout = 3 self.print_to_console('Searching for ' + stream_type + ' streams... (timeout = ' + str(timeout) + ' seconds)') streams = resolve_byprop('type', stream_type, timeout=timeout) if not streams: self.print_to_console('No stream found.') return widget.configure(state='normal') stream_list = [] for stream in streams: stream_dict[stream.name()] = stream stream_list.append(stream.name()) widget['values'] = stream_list if len(streams) >= 1: var.set(streams[0].name()) self.print_to_console(str(len(streams)) + ' Stream(s) found!') self.test_if_two_streams() def test_if_two_streams(self): if self.eeg_stream.get() is not '' and self.marker_stream.get( ) is not '': self.connect_button.configure(state='normal') else: self.connect_button.configure(state='disabled') def print_to_console(self, text_to_print): text_to_print = str(text_to_print) self.text_console.configure(state='normal') self.text_console.insert('end', text_to_print + '\n') self.text_console.configure(state='disabled') def print_from_queue(self): if not self.message_q.empty(): self.print_to_console(self.message_q.get()) self.master.after(500, self.print_from_queue) # noinspection PyUnusedLocal def update_connector_dict(self, event=None): self.connector_dict['update interval'] = self.update_interval.get() self.connector_dict['channel select'] = self.channel_select.get() self.connector_dict['eeg streamname'] = self.eeg_stream.get() self.connector_dict['marker streamname'] = self.marker_stream.get() self.connector_dict['y lim'] = [self.y_min.get(), self.y_max.get()] self.connector_dict['savefile'] = self.save_filename.get() self.connector_dict['filter'] = self.filter_check.get() self.connector_dict['squared'] = self.squared_check.get() def connect_streams(self): self.eeg_stream_combobox.configure(state='disabled') self.eeg_stream_button.configure(state='disabled') self.marker_stream_combobox.configure(state='disabled') self.marker_stream_button.configure(state='disabled') self.filter_checkbutton.configure(state='disabled') self.connect_button.configure(state='disabled') self.update_connector_dict() self.ready_for_connection_e.set() self.connected_e.wait() self.start_recording_btn.configure(state='normal') def run(self): self.build_main_window() self.master.mainloop()
def init(metrics_data: dict): top_window = Tk() # main widget properties top_window.geometry(f'{metrics_data["width"]}x{metrics_data["height"]}') top_window.iconphoto(False, PhotoImage(file=f'../{metrics_data["icon"]}')) top_window.configure(bg=metrics_data['background']) top_window.title(metrics_data['title']) def play(track_path: str, duration: int) -> None: playsound(track_path, False) top_window.after(duration * 1000, lambda: play(track_path, duration)) def pick_directory(): # TODO: set $HOME directory as default (may be in config) path_save = filedialog.askdirectory().strip() if path_save: input_directory.delete(0, END) input_directory.insert(0, path_save) def make_request(): author: str = input_author.get().strip() path_save: str = input_directory.get().strip() if not author.strip(): messagebox.showerror('🚫 Error occurred!', 'Empty string is not allowed as author\'s name.') return 1 # directory to save should be present -- chosen or default print('author:', author) print('directory to save:', path_save) pass def close(): top_window.destroy() top_window.quit() # UI label_guide = Label(top_window, text=metrics_data['guide'], font=('Arial Bold', 23)) label_guide.grid(column=0, row=0, padx=(14, 5), pady=(20, 50)) input_author = Entry(top_window, width=50) input_author.grid(row=8, column=0) input_author.focus() input_directory = Entry(top_window, width=50) input_directory.grid(row=9, column=0) button_choose = Button(top_window, text='Choose', command=pick_directory) button_choose.grid(row=9, column=1) Separator(orient='horizontal') button_go = Button(top_window, text='Go!', command=make_request) button_go.grid(row=10, column=0) top_window.protocol('WM_DELETE_WINDOW', close) play(f'../{metrics_data["track"]}', 83) top_window.mainloop()
def _gui(): try: from tkinter import Tk, ttk, filedialog, messagebox, StringVar, IntVar from tkinter.ttk import Button, Entry, Frame, Label, LabelFrame, Notebook, Radiobutton, Style except: sys.exit("Unable to load tkinter. Aborting.") def _check_single(): #check the input and accordingly give the output... for the f_single tab if txt_f_single_entry.get()=="": lbl_f_single_result.config(text="", style="TLabel") elif check_afm(txt_f_single_entry.get()): lbl_f_single_result.config(text="Έγκυρο ΑΦΜ.", style="valid.TLabel") else: lbl_f_single_result.config(text="Άκυρο ΑΦΜ.", style="invalid.TLabel") def _select_input_file(): strv_f_file_input.set(filedialog.askopenfilename(title="Άνοιγμα αρχείου")) if strv_f_file_input.get() != "" and strv_f_file_output.get() != "": btn_f_file_submit.config(state="normal") else: btn_f_file_submit.config(state="disabled") #TODO a much better mechanism to enable / disable btn_f_file_submit is needed. def _select_output_file(): strv_f_file_output.set(filedialog.asksaveasfilename(title="Αποθήκευση ως...")) if strv_f_file_input.get() != "" and strv_f_file_output.get() != "": btn_f_file_submit.config(state="normal") else: btn_f_file_submit.config(state="disabled") def _check_file():#TODO this could / should be merged with the TUI version... input_filepath = strv_f_file_input.get() output_filepath = strv_f_file_output.get() filter_output = intvar_filter_sel.get() try: input_file = open(input_filepath, "r") output_file = open(output_filepath, "w") except: messagebox.showerror(title="Σφάλμα", message="Αδυναμία διαχείρησης των αρχείων που ορίσατε.\n\nΠαρακαλώ επιβεβαιώστε πως το αρχείο με τα δεδομένα υπάρχει, πως έχετε δικαιώματα ανάγνωσης, και πως έχετε δικαιώματα εγγραφής στον κατάλογο εξαγωγής των αποτελεσμάτων.") return counter = {True:0, False:0} for entry in input_file: validation = check_afm(entry.strip()) counter[validation]+=1 if filter_output == 3 and validation == False: output_file.write(entry) elif filter_output == 2 and validation == True: output_file.write(entry) elif filter_output == 1: output_file.write(entry.strip() + "\t" + str(validation) + "\n\r") lbl_f_file_result.config(text="Σύνολο: "+str(counter[True]+counter[False])+"\nΈγκυρα: "+str(counter[True])+"\nΆκυρα: "+str(counter[False])) #create the window main_window = Tk() main_window.title("Έλεγχος εγκυρότητας Α.Φ.Μ. (v 2.0)") main_window.geometry("600x180") main_window.minsize(600,180) #fool arround with styling style = ttk.Style() style.configure("valid.TLabel", background="green") style.configure("empty.TLabel", background="white") style.configure("invalid.TLabel", background="red") style.configure("TNotebook", padding = 10) #create the Notebook tabs = Notebook(main_window) f_single = Frame(tabs) f_file = Frame(tabs) tabs.add(f_single, text="Μεμονομένα Α.Φ.Μ.") tabs.add(f_file, text="Λίστα από αρχείο")#add state="disabled" prior to git push until ready tabs.pack(anchor="nw") #add some widgets in f_single tab lbl_f_single_instructions = Label(f_single, text="Εισάγετε έναν ΑΦΜ για έλεγχο") lbl_f_single_instructions.grid(column=0, row=0) lbl_f_single_result = Label(f_single, text="", width=10, justify="center") lbl_f_single_result.grid(column=1, row=0, rowspan=2, sticky="ewns") txt_f_single_entry = Entry(f_single, width=11) txt_f_single_entry.focus() txt_f_single_entry.bind("<KeyRelease>", lambda e: _check_single() ) txt_f_single_entry.grid(column=0,row=1) #btn_f_single_submit = Button(f_single, text="Έλεγχος", command=_check_single) #btn_f_single_submit.grid(column=0,row=2) #add some widgets in f_file tab lbl_f_file_finput = Label(f_file, text="Άνοιγμα...") lbl_f_file_finput.grid(column=0, row=0) strv_f_file_input = StringVar() txt_f_file_finput = Entry(f_file, textvariable = strv_f_file_input) txt_f_file_finput.grid(column=1, row=0) btn_f_file_finput = Button(f_file, text="...", width=3, command=_select_input_file) btn_f_file_finput.grid(column=2, row=0, sticky="W") lbl_f_file_foutput = Label(f_file, text="Αποθήκευση ως...") lbl_f_file_foutput.grid(column=0, row=1) strv_f_file_output = StringVar() txt_f_file_foutput = Entry(f_file, textvariable = strv_f_file_output) txt_f_file_foutput.grid(column=1, row=1) btn_f_file_foutput = Button(f_file, text="...", width=3, command=_select_output_file) btn_f_file_foutput.grid(column=2, row=1, sticky="W") lf_filter = LabelFrame(f_file, text="Επιστροφή") lf_filter.grid(column=3, row=0, rowspan=2, sticky="ewns") intvar_filter_sel = IntVar() rb_filter_all = Radiobutton(lf_filter, text="Όλων", variable=intvar_filter_sel, value=1) #TODO maybe add command rb_filter_all.pack(anchor="w") rb_filter_all.invoke() rb_filter_true = Radiobutton(lf_filter, text="Έγκυρων", variable=intvar_filter_sel, value=2) rb_filter_true.pack(anchor="w") rb_filter_false = Radiobutton(lf_filter, text="Άκυρων", variable=intvar_filter_sel, value=3) rb_filter_false.pack(anchor="w") lf_result = LabelFrame(f_file, text="Σύνοψη") lf_result.grid(column=4, row=0, rowspan=2, sticky="ewns") lbl_f_file_result = Label(lf_result, text="", width=12)#TODO bring results lbl_f_file_result.pack() btn_f_file_submit = Button(f_file, text="Επεξεργασία", state="disabled", command=_check_file) btn_f_file_submit.grid(column=0, row=2, columnspan=3) btn_main_exit = Button(main_window, text="Έξοδος", command=sys.exit) btn_main_exit.pack(anchor="se") main_window.mainloop()
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent, name="frame") self.parent = parent self.initUI() def initUI(self): self.parent.title("Pi computation") self.pack(fill=BOTH, expand=True) self.grid_columnconfigure(4, weight=1) self.grid_rowconfigure(3, weight=1) lbl1 = Label(self, text="Digits:") lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10) self.ent1 = Entry(self, width=10) self.ent1.insert(END, "4000") self.ent1.grid(row=0, column=1, sticky=W) lbl2 = Label(self, text="Accuracy:") lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10) self.ent2 = Entry(self, width=10) self.ent2.insert(END, "100") self.ent2.grid(row=0, column=3, sticky=W) self.startBtn = Button(self, text="Start", command=self.onStart) self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W) self.pbar = Progressbar(self, mode='indeterminate') self.pbar.grid(row=1, column=1, columnspan=3, sticky=W + E) self.txt = scrolledtext.ScrolledText(self) self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5, columnspan=5, sticky=E + W + S + N) def onStart(self): self.startBtn.config(state=DISABLED) self.txt.delete("1.0", END) #self.p1 = Process(target=generatePi, args=(q, digits, accuracy)) self.p1 = Process(target=lengthy_function) self.p1.start() self.pbar.start(DELAY2) #20 self.after( DELAY1, self.listen_for_results) # after 80 ms, start checking for results # consumer function is in the GUI class def listen_for_results(self): # if the worker process is still running, delay a bit and check again if (self.p1.is_alive()): print('p1 is still alive') self.after(DELAY1, self.listen_for_results) return else: # the worker process has finished and put the result in the queue print('p1 is NOT alive') print(f'Checking if queue.Empty(): {q.empty()}') print(f'Checking queue.qsize(): {q.qsize()}') while q.qsize() > 0: print('something in the queue') record = q.get() print(record) time.sleep(1) print('queue is empty') self.pbar.stop() self.startBtn.config(state=NORMAL) '''while True:
class GUI(object): '''Stellt die Oberflaeche dar. Alle steuerden Taetigkeiten werden (sollten) vom Controller Objekt uebernommen werden. ''' def __init__(self): ''' Constructor ''' self.root = Tk() self.root.title("DinnerLog") self.root.minsize(800, 600) self.root.grid_columnconfigure(0, weight=1) self.root.grid_rowconfigure(0, weight=1) self.root.grid_rowconfigure(1, weight=3) # Ein Frame für alles, das mit Zutaten zu tun hat self.fr_zutaten = Labelframe(self.root, borderwidth=2, relief=GROOVE, text="Zutaten") self.fr_zutaten.grid_columnconfigure(0, weight=1) self.fr_zutaten.grid_rowconfigure(0, weight=1) self.fr_zutaten.grid(row=0, column=0, sticky="NSWE") self.lb_zutaten = Listbox(self.fr_zutaten) sb_zutaten = Scrollbar(self.lb_zutaten, orient=VERTICAL) self.lb_zutaten.configure(yscrollcommand=sb_zutaten.set) sb_zutaten.config(command=self.lb_zutaten.yview) sb_zutaten.pack(side="right", fill="both") self.lb_zutaten.grid(row=0, column=0, sticky="NSEW") self._addNeueZutatFrame() # Ein Frame in den alles, das mit Mahlzeiten zu tun hat, kommt self.fr_mahlzeit = Labelframe(self.root, borderwidth=2, relief=GROOVE, text="Mahlzeiten") self.fr_mahlzeit.grid_columnconfigure(0, weight=1) self.fr_mahlzeit.grid_rowconfigure(0, weight=1) self.fr_mahlzeit.grid(row=1, column=0, sticky="NSWE") self._addNeueMahlzeitFrame() self.lb_mahlzeiten = Listbox(self.fr_mahlzeit, selectmode=SINGLE) sb_mahlzeiten = Scrollbar(self.lb_mahlzeiten, orient=VERTICAL) sb_mahlzeiten.configure(command=self.lb_mahlzeiten.yview) self.lb_mahlzeiten.configure(yscrollcommand=sb_mahlzeiten.set) sb_mahlzeiten.pack(side="right", fill="both") self.lb_mahlzeiten.grid(row=0, column=0, sticky="NSEW") fr_neu_ok = Frame(self.fr_mahlzeit) fr_neu_ok.grid(row=1, column=0, columnspan=2, sticky="E") self.btn_neu = Button(fr_neu_ok, text="Neu") self.btn_neu.pack(side="left") self.btn_mahlzeit_als_zt = Button(fr_neu_ok, text="Als Zutat") self.btn_mahlzeit_als_zt.pack(anchor=E, side="right") self.btn_insert = Button(fr_neu_ok, text="Hinzufuegen") self.btn_insert.pack(anchor=E, side="right") self.btn_update = Button(fr_neu_ok, text="Update") self.btn_update.pack(anchor=E, side="right") self.btn_delete = Button(fr_neu_ok, text="Loeschen") self.btn_delete.pack(anchor=E, side="right") # Ein Frame der Statistiken darstellt self.fr_stats = Labelframe(self.root, borderwidth=2, relief=GROOVE, text="Statistik") self.fr_stats.grid(row=3, column=0, sticky="NSWE") #self.cv_stats = Canvas(self.fr_stats, height=80, width=600) #self.cv_stats.create_line(2,5,598,5, fill="#bbb") def _addNeueMahlzeitFrame(self): self.fr_neue_mz = Frame(self.fr_mahlzeit) self.fr_neue_mz.grid_rowconfigure(2, weight=1) self.fr_neue_mz.grid(row=0, column=1, sticky="WSNE") lbl_name = Label(self.fr_neue_mz, text="Name:") lbl_name.grid(row=0, column=0, sticky="NW") self.en_name = Entry(self.fr_neue_mz) self.en_name.grid(row=0, column=1, columnspan=2, sticky="WNE") lbl_zutat = Label(self.fr_neue_mz, text="Zutaten:") lbl_zutat.grid(row=1, column=0, sticky="NW") self.lb_zutat = Listbox(self.fr_neue_mz) sb_zutat = Scrollbar(self.lb_zutat, orient=VERTICAL) self.lb_zutat.configure(yscrollcommand=sb_zutat.set) sb_zutat.configure(command=self.lb_zutat.yview) sb_zutat.pack(side="right", fill="both") self.lb_zutat.grid(row=2, column=0, columnspan=3, sticky="NWSE") self.var_zutat = StringVar(self.fr_neue_mz) self.opt_zutat = OptionMenu(self.fr_neue_mz, self.var_zutat, "Auswahl") self.opt_zutat.grid(row=3, column=0) self.en_menge = Entry(self.fr_neue_mz) self.en_menge.grid(row=3, column=1) self.btn_mahlzeit_hinzu = Button(self.fr_neue_mz, text="Hinzu") self.btn_mahlzeit_hinzu.grid(row=3, column=2, sticky="E") def _addNeueZutatFrame(self): fr_neue_zt = Frame(self.fr_zutaten) fr_neue_zt.grid(row=0, column=2,sticky="NWSE") lbl_name = Label(fr_neue_zt, text="Name:") lbl_name.grid(row=0, column=0, sticky="W") self.en_name_zt = Entry(fr_neue_zt) self.en_name_zt.grid(row=0, column=1, columnspan=2, sticky="WE") lbl_fett = Label(fr_neue_zt, text="Fett:") lbl_fett.grid(row=1, column=0, sticky="W") self.en_fett = Entry(fr_neue_zt) self.en_fett.grid(row=1, column=1, columnspan=2) lbl_eiweiss = Label(fr_neue_zt, text="Eiweiss:") lbl_eiweiss.grid(row=2, column=0, sticky="W") self.en_eiweiss = Entry(fr_neue_zt) self.en_eiweiss.grid(row=2, column=1, columnspan=2) lbl_kh = Label(fr_neue_zt, text="Kohlenhy.:") lbl_kh.grid(row=3, column=0, sticky="W") self.en_kh = Entry(fr_neue_zt) self.en_kh.grid(row=3, column=1, columnspan=2) self.btn_zutat_insert = Button(fr_neue_zt, text="Hinzu") self.btn_zutat_insert.grid(row=4, column=1, sticky="E") self.btn_zutat_update = Button(fr_neue_zt, text="Update") self.btn_zutat_update.grid(row=5, column=1, sticky="E") self.btn_zutat_delete = Button(fr_neue_zt, text="Loeschen") self.btn_zutat_delete.grid(row=6, column=1, sticky="E")
def init_ui(self): # pylint: disable=R0915 """ Initialize the UI widgets. Refactored to separate method, since the tkroot UI might be required before information on the widgets are available. ------------------------------------ | GEL file: |____________| |Browse| | | Lane file: |____________| |Browse| | | YAML file: |____________| |Browse| | << fileinfo frame, column=0, row=0 ------------------------------------ | | ANNOTATE! | | << button frame, column=0, row=0 ------------------------------------ | Lane names: | YAML config: | | ------------- | -------------- | << text input frame | | | | | | | | | | | | | | << lanenames frame | | | | | | | << yaml frame | | | | | | | | | | | | | | | ------------- | -------------- | ------------------------------------ Non-used: | |Save| |Load| | |Save| |Load| | | Autosave |_| | Autosave |_| | | _________ __________ ______ | | |OK (Keep)| |OK (Clear)| |Cancel| | << buttonbox frame | ¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨ | ------------------------------------ | Shift-enter=Annotate, | | Added entry: "<product name>" | << Info frame | View page in browser | ------------------------------------ """ # .grid column defaults to 0 and row defaults to the first unused row in the grid. # Make sure mainframe expands: self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) # MAINFRAME: mainframe = Frame(self) mainframe.grid(sticky='news', row=0, column=0) # Defaults to 0 mainframe.columnconfigure(0, weight=1) mainframe.rowconfigure(2, weight=1) # Row 2 is textinput frame mainframe.rowconfigure(1, minsize=40) # Button frame. # FILE FRAME - has filenames/paths: fileframe = Frame(mainframe) fileframe.grid(sticky='news', row=0, column=0) # All vertical frames are placed implicitly fileframe.columnconfigure(1, weight=1, minsize=30) # Filepath labels: lbl = Label(fileframe, text="Directory: ") lbl.grid(sticky='w', row=0, column=0) lbl = Label(fileframe, text="Gel file: ") lbl.grid(sticky='w', row=1, column=0) lbl = Label(fileframe, text="Lane file:") lbl.grid(sticky='w', row=2, column=0) lbl = Label(fileframe, text="Yaml file:") lbl.grid(sticky='w', row=3, column=0) # self.GelfileEntry = entry = Entry(fileframe, textvariable=self.Gelfilepath) # How to make the right-most text visible? , justify='right' does not have the desired effect... # Filepath entries: entry = Entry(fileframe, textvariable=self.Gelfiledirectory, state='readonly') entry.grid(row=0, column=1, sticky='ew') entry = Entry(fileframe, textvariable=self.Gelfilepath) # = self.GelfilepathEntry entry.grid(row=1, column=1, sticky='ew') entry = Entry(fileframe, textvariable=self.Annotationsfilepath) entry.grid(row=2, column=1, sticky='ew') entry = Entry(fileframe, textvariable=self.Yamlfilepath) entry.grid(row=3, column=1, sticky='ew') # BROWSE buttons: btn = Button(fileframe, text='Help...', command=self.App.show_help) btn.grid(row=0, column=2) btn = Button(fileframe, text='Browse', command=self.App.browse_for_gelfile) btn.grid(row=1, column=2) btn = Button(fileframe, text='Browse', command=self.App.browse_for_annotationsfile) btn.grid(row=2, column=2) btn = Button(fileframe, text='Browse', command=self.App.browse_for_yamlfile) btn.grid(row=3, column=2) # BUTTON FRAME: buttonframe = Frame(mainframe) buttonframe.grid(sticky='news', column=0, row=1) btn = self.AnnotateBtn = Button(buttonframe, text="ANNOTATE!", command=self.App.annotate) btn.grid(sticky='news', row=1, column=2) buttonframe.rowconfigure(1, minsize=40) # mainframe row 1 must also be set to minsize. buttonframe.columnconfigure(2, weight=2) buttonframe.columnconfigure((1, 3), weight=1) # self.ProcessBtn = btn = Button(fileframe, text="Process!") # btn.grid(row=3, column=1, columnspan=2, sticky='news') # Outer textinputs FRAME - Contains both annotationsframe and yamlframe. ### textinput = Frame(mainframe) # Specify starting width and height textinput.grid(sticky="news", column=0, row=2) # Make sure it expands textinput.rowconfigure(0, weight=1) # Make sure it expands vertically textinput.columnconfigure((0, 1), weight=1) def loose_focus(event=None): self.AnnotateBtn.focus_set() def dont_propagate(event=None): # prevent Tkinter from propagating the event by returning the string "break" print("dont_propagate called...") return "break" self.bind_all("<Escape>", loose_focus) # ANNOTATIONS FRAME: annotationsframe = Frame(textinput, borderwidth=1) annotationsframe.grid(sticky='news', column=0, row=0) annotationsframe.rowconfigure(1, weight=1) # row 1 column 0 has text input annotationsframe.columnconfigure(0, weight=1) lbl = Label(annotationsframe, text="Lane annotations file:") lbl.grid(sticky='w', column=0, row=0) # undo ref: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/text-undo-stack.html # http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/text.html # default: width=80, height=24 # pylint: disable=W0201 text = self.AnnotationsText = Text(annotationsframe, width=40, height=20, undo=True, maxundo=-1) text.grid(sticky='news', column=0, row=1) text.bind(sequence='<Control-s>', func=self.App.save_annotations) # text.bind("<Control-Return>", dont_propagate) # More cheat-sheet: http://stackoverflow.com/questions/16082243/how-to-bind-ctrl-in-python-tkinter # YAML FRAME: yamlframe = Frame(textinput, borderwidth=1) yamlframe.grid(sticky='news', column=1, row=0) yamlframe.rowconfigure(1, weight=1) # row 1 has text input yamlframe.columnconfigure(0, weight=1) lbl = Label(yamlframe, text="Yaml (config) file:") lbl.grid(sticky='w', column=0, row=0) text = self.YamlText = Text(yamlframe, width=40, height=30, undo=True, maxundo=-1) # pylint: disable=W0201 text.grid(sticky='news', column=0, row=1) text.bind(sequence='<Control-s>', func=self.App.save_yaml) # text.bind("<Control-Return>", dont_propagate) # INFO FRAME - displays some help to the user (status bar) infoframe = Frame(mainframe, borderwidth=1, relief='sunken') # Specify starting width and height infoframe.grid(sticky="news", column=0, row=3) # Make sure it expands # standard statusbar style: # Using standard tk, don't want to bother with ttk styles for now... # anchor='w' ?? lbl = self.Statusbar = Label(infoframe, textvariable=self.Statustext) # , borderwidth=1, relief='sunken') # text="Tip: Use CTRL+ENTER to annotate. Buffers can be saved with ctrl+s, but that's also done automatically.") lbl.grid(sticky='news') # lbl = Label(infoframe, text="(Buffers can be saved with ctrl+s, but you don't have to.)") # lbl.grid(sticky='news') # l = Label(f, text="( Shift-enter=OK (keep), Enter=OK (clear), Escape=Abort )") # infoframe.rowconfigure(0, weight=1) # Make sure it expands vertically # infoframe.columnconfigure(0, weight=1) # self.bind(sequence='<Control-Return>', func=self.App.annotate) # Binding at app-level instead with bind_all logger.debug("Init ui done.")
class Example(Frame): def __init__(self, parent, q): Frame.__init__(self, parent) self.queue = q self.parent = parent self.initUI() def callback(self): self.root.quit() def initUI(self): # self.root = tk.Tk() # self.root.protocol("WM_DELETE_WINDOW", self.callback) self.parent.title("Pi Computation") self.pack(fill=BOTH, expand=True) self.grid_columnconfigure(4, weight=1) self.grid_rowconfigure(3, weight=1) lbl1 = Label(self, text="Digits:") lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10) self.ent1 = Entry(self, width=10) self.ent1.insert(END, "4000") self.ent1.grid(row=0, column=1, sticky=W) lbl2 = Label(self, text="Accuracy:") lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10) self.ent2 = Entry(self, width=10) self.ent2.insert(END, "100") self.ent2.grid(row=0, column=3, sticky=W) self.startBtn = Button(self, text="Start", command=self.onStart) self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W) self.pbar = Progressbar(self, mode='indeterminate') self.pbar.grid(row=1, column=1, columnspan=3, sticky=W + E) self.txt = st.ScrolledText(self) self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5, columnspan=5, sticky=E + W + S + N) # self.root.mainloop() def onStart(self): self.startBtn.config(state=DISABLED) self.txt.delete("1.0", END) self.digits = int(self.ent1.get()) self.accuracy = int(self.ent2.get()) self.p1 = Process(target=self.generatePi, args=(self.queue, )) # self.p1 = Process(target=self.generatePi, args=(self.queue )) self.p1.start() self.pbar.start(DELAY2) self.after(DELAY1, self.onGetValue) def onGetValue(self): if (self.p1.is_alive()): self.after(DELAY1, self.onGetValue) return else: try: self.txt.insert('end', self.queue.get(0)) self.txt.insert('end', "\n") self.pbar.stop() self.startBtn.config(state=NORMAL) except queue.Empty: print("queue is empty") def generatePi(self, queue): getcontext().prec = self.digits pi = Decimal(0) k = 0 n = self.accuracy while k < n: pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - \ (Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5))- \ (Decimal(1)/(8*k+6))) k += 1 print("Example frame is still alive = ", self.p1.is_alive()) # queue.put("Example frame is still alive = ", self.p1.is_alive()) queue.put(pi) print("Example frame end")
class ClientGUI: def __init__(self): self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.client_socket.settimeout(5.0) self.port = 2345 self.client_running = False self.client_connected = False self.root = tk.Tk() self.root.resizable(width=False, height=False) self.root.title('Chat Client') self.createGUI() self.root.protocol('WM_DELETE_WINDOW', self.onShuttingDownClient) self.root.mainloop() return def createGUI(self): tk.ttk.Style().configure('TLabel', font=('Times New Roman', 16)) tk.ttk.Style().configure('TButton', font=('Times New Roman', 16)) self.frame = Frame(self.root) self.user_name_label = Label(self.frame, text='User Name') self.user_name_label.grid(row=0, column=0, sticky='W') self.user_name_box = Entry(self.frame, font=('Times New Roman', 16), width=20) self.user_name_box.grid(row=0, column=1) self.ip_label = Label(self.frame, text='Server IP Address') self.ip_label.grid(row=1, column=0, sticky='W') self.ip_addr_box = Entry(self.frame, font=('Times New Roman', 16)) self.ip_addr_box.grid(row=1, column=1) self.connect_btn = Button(self.frame, text='Connect', command=self.connectBtnClick) self.connect_btn.grid(row=2, column=0, sticky='W') self.chat_area = scrolledtext.ScrolledText(self.frame, height=10, width=42, undo=True, font=('Times New Roman', 16)) self.chat_area.grid(row=3, column=0, sticky='NEWS') self.chat_area.configure(state='disabled') self.client_list = Listbox(self.frame, font=('Times New Roman', 16), selectmode=tk.MULTIPLE) self.client_list.grid(row=3, column=1, sticky='NEWS') self.msg_box = scrolledtext.ScrolledText(self.frame, font=('Times New Roman', 16), height=1, width=42, undo=True) self.msg_box.grid(row=4, column=0, sticky='W') self.send_btn = Button(self.frame, text='Send', command=self.sendBtnClick) self.send_btn.grid(row=4, column=1, sticky='W') self.send_btn.state(['disabled']) self.frame.grid(row=0, column=0) return def connectBtnClick(self): self.client_name = self.user_name_box.get() if not (len(self.client_name) == 0): try: self.client_socket.sendto(('1111||'+ self.client_name).encode('ascii'), (self.ip_addr_box.get(), self.port)) self.message, self.address = self.client_socket.recvfrom(2048) self.chat_area.config(state='normal') self.chat_area.insert(tk.END, self.message.decode('ascii') + '\n') self.chat_area.config(state='disabled') self.client_running = True threading.Thread(target=self.updateClientList).start() self.connect_btn.state(['disabled']) self.user_name_box.state(['disabled']) self.ip_addr_box.state(['disabled']) self.send_btn.state(['!disabled']) self.client_connected = True except socket.timeout as tout: messagebox.showerror("Message From Client", tout) except socket.gaierror as gerror: messagebox.showerror("Message From Client", gerror) pass pass else: messagebox.showerror('Message From Client', 'User Name cannot be empty') def sendBtnClick(self): recv_clients_list = self.client_list.curselection() msg_type = '' if len(recv_clients_list) > 1: msg_type = ' [MC]' recv_clients = '' for k in recv_clients_list: recv_clients = recv_clients + '||' + self.client_list.get(k) self.message_to_sent = self.client_name + '||' + self.msg_box.get(1.0, tk.END) + msg_type + recv_clients self.chat_area.config(state='normal') self.chat_area.insert(tk.END, 'You>>' + self.msg_box.get(1.0, tk.END) + '\n') self.chat_area.config(state='disabled') self.client_socket.sendto(self.message_to_sent.encode('ascii'), (self.ip_addr_box.get(), self.port)) self.msg_box.delete(1.0, tk.END) pass def onShuttingDownClient(self): if self.client_connected: self.client_socket.sendto(('0000' + '||' + self.client_name).encode('ascii'), (self.ip_addr_box.get(), self.port)) self.client_running = False self.root.destroy() pass def updateClientList(self): self.client_socket.setblocking(0) while self.client_running: try: self.message, self.address = self.client_socket.recvfrom(2048) self.message = self.message.decode('ascii') i = 0 j = 0 if self.isContain(self.message, '1111'): temp_client_list = self.message.split('||') self.client_list.delete(0, tk.END) while i < len(temp_client_list): if not (self.client_name == temp_client_list[i]) and not (temp_client_list[i] == '1111'): self.client_list.insert(j, temp_client_list[i]) j = j + 1 i = i+1 elif 'Empty List 0000' in self.message: self.client_list.delete(0, tk.END) elif 'Server Offline 0101' in self.message: self.client_connected = False self.chat_area.config(state='normal') self.chat_area.insert(tk.END, 'Server is Offline. Chat discontinues!!!\n') self.chat_area.config(state='disabled') self.send_btn.state(['disabled']) self.connect_btn.state(['!disabled']) self.ip_addr_box.state(['!disabled']) self.user_name_box.state(['!disabled']) self.client_socket.settimeout(1) self.client_running = False else: self.chat_area.config(state='normal') self.chat_area.insert(tk.END, self.message + '\n') self.chat_area.config(state='disabled') except socket.error: pass pass def isContain(self, str, sub_str): index = str.find(sub_str) if index == -1: return False else: return True
class DCSWPControllerApp(Tk): """DCS WP-Manager GUI layer.""" def __init__(self): super().__init__() self.geometry("300x200") self.iconbitmap('icon.ico') self.title("DCS WP Manager") self.host_label = Label(self, text='Host:') self.host_label.grid(column=0, row=1) self.host = Combobox( values=["GAW", "PGAW", "LOCALHOST", "A-Horrible-Server"]) self.host.insert(50, "A-Horrible-Server") self.host.grid(column=1, row=1) self.user_label = Label(self, text='Username:'******'disabled', command=self.switch_status) self.stop.grid(column=1, row=3) self.label = Label(self, text='Status:') self.label.grid(column=0, row=5) self.status_value = Label(self, text="Stopped") self.status_value.grid(column=1, row=5) self.tac_proc = None self.coord_proc = None def switch_status(self): """Either start or stop all processes, depending on current state.""" if str(self.stop['state']) == 'disabled': self.start_tac_client() self.start_coord_server() self.stop.configure(state="normal") self.start.configure(state="disabled") self.status_value.configure(text="Running") r.get("http://127.0.0.1:5000/set_username/" + self.user.get()) LOG.info('Status values updated correctly...') else: self.stop_process() LOG.info('Process stopped...updating status values...') self.stop.configure(state="disabled") self.start.configure(state="normal") self.status_value.configure(text="Stopped") LOG.info('Status values updated correctly...') def start_tac_client(self): """Start the tacview client in a background process.""" if self.tac_proc: raise ValueError("Tacview client process already exists!") LOG.info('Starting tacview client process...') host = config.presets[self.host.get()].split(":") self.tac_proc = Process(target=client.main, args=( host[0], host[1], )) self.tac_proc.start() LOG.info("Tacview client process started successfully...") def start_coord_server(self): """Start the coord server in a background process.""" if self.coord_proc: raise ValueError("Coord Server process already exists!") LOG.info('Starting coord server process...') self.coord_proc = Process(target=coord_server.main) self.coord_proc.start() LOG.info("Coord server process started successfully...") def stop_process(self): """Stop both the tacview client and coord server processes.""" if self.coord_proc: LOG.info('Stopping coord server process...') self.coord_proc.terminate() self.coord_proc.join() self.coord_proc = None LOG.info("Coord server process stopped successfully...") if self.tac_proc: LOG.info('Stopping tacview client process...') self.tac_proc.terminate() self.tac_proc.join() self.tac_proc = None LOG.info("tacview client process stopped successfully...")
class Program(Frame): """Class to represent a main window""" def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.meters_value = StringVar() self.initUI() def initUI(self): self.grid(column=0, row=0, sticky=(N, W, E, S)) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.parent.title('Feet to meter') self.pack(expand=True) self.centerWindow() self.initItems() def initItems(self): """Initialize all widgets here""" # An entry to enter feet value. self.feet_entry = Entry(self, width=7) self.feet_entry.grid(column=2, row=1, sticky=(W, E)) # A label to display translated meters. self.meters_lbl = Label(self, textvariable=self.meters_value) self.meters_value.set(0) self.meters_lbl.grid(column=2, row=2, sticky=(W, E)) # Different labels for text only. Label(self, text='feet').grid(column=3, row=1, sticky=W) Label(self, text='is equivalent to').grid(column=1, row=2, sticky=E) Label(self, text='meters').grid(column=3, row=2, sticky=W) # Button to calculate things. calc_btn = Button(self, text='Calculate', command=lambda: calculate(self)) calc_btn.grid(column=3, row=3, sticky=W) # This widget is just for fun. # Also it shows how to get an event callback when Entry widget is modified def callback(str): print(str.get()) entry_str = StringVar() entry_str.trace('w', lambda name, index, mode, str=entry_str: callback(str)) self.entry_widg = Entry(self, width=10, textvariable=entry_str) self.entry_widg.grid(column=1, row=4, sticky=(W, E)) # A really simple way to change label text: test_lbl = Label(self) test_lbl.grid(column=3, row=4, sticky=E) test_lbl['text'] = 'hello!' # Handling label's events ev_lbl = Label(self, text='Do something with me...', width=30) ev_lbl.grid(column=1, row=5, columnspan=2, rowspan=2) ev_lbl.bind('<Enter>', lambda e: ev_lbl.configure(text='Moved mouse inside')) ev_lbl.bind('<Leave>', lambda e: ev_lbl.configure(text='Moved mouse outside')) ev_lbl.bind( '<1>', lambda e: ev_lbl.configure(text='Clicked left mouse button!')) ev_lbl.bind( '<Double-1>', lambda e: ev_lbl.configure( text='Double clicked left mouse button!')) # Configure pads for all grid cells for child in self.winfo_children(): child.grid_configure(padx=5, pady=5) # As default, entry is focused self.feet_entry.focus() def centerWindow(self): """Place the main window in the center of screen""" window_w = 300 window_h = 200 screen_w = self.winfo_screenwidth() screen_h = self.winfo_screenheight() x = (screen_w - window_w) / 2 y = (screen_h - window_h) / 2 self.parent.geometry('%dx%d+%d+%d' % (window_w, window_h, x, y))
def __init__(self, parent, title, host=None, realm=None, useOsProxy=None, urlAddr=None, urlPort=None, user=None, password=None, database=None, timeout=None, dbType=None, showUrl=False, showUser=False, showHost=True, showRealm=True, showDatabase=False): super(DialogUserPassword, self).__init__(parent) self.parent = parent parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.accepted = False self.transient(self.parent) self.title(title) self.urlAddrVar = StringVar() self.urlAddrVar.set(urlAddr if urlAddr else "") self.urlPortVar = StringVar() self.urlPortVar.set(urlPort if urlPort else "") self.userVar = StringVar() self.userVar.set(user if user else "") self.passwordVar = StringVar() self.passwordVar.set(password if password else "") self.databaseVar = StringVar() self.databaseVar.set(database if database else "") self.timeoutVar = StringVar() self.timeoutVar.set(timeout if timeout else "") frame = Frame(self) y = 0 if showHost: hostLabel = Label(frame, text=_("Host:"), underline=0) hostDisplay = Label(frame, text=host, width=30) if host and len(host) > 30: ToolTip(hostDisplay, text=host, wraplength=240) hostLabel.grid(row=y, column=0, sticky=W, pady=3, padx=3) hostDisplay.grid(row=y, column=1, columnspan=4, sticky=EW, pady=3, padx=3) y += 1 if showRealm: realmLabel = Label(frame, text=_("Realm:"), underline=0) realmDisplay = Label(frame, text=realm, width=25) if realm and len(realm) > 30: ToolTip(realmDisplay, text=realm, wraplength=240) realmLabel.grid(row=y, column=0, sticky=W, pady=3, padx=3) realmDisplay.grid(row=y, column=1, columnspan=4, sticky=EW, pady=3, padx=3) y += 1 self.enabledWidgets = [] if useOsProxy is not None: if sys.platform.startswith("win"): hostProxy = _('Microsoft Windows Internet Settings') elif sys.platform in ("darwin", "macos"): hostProxy = _('Mac OS X System Configuration') else: # linux/unix hostProxy = _('environment variables') useOsProxyCb = checkbox(frame, 0, y, text=_("Use proxy server of {0}").format(hostProxy)) useOsProxyCb.grid(columnspan=5) useOsProxyCb.valueVar.set(useOsProxy) ToolTip(useOsProxyCb, text=_("Check to use {0} \n" "Uncheck to specify: \n" " No proxy if URL address is left blank, \n" " Proxy via URL address if it is not blank, \n" " with user and password (if provided)" ).format(hostProxy), wraplength=360) self.useOsProxyCb = useOsProxyCb useOsProxyCb.valueVar.trace("w", self.setEnabledState) y += 1 if showUrl: urlAddrLabel = Label(frame, text=_("Address:"), underline=0) urlAddrEntry = Entry(frame, textvariable=self.urlAddrVar, width=16) urlPortLabel = Label(frame, text=_("Port:"), underline=0) urlPortEntry = Entry(frame, textvariable=self.urlPortVar, width=5) urlAddrEntry.focus_set() urlAddrLabel.grid(row=y, column=0, sticky=W, pady=3, padx=3) urlAddrEntry.grid(row=y, column=1, columnspan=2, sticky=EW, pady=3, padx=3) urlPortLabel.grid(row=y, column=3, sticky=W, pady=3, padx=3) urlPortEntry.grid(row=y, column=4, sticky=EW, pady=3, padx=3) ToolTip(urlAddrEntry, text=_("Enter URL address and port number \n" " e.g., address: 168.1.2.3 port: 8080 \n" " or address: proxy.myCompany.com port: 8080 \n" " or leave blank to specify no proxy server"), wraplength=360) self.enabledWidgets.append(urlAddrEntry) self.enabledWidgets.append(urlPortEntry) y += 1 userLabel = Label(frame, text=_("User:"******"Password:"******"*") passwordLabel.grid(row=y, column=0, sticky=W, pady=3, padx=3) passwordEntry.grid(row=y, column=1, columnspan=4, sticky=EW, pady=3, padx=3) self.enabledWidgets.append(passwordEntry) y += 1 if showDatabase: urlDatabaseLabel = Label(frame, text=_("Database:"), underline=0) urlDatabaseEntry = Entry(frame, textvariable=self.databaseVar, width=25) urlDatabaseLabel.grid(row=y, column=0, sticky=W, pady=3, padx=3) urlDatabaseEntry.grid(row=y, column=1, columnspan=4, sticky=EW, pady=3, padx=3) ToolTip(urlAddrEntry, text=_("Enter database name (optional) or leave blank"), wraplength=360) self.enabledWidgets.append(urlDatabaseEntry) y += 1 urlTimeoutLabel = Label(frame, text=_("Timeout:"), underline=0) urlTimeoutEntry = Entry(frame, textvariable=self.timeoutVar, width=25) urlTimeoutLabel.grid(row=y, column=0, sticky=W, pady=3, padx=3) urlTimeoutEntry.grid(row=y, column=1, columnspan=4, sticky=EW, pady=3, padx=3) ToolTip(urlAddrEntry, text=_("Enter timeout seconds (optional) or leave blank for default (60 secs.)"), wraplength=360) self.enabledWidgets.append(urlTimeoutEntry) y += 1 dbTypeLabel = Label(frame, text=_("DB type:"), underline=0) dbTypeLabel.grid(row=y, column=0, sticky=W, pady=3, padx=3) self.cbDbType = gridCombobox(frame, 1, y, values=DBDescriptions, selectindex=DBTypes.index(dbType) if dbType in DBTypes else None) self.cbDbType.grid(columnspan=4, pady=3, padx=3) y += 1 okButton = Button(frame, text=_("OK"), command=self.ok) cancelButton = Button(frame, text=_("Cancel"), command=self.close) okButton.grid(row=y, column=2, sticky=E, pady=3) cancelButton.grid(row=y, column=3, columnspan=2, sticky=EW, pady=3, padx=3) y += 1 if useOsProxy is not None: self.setEnabledState() frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(1, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100)) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self)
class MyGUI: def __init__(self, master, title=None, args=None): self.master = master self.args = args self.name = title master.title("Startup interface for %s" % title) self.arguments = dict() style = Style() style.configure(".", background="lightgrey") labelStyle = Style() labelStyle.configure("TLabel", background="lightgrey") buttonStyle = Style() buttonStyle.configure("TButton", background="lightgrey") chkbuttonStyle = Style() chkbuttonStyle.configure("TCheckbutton", background="lightgrey") rbuttonStyle = Style() rbuttonStyle.configure("TRadiobutton", background="lightgrey") row = 0 column = 0 # Input edge file self.inEdgeLabel = Label(master, text="Input edge file") self.inEdgeLabel.grid(row=row, column=column, sticky=W, padx=3) self.inEdgeFile = StringVar() if self.args.i: self.inEdgeFile.set(self.args.i) self.inEdgeEntry = Entry(master, width=WIDTH, textvariable=self.inEdgeFile) column += 1 self.inEdgeEntry.grid(row=row, column=column, padx=3) self.inEdgeSelect = Button(master, text = "Select",\ command = lambda: self.setOutputFiles2(IN=self.inEdgeFile,OUT=[(self.configFile,"config"),(self.outFile,"desc"),(self.outFile2,"xml_desc")])) column += 1 self.inEdgeSelect.grid(row=row, column=column, sticky=W, padx=3) self.optionLabel2 = Label(master, text="required") column += 1 self.optionLabel2.grid(row=row, column=column, sticky=W, padx=3) # tip helpText1 = "Edge file for input graph (two columns, tab-delimited)." self.inEdgeTip = CreateToolTip(self.inEdgeEntry, helpText1) ## row += 1 column = 0 self.annotLabel = Label(master, text="Annotation file") self.annotLabel.grid(row=row, column=column, sticky=W, padx=3) self.a = StringVar() if self.args.a: self.a.set(os.path.abspath(os.path.normpath(self.args.a))) self.annotEntry = Entry(master, width=WIDTH, textvariable=self.a) column += 1 self.annotEntry.grid(row=row, column=column, padx=3) self.annotSelect = Button( master, text="Select", command=lambda: self.openAnnotFile(var=self.a)) column += 1 self.annotSelect.grid(row=row, column=column, sticky=W, padx=3) self.optionLabel2 = Label(master, text="required") column += 1 self.optionLabel2.grid(row=row, column=column, sticky=W, padx=3) CreateToolTip( self.annotEntry, "Common annotation file for genomes and genes.\nTab-delimited, compulsory header with attribute names.\nSpecify empty annotations with '-'." ) row += 1 column = 0 self.k = StringVar() if self.a.get(): with open(self.a.get(), 'r') as ANNOT: keyList = ANNOT.readline().strip().split("\t")[1:] #print(keyList) keyList.sort() keyString = ",".join(keyList) self.optionLabel = Label(master, text="Annotation keys") self.optionLabel.grid(row=row, column=0, sticky=W, padx=3) self.k = StringVar() self.k.set(keyString) self.optionEntry = Entry(master, width=WIDTH, textvariable=self.k) self.optionEntry.grid(row=row, column=1, padx=3) self.optionLabel2 = Label(master, text="comma-separated") self.optionLabel2.grid(row=row, column=3, sticky=W, padx=3) CreateToolTip( self.optionEntry, "List of available attributes in file %s.\nIf you wish to remove some, click on line and edit." % self.args.a) row += 1 self.configLabel = Label(master, text="Configuration file") self.configLabel.grid(row=row, column=column, sticky=W, padx=3) self.configFile = StringVar() self.generateConfig = BooleanVar() self.generateConfig.set(bool(self.args.X)) self.useConfig = BooleanVar() self.useConfig.set(bool(self.args.x)) if self.args.x or self.args.X: if self.args.x and self.args.X: if self.args.x == self.args.X: cFile = self.args.x self.configFile.set(cFile) else: sys.exit( "Conflicting fields -x and -X. Check and run again.") elif self.args.x: cFile = self.args.x else: cFile = self.args.X self.configFile.set(cFile) else: self.configFile.set('') self.configEntry = Entry(master, width=WIDTH, textvariable=self.configFile) column += 1 self.configEntry.grid(row=row, column=column, padx=3) self.configSelect = Button( master, text="Select", command=lambda: self.setFile(var1=self.configFile, var2=self.outTrailFile)) column += 1 self.configSelect.grid(row=row, column=column, sticky=W, padx=3) """self.optionLabel2 = Label(master, text = "optional") column += 1 self.optionLabel2.grid(row=row,column=column,sticky=W, padx=3) """ # tip helpText3 = "XML file specifying component, trails and annotations for all node types." self.configTip = CreateToolTip(self.configEntry, helpText3) # column += 1 #row += 1 #column = 0 cbFrame = Frame(master) chk1 = Checkbutton(cbFrame, text="Generate", var=self.generateConfig) chk1.pack(side="left", fill=None, expand=False, padx=3) CreateToolTip(chk1, "Generate configuration file %s" % self.configFile.get()) chk2 = Checkbutton(cbFrame, text="Use", var=self.useConfig) chk2.pack(side="left", fill=None, expand=False, padx=3) CreateToolTip(chk2, "Use configuration file %s" % self.configFile.get()) cbFrame.grid(row=row, column=column, sticky=W) row += 1 column = 0 self.TrailLabel = Label(master, text="Use trail file") self.TrailLabel.grid(row=row, column=column, sticky=W, padx=3) self.inTrailFile = StringVar() self.T = StringVar() if self.args.t: self.T.set("1") self.inTrailFile.set(self.args.t) elif self.args.H: self.T.set("2") self.inTrailFile.set(self.args.H) else: self.T.set("0") MODES = [ ("No", "0"), ("Unique level", "1"), ("Follow history", "2"), ] trailVal = { "0": "Toto", "1": self.inTrailFile.get(), "2": self.inTrailFile.get() } helpVal = { "0": "Do not use trail file.\nCheck that annotations refer to IDs of current graph.", "1": "Use only level described by trail file.", "2": "Use all levels found in the trail history." } rbFrame = Frame(master) # create subframe for radiobuttons i = 0 MODE = MODES[0] b = Radiobutton(rbFrame, text=MODE[0], variable=self.T, value=MODE[1], command=lambda: self.inTrailFile.set('')) # tip CreateToolTip(b, helpVal[str(i)]) ## b.pack(side="left", fill=None, expand=False, padx=3) for text, mode in MODES[1:]: b = Radiobutton( rbFrame, text=text, variable=self.T, value=mode, command=lambda: self.openFileCheck(var=self.inTrailFile)) # tip CreateToolTip(b, helpVal[mode]) ## b.pack(side="left", fill=None, expand=False, padx=3) rbFrame.grid(row=row, column=1) row += 1 column = 0 self.inTrailLabel = Label(master, text="Trail file") self.inTrailLabel.grid(row=row, column=column, sticky=W, padx=18) #self.inTrailEntry = Entry(master, width = WIDTH, textvariable = self.inTrailFile) self.inTrailEntry = Entry(master, width=WIDTH, textvariable=self.inTrailFile, validate='focusin', validatecommand=lambda: self.T.set("2")) CreateToolTip( self.inTrailEntry, """Select node type file for multipartite graphs.\nThis will reset the partiteness to "Multipartite".""" ) column += 1 self.inTrailEntry.grid(row=row, column=column, padx=3) self.inTrailSelect = Button( master, text="Select", command=lambda: self.openFile2( var=self.inTrailFile, var2=self.T, value="2")) column += 1 self.inTrailSelect.grid(row=row, column=column, sticky=W, padx=3) self.optionLabel2 = Label(master, text="if option set") column += 1 self.optionLabel2.grid(row=row, column=column, sticky=W, padx=3) # tip helpText3 = "Links IDs of current graph to IDs of ROOT graph (two columns, tab-delimited).\nIf skipped, current graph is considered ROOT." self.inTrailTip = CreateToolTip(self.inTrailEntry, helpText3) # """ cbFrame = Frame(master) self.uniqueTrail = BooleanVar() chk1 = Checkbutton(cbFrame, text="Unique trail file", var = self.uniqueTrail) chk1.pack(side="left", fill=None, expand=False, padx=3) CreateToolTip(chk1, "Consider only level given by %s" % self.inTrailFile.get()) self.history = BooleanVar() chk2 = Checkbutton(cbFrame, text="Use trail history", var = self.history) chk2.pack(side="left", fill=None, expand=False, padx=3) CreateToolTip(chk2, "Follow trail history of trail file %s" % self.inTrailFile.get()) cbFrame.grid(row=row,column=1) """ row += 1 column = 0 # Component file self.CompLabel = Label(master, text="Component file ") self.CompLabel.grid(row=row, column=column, sticky=W, padx=3) self.CompFile = StringVar() if self.args.c: self.CompFile.set(self.args.c) self.CompEntry = Entry(master, width=WIDTH, textvariable=self.CompFile) column += 1 self.CompEntry.grid(row=row, column=column, padx=3) self.CompSelect = Button( master, text="Select", command=lambda: self.openFile(var=self.CompFile)) column += 1 self.CompSelect.grid(row=row, column=column, sticky=W, padx=3) self.optionLabel2 = Label(master, text="optional") column += 1 self.optionLabel2.grid(row=row, column=column, sticky=W, padx=3) # tip helpText3 = "Links a nodeID and its neighbours to the twin class ID.\nThis is usually an overlapping clustering.\nIf left empty, consider nodes of current graph as components." self.CompTip = CreateToolTip(self.CompEntry, helpText3) ## row += 1 column = 0 # Partiteness options self.inNodeLabel = Label(master, text="Partiteness") self.inNodeLabel.grid(row=row, column=column, sticky=W, padx=3) column += 1 MODES = [ ("Unipartite", "1"), ("Bipartite", "2"), ] self.inNodeType = StringVar() self.v = StringVar() if str(self.args.N) == '1' or str(self.args.N) == '2': self.v.set(self.args.N) # initialize at value elif self.args.N: self.v.set("m") self.inNodeType.set(self.args.N) else: self.v.set("2") rbFrame = Frame(master) # create subframe for radiobuttons for text, mode in MODES: b = Radiobutton(rbFrame, text=text, variable=self.v, value=mode, command=lambda: self.inNodeType.set('')) # tip CreateToolTip(b, "Select if graph is %s" % text.lower()) ## b.pack(side="left", fill=None, expand=False, padx=3) b = Radiobutton(rbFrame, text="Multipartite", variable=self.v, value="m", command=lambda: self.openFile(var=self.inNodeType)) CreateToolTip( b, "Select if graph is multipartite.\nThis will open a select box for the node type file." ) b.pack(side="left", fill=None, expand=False, padx=3) rbFrame.grid(row=row, column=column, padx=3) row += 1 column = 0 self.Label = Label(master, text="Node type file") self.Label.grid(row=row, column=column, sticky=W, padx=18) self.inNodeEntry = Entry(master, width=WIDTH, textvariable=self.inNodeType, validate='focusin', validatecommand=lambda: self.v.set("m")) CreateToolTip( self.inNodeEntry, """Select node type file for multipartite graphs.\nThis will reset the partiteness to "Multipartite".""" ) column += 1 self.inNodeEntry.grid(row=row, column=column, padx=3) self.inNodeSelect = Button( master, text="Select", command=lambda: self.openFile2( var=self.inNodeType, var2=self.v, value="m") ) # reset value to "multipartite" when type file is chosen. column += 1 self.inNodeSelect.grid(row=row, column=column, sticky=W, padx=3) self.optionLabel2 = Label(master, text="for multipartite only") column += 1 self.optionLabel2.grid(row=row, column=column, sticky=W, padx=3) CreateToolTip( self.inNodeSelect, """Select node type file for multipartite graphs.\nThis will reset the partiteness to "Multipartite".""" ) row += 1 column = 0 # Output file self.outLabel = Label(master, text="Output plain file") self.outLabel.grid(row=row, column=column, sticky=W, padx=3) self.outFile = StringVar() if self.args.o: self.outFile.set(self.args.o) self.outEntry = Entry(master, width=WIDTH, textvariable=self.outFile) column += 1 self.outEntry.grid(row=row, column=column, padx=3) self.outSelect = Button( master, text="Select", command=lambda: self.openFile(var=self.outFile)) column += 1 self.outSelect.grid(row=row, column=column, sticky=W, padx=3) self.optionLabel2 = Label(master, text="required") column += 1 self.optionLabel2.grid(row=row, column=column, sticky=W, padx=3) # tip helpText2 = "Set name of the plain text description file" self.outTip = CreateToolTip(self.outEntry, helpText2) ## row += 1 column = 0 # Output file self.outLabel2 = Label(master, text="Output XML file") self.outLabel2.grid(row=row, column=column, sticky=W, padx=3) self.outFile2 = StringVar() if self.args.O: self.outFile.set(self.args.O) self.outEntry2 = Entry(master, width=WIDTH, textvariable=self.outFile2) column += 1 self.outEntry2.grid(row=row, column=column, padx=3) self.outSelect2 = Button( master, text="Select", command=lambda: self.openFile(var=self.outFile2)) column += 1 self.outSelect2.grid(row=row, column=column, sticky=W, padx=3) self.optionLabel2 = Label(master, text="optional") column += 1 self.optionLabel2.grid(row=row, column=column, sticky=W, padx=3) # tip helpText2 = "Set name of the XML description file" self.outTip = CreateToolTip(self.outEntry2, helpText2) ## row += 1 column = 0 self.optionLabel = Label(master, text="Unique node identifier") self.optionLabel.grid(row=row, column=0, sticky=W, padx=3) self.I = StringVar() if self.args.I: self.I.set(self.args.I) self.optionEntry = Entry(master, width=WIDTH, textvariable=self.I) self.optionEntry.grid(row=row, column=1, padx=3) CreateToolTip( self.optionEntry, """Name of first column in annotation %s file.\nCheck that the items in this column match the node IDs in the ROOT graph.""" % os.path.basename(self.a.get())) row += 1 column = 0 self.trackLabel = Label(master, text="Missing annotation label") self.trackLabel.grid(row=row, column=column, sticky=W, padx=3) self.trackName = StringVar() if self.args.T: self.trackName.set(self.args.T) self.trackEntry = Entry(master, width=WIDTH, textvariable=self.trackName) column += 1 self.trackEntry.grid(row=row, column=column, padx=3) # tip helpText3 = "Name replacing missing annotations" self.trackTip = CreateToolTip(self.trackEntry, helpText3) # column += 2 self.Track = BooleanVar() chk1 = Checkbutton(master, text="Skip", var=self.Track) CreateToolTip(chk1, "Skip missing annotations") chk1.grid(row=row, column=column, sticky=W, padx=9) row += 1 column = 0 self.optionLabel = Label(master, text="Graphic interface for %s" % self.configFile.get()) self.optionLabel.grid(row=row, column=0, sticky=W, padx=3) self.K = BooleanVar() self.K.set(self.args.K) self.chk = Checkbutton(master, text="Display?", var=self.K) self.chk.grid(row=row, column=1, padx=3, sticky=W) CreateToolTip( self.chk, "Displays graphic customization interface for the last description.py step.\nIf not selected, displays all attributes for all key types and all trail levels." ) row += 1 column = 0 # Log self.optionLabel = Label(master, text="Log file") self.optionLabel.grid(row=row, column=0, sticky=W, padx=3) self.l = StringVar() try: log = self.args.l.name.strip("(<,>") except: log = log self.l.set(log) self.optionEntry = Entry(master, width=WIDTH, textvariable=self.l) self.optionEntry.grid(row=row, column=1, padx=3) row += 2 # Populate outFiles if edge file given if self.args.i: self.setOutputFiles2(IN=self.inEdgeFile, OUT=[(self.configFile, "config"), (self.outFile, "desc"), (self.outFile2, "xml_desc")], OPEN=False) cbFrame = Frame(master) # create subframe for command buttons self.run_button = Button(cbFrame, text="Run", command=self.run) self.run_button.grid(row=row, column=0, padx=12) self.close_button = Button(cbFrame, text="Close", command=self.Quit) self.close_button.grid(row=row, column=1, padx=12) cbFrame.grid(row=row, column=1, columnspan=2, sticky=E + W) helpText = description.processArgs().format_help() self.helpbutton = Button( master, text="Help", command=lambda: HelpWindow(text=helpText, name=self.name)) self.helpbutton.grid(row=row, column=2, sticky=W, padx=3) def func(self, value): print("Set %s " % value) def setFile(self, var1=None, var2=None): self.openFile(var=var1) modfile = os.path.split(var1.get())[1] var2.set(modfile) self.master.update_idletasks() def setOutputFiles(self, IN=None, TWIN=None, TWINCOMP=None): self.openFile(var=IN) inFile = os.path.split(IN.get())[1] inRad = inFile.split(".")[0] twin = inRad + ".twins" twinComp = inRad + ".twin_comp" TWIN.set(twin) TWINCOMP.set(twinComp) self.master.update_idletasks() def setOutputFiles2(self, IN=None, OUT=None, OPEN=True): if OPEN: self.openFile(var=IN) inFile = os.path.split(IN.get())[1] inRad = inFile.split(".")[0] for items in OUT: FILE, EXT = items FILE.set(inRad + "." + EXT) self.master.update_idletasks() def openFile(self, var=None): var.set(askopenfilename()) def openFileCheck(self, var=None): if not var.get(): var.set(askopenfilename()) def openFile2(self, var=None, var2=None, value=None): var.set(askopenfilename()) var2.set(value) self.master.update_idletasks() def openAnnotFile(self, var=None): var.set(askopenfilename()) row = 2 master = self.master try: with open(var.get(), 'r') as ANNOT: keyList = ANNOT.readline().strip().split("\t")[1:] #print(keyList) keyList.sort() keyString = ",".join(keyList) except FileNotFoundError: return self.optionLabel = Label(master, text="Annotation keys") self.optionLabel.grid(row=row, column=0, sticky=W, padx=3) self.k = StringVar() self.k.set(keyString) self.optionEntry = Entry(master, width=WIDTH, textvariable=self.k) self.optionEntry.grid(row=row, column=1, padx=3) self.optionLabel2 = Label(master, text="comma-separated") self.optionLabel2.grid(row=row, column=3, sticky=W, padx=3) ann = os.path.basename(self.a.get()) CreateToolTip( self.optionEntry, """List of available attributes in file %s.\nIf you wish to remove some, click on line and edit.""" % ann) self.master.update_idletasks() RHeight = self.master.winfo_reqheight() RWidth = self.master.winfo_reqwidth() self.master.geometry(("%dx%d+300+300") % (RWidth, RHeight)) center(self.master) def Quit(self, event=None): self.master.destroy() def run(self, event=None): self.arguments['edgeFile'] = self.inEdgeFile.get() self.arguments['annotFile'] = self.a.get() if self.k.get(): #print("KeyList defined: %s" % self.k.get()) self.arguments['keyList'] = self.k.get() if self.useConfig.get(): self.arguments['x'] = self.configFile.get() if self.generateConfig.get(): self.arguments['X'] = self.configFile.get() if self.T.get() == '1': self.arguments['trail'] = self.inTrailFile.get() elif self.T.get() == '2': self.arguments['hist'] = self.inTrailFile.get() self.arguments['comp'] = self.CompFile.get() if self.v.get() == '1' or self.v.get() == '2': self.arguments['NodeType'] = self.v.get() else: self.arguments['NodeType'] = self.inNodeType.get() self.arguments['outFile'] = self.outFile.get() self.arguments['Xout'] = self.outFile2.get() self.arguments['log'] = self.l.get() if self.arguments['log'] == 'stderr': self.arguments['log'] = sys.stderr self.arguments['sep'] = self.args.s self.arguments['track'] = self.trackName.get() self.arguments['empty'] = self.Track.get() if self.K.get(): self.arguments['K'] = self.K else: self.arguments['display'] = True if self.k.get(): self.arguments['keyList'] = self.k.get() if self.I.get(): self.arguments['nodeID'] = self.I.get() self.arguments = renorm(self.arguments) self.master.destroy()
class ManagerWindow: """ 主管理界面入口类,直接无参数创建对象即可。 """ # 窗口宽高 WIN_WIDTH = 800 WIN_HEIGHT = 600 def __init__(self): # 界面根节点 self.root = Tk() # 主窗口标题 self.root.title(MANAGER_TITLE) # 读取config self.config_dict = ConfigOperation.get_dir_from_file() # 主窗口分辨率 self.root.geometry("%sx%s+%s+%s" % ( self.WIN_WIDTH, self.WIN_HEIGHT, int((self.root.winfo_screenwidth() - self.WIN_WIDTH) / 2), int((self.root.winfo_screenheight() - self.WIN_HEIGHT) / 2) )) self.root.minsize(self.WIN_WIDTH, self.WIN_HEIGHT) # 选项卡 self.tab_main = Notebook(self.root) self.tab_main.pack(expand=True, fill=BOTH) # 登录选项卡 self.frame_login = Frame(self.tab_main, bg=BG_COLOR) self.frame_login.pack(side=TOP) self.tab_main.add(self.frame_login, text=TAB_NAME_LIST["login"]["text"]) # 管理选项卡 self.frame_manage = Frame(self.tab_main, bg=BG_COLOR) self.tab_main.add(self.frame_manage, text=TAB_NAME_LIST["manage"]["text"]) # 好友选项卡 self.frame_friend = Frame(self.tab_main, bg=BG_COLOR) self.frame_friend.pack(side=TOP) self.tab_main.add(self.frame_friend, text=TAB_NAME_LIST["friends"]["text"]) # 群选项卡 self.frame_group = Frame(self.tab_main, bg=BG_COLOR) self.frame_group.pack(side=TOP) self.tab_main.add(self.frame_group, text=TAB_NAME_LIST["groups"]["text"]) # 插件选项卡 self.frame_plugin = Frame(self.tab_main, bg=BG_COLOR) self.frame_plugin.pack(side=TOP) self.tab_main.add(self.frame_plugin, text=TAB_NAME_LIST["plugins"]["text"]) # 初始化登录选项卡 self.__init_login_tab() # 初始化好友选项卡 self.__init_friend_tab() # 初始化群选项卡 self.__init_group_tab() # 初始化管理选项卡 self.__init_manage_tab() # 初始化插件选项卡 self.__init_plugin_tab() # 关闭窗口自动释放Session self.root.protocol("WM_DELETE_WINDOW", lambda: self.__on_close_root()) # 刷新显示 self.__refresh() # 运行相关线程 fetch_message_thread = FetchMessageThread() fetch_message_thread.daemon = True fetch_message_thread.start() # 运行插件初始化方法 PluginHandler.call_init() # 执行自动连接一次 self.__auto_connect() # 显示 self.root.mainloop() def __init_login_tab(self): """ 初始化登录选项卡界面 :return: 无 """ # 左边列表的frame frame_login_list = Frame(self.frame_login, bg=BG_COLOR) frame_login_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 列表,用于保存连接记录 self.treeview_login_list = Treeview( frame_login_list, columns=[ LOGIN_GUIDE["host"], LOGIN_GUIDE["port"], LOGIN_GUIDE["authkey"], LOGIN_GUIDE["qq"] ], show="headings", selectmode=BROWSE ) self.treeview_login_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_login_list.column( LOGIN_GUIDE["host"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["host"], text=LOGIN_GUIDE["host"] ) self.treeview_login_list.column( LOGIN_GUIDE["port"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["port"], text=LOGIN_GUIDE["port"] ) self.treeview_login_list.column( LOGIN_GUIDE["authkey"], width=40 ) self.treeview_login_list.heading( LOGIN_GUIDE["authkey"], text=LOGIN_GUIDE["authkey"] ) self.treeview_login_list.column( LOGIN_GUIDE["qq"], width=0 ) self.treeview_login_list.heading( LOGIN_GUIDE["qq"], text=LOGIN_GUIDE["qq"] ) # 设定双击事件 self.treeview_login_list.bind( "<Double-Button-1>", lambda event: self.__on_double_click_login_list_content() ) # 设定登录列表的滚动条 scrollbar_login_list = Scrollbar(frame_login_list) scrollbar_login_list.pack(fill="y", expand=True) self.treeview_login_list.config(yscrollcommand=scrollbar_login_list.set) scrollbar_login_list.config(command=self.treeview_login_list.yview) # 设置列表右键菜单 self.treeview_login_list.bind("<Button-3>", self.__show_login_list_pop_up_menu) # 登录界面显示的那一坨 frame_login_menu = Frame(self.frame_login, bg=BG_COLOR) frame_login_menu.pack(side=LEFT, padx=5, pady=5) # mirai端地址 Label(frame_login_menu, text=LOGIN_GUIDE["host"], bg=BG_COLOR).grid(row=0, sticky=E, padx=5, pady=5) self.entry_host = Entry(frame_login_menu) self.entry_host.grid(row=0, column=1, sticky=W, padx=5, pady=5) # mirai端端口号 Label(frame_login_menu, text=LOGIN_GUIDE["port"], bg=BG_COLOR).grid(row=1, sticky=E, padx=5, pady=5) self.entry_port = Entry(frame_login_menu) self.entry_port.grid(row=1, column=1, sticky=W, padx=5, pady=5) # mirai端http授权码 Label(frame_login_menu, text=LOGIN_GUIDE["authkey"], bg=BG_COLOR).grid( row=2, sticky=E, padx=5, pady=5 ) self.entry_authkey = Entry(frame_login_menu, show=PWD_CHAR_CIRCLE) self.entry_authkey.grid(row=2, column=1, sticky=W, padx=5, pady=5) # 用于激活sessioKey的qq号码 Label(frame_login_menu, text=LOGIN_GUIDE["qq"], bg=BG_COLOR).grid( row=3, sticky=E, padx=5, pady=5 ) self.entry_qq = Entry(frame_login_menu) self.entry_qq.grid(row=3, column=1, sticky=W, padx=5, pady=5) # 自动连接复选框 self.auto_connect_var = BooleanVar() self.checkbutton_auto_connect = Checkbutton( frame_login_menu, text=AUTO_CONNECT_GUIDE, onvalue=True, offvalue=False, variable=self.auto_connect_var, bg=BG_COLOR ) self.checkbutton_auto_connect.grid(row=4, column=0, padx=5, pady=5, columnspan=2) # 连接按钮 self.btn_connect = Button( frame_login_menu, text=BTN_TEXT_CONN["connect"], width=15, command=lambda: self.__on_click_connect_event(), ) self.btn_connect.grid(row=5, columnspan=2, padx=5, pady=5) # 添加到登录列表按钮 self.btn_save_login = Button( frame_login_menu, width=15, text=BTN_TEXT_ADD_LOGIN, command=lambda: self.__on_click_add_to_login_list() ) self.btn_save_login.grid(row=6, columnspan=2, padx=5, pady=5) # 状态栏 self.label_login_status_bar = Label( self.root, text=LOGIN_STATUS_BAR_TEXT["notConnect"], fg=STATUS_BAR_COLOR["normal"] ) self.label_login_status_bar.pack(side=LEFT) # 下面开始从config中将内容填充进文本框中 self.entry_host.delete(0, END) self.entry_host.insert(END, self.config_dict["lastConnection"]["host"]) self.entry_port.delete(0, END) self.entry_port.insert(END, self.config_dict["lastConnection"]["port"]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, self.config_dict["lastConnection"]["authkey"]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, self.config_dict["lastConnection"]["qq"]) # 自动连接复选框内容 self.auto_connect_var.set(self.config_dict["autoConnect"]) def __init_friend_tab(self): """ 初始化好友选项卡内容 :return: 无 """ # 创建好友列表框架 frame_friend_list = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_friend_send = Frame(self.frame_friend, bg=BG_COLOR) frame_friend_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_friend_list = Treeview( frame_friend_list, columns=[ FRIEND_GUIDE["qq"], FRIEND_GUIDE["nickname"], FRIEND_GUIDE["remark"] ], show="headings", selectmode=BROWSE ) self.treeview_friend_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_friend_list.column( FRIEND_GUIDE["qq"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["qq"], text=FRIEND_GUIDE["qq"] ) self.treeview_friend_list.column( FRIEND_GUIDE["nickname"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["nickname"], text=FRIEND_GUIDE["nickname"] ) self.treeview_friend_list.column( FRIEND_GUIDE["remark"], width=0 ) self.treeview_friend_list.heading( FRIEND_GUIDE["remark"], text=FRIEND_GUIDE["remark"] ) # 设定好友列表的滚动条 scrollbar_friend_list = Scrollbar(frame_friend_list) scrollbar_friend_list.pack(fill="y", expand=True) self.treeview_friend_list.config(yscrollcommand=scrollbar_friend_list.set) scrollbar_friend_list.config(command=self.treeview_friend_list.yview) # 刷新列表按钮 Button( frame_friend_send, text=BTN_FRIEND_REFRESH, command=lambda: self.__on_click_refresh_friend_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_friend_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_friend_send = Text(frame_friend_send, width=30, height=5) self.text_friend_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_friend_send, text=BTN_SEND, command=lambda: self.__on_click_send_friend_message() ).grid(row=3, padx=5, pady=5) def __init_group_tab(self): """ 初始化群选项卡内容 :return: 无 """ # 创建好友列表框架 frame_group_list = Frame(self.frame_group, bg=BG_COLOR) frame_group_list.pack( side=LEFT, expand=True, fill=BOTH, padx=5, pady=5 ) # 创建消息测试发送框架 frame_group_send = Frame(self.frame_group, bg=BG_COLOR) frame_group_send.pack( side=LEFT, padx=5, pady=5 ) # 设置列表 self.treeview_group_list = Treeview( frame_group_list, columns=[ GROUP_GUIDE["group"], GROUP_GUIDE["name"], GROUP_GUIDE["permission"] ], show="headings", selectmode=BROWSE ) self.treeview_group_list.pack( expand=True, fill=BOTH, side=LEFT ) self.treeview_group_list.column( GROUP_GUIDE["group"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["group"], text=GROUP_GUIDE["group"] ) self.treeview_group_list.column( GROUP_GUIDE["name"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["name"], text=GROUP_GUIDE["name"] ) self.treeview_group_list.column( GROUP_GUIDE["permission"], width=0 ) self.treeview_group_list.heading( GROUP_GUIDE["permission"], text=GROUP_GUIDE["permission"] ) # 设定群列表的滚动条 scrollbar_group_list = Scrollbar(frame_group_list) scrollbar_group_list.pack(fill="y", expand=True) self.treeview_group_list.config(yscrollcommand=scrollbar_group_list.set) scrollbar_group_list.config(command=self.treeview_group_list.yview) # 刷新列表按钮 Button( frame_group_send, text=BTN_GROUP_REFRESH, command=lambda: self.__on_click_refresh_group_list_event() ).grid(row=0, padx=5, pady=5) # 发送纯文本窗口标题 Label(frame_group_send, text=SEND_TITLE, bg=BG_COLOR).grid(row=1, padx=5, pady=5) # 发送纯文本窗口 self.text_group_send = Text(frame_group_send, width=30, height=5) self.text_group_send.grid(row=2, padx=5, pady=5) # 发送按钮 Button( frame_group_send, text=BTN_SEND, command=lambda: self.__on_click_send_group_message() ).grid(row=3, padx=5, pady=5) def __init_manage_tab(self): """ 初始化管理选项卡 :return: 无 """ f_manage = Frame(self.frame_manage, bg=BG_COLOR) f_manage.pack(padx=5, pady=5, expand=True) # 指定头指示 Label(f_manage, text=MANAGE_GUIDE["commandHead"], bg=BG_COLOR).grid( row=0, column=0, padx=5, pady=5, sticky=E ) # 指令头文本框 self.entry_command_head = Entry(f_manage) self.entry_command_head.grid(row=0, column=1, padx=5, pady=5, sticky=EW) # 调试复选框 self.debug_var = BooleanVar() checkbutton_debug = Checkbutton( f_manage, text=MANAGE_GUIDE["debug"], onvalue=True, offvalue=False, variable=self.debug_var, bg=BG_COLOR ) checkbutton_debug.grid(row=1, column=0, columnspan=3, padx=5, pady=5) # 启用机器人 self.enable_var = BooleanVar() checkbutton_enable = Checkbutton( f_manage, text=MANAGE_GUIDE["enable"], onvalue=True, offvalue=False, variable=self.enable_var, bg=BG_COLOR ) checkbutton_enable.grid(row=2, column=0, columnspan=3, padx=5, pady=5) # 配置保存 Button( f_manage, text=MANAGE_GUIDE["saveConfig"], command=self.__on_click_save_config ).grid( row=3, column=1, padx=5, pady=5, sticky=EW ) # bot管理qq列表 self.treeview_op_list = Treeview( f_manage, columns=[ MANAGE_GUIDE["botOpQQ"] ], show="headings", selectmode=BROWSE ) self.treeview_op_list.column(MANAGE_GUIDE["botOpQQ"], width=200) self.treeview_op_list.heading(MANAGE_GUIDE["botOpQQ"], text=MANAGE_GUIDE["botOpQQ"]) self.treeview_op_list.grid( row=4, column=0, columnspan=3, rowspan=10, sticky=EW ) # 列表右键 self.treeview_op_list.bind("<Button-3>", self.__show_op_list_pop_up_menu) # 添加管理标签 Label(f_manage, text=MANAGE_GUIDE["addOpQQ"], bg=BG_COLOR).grid(row=14, column=0, padx=5, pady=5) # 添加管理文本框 self.entry_add_op = Entry(f_manage) self.entry_add_op.grid(row=14, column=1, padx=5, pady=5) # 添加添加按钮 Button( f_manage, text=MANAGE_GUIDE["btnAddOpQQ"], command=lambda: self.__on_click_add_op() ).grid(row=14, column=2, padx=5, pady=5, sticky=EW) def __init_plugin_tab(self): """ 初始化插件选项卡 :return: 无 """ # 指示标签 Label(self.frame_plugin, text=PLUGIN_LABEL_TEXT, bg=BG_COLOR).pack(side=TOP) # 插件列表frame frame_plugin_list = Frame(self.frame_plugin, bg=BG_COLOR) frame_plugin_list.pack( side=TOP, expand=True, fill=BOTH, padx=5, pady=5 ) # 插件列表 self.treeview_plugin_list = Treeview( frame_plugin_list, columns=[ PLUGIN_GUIDE["pluginName"] ], show="headings", selectmode=BROWSE ) self.treeview_plugin_list.pack(fill=BOTH, expand=True, side=LEFT) self.treeview_plugin_list.column(PLUGIN_GUIDE["pluginName"]) self.treeview_plugin_list.heading(PLUGIN_GUIDE["pluginName"], text=PLUGIN_GUIDE["pluginName"]) # 设定插件列表滚动条 scrollbar_plugin_list = Scrollbar(frame_plugin_list) scrollbar_plugin_list.pack(fill="y", expand=True) self.treeview_plugin_list.config(yscrollcommand=scrollbar_plugin_list.set) scrollbar_plugin_list.config(command=self.treeview_plugin_list.yview) def __on_click_connect_event(self): """ 点击连接按钮事件 :return: 无 """ if not GlobalValues.is_connected: # 如果是要连接 # 存到全局使用变量 GlobalValues.conn_host = self.entry_host.get() GlobalValues.conn_port = self.entry_port.get() GlobalValues.conn_authkey = self.entry_authkey.get() try: # 转换为整型后保存 GlobalValues.conn_qq = int(self.entry_qq.get()) except ValueError: self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["wrongQQ"], fg=STATUS_BAR_COLOR["failed"]) return # 修改界面上的一些内容为不可修改 self.__set_login_tools_active(False) # 修改按钮内容 self.btn_connect.config(text=BTN_TEXT_CONN["disconnect"]) # 修改状态栏内容 self.label_login_status_bar.config(text=LOGIN_STATUS_BAR_TEXT["connecting"], fg=STATUS_BAR_COLOR["normal"]) # 调用连接 try: Conn.new_session_key() except ( requests.exceptions.InvalidURL, requests.exceptions.ConnectionError, ): # 连接错误 # 错误信息显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connectFailed"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except WrongAuthkeyException: # 授权码错误 # 显示到状态栏 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["wrongAuthkey"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return except BotNotExistException: # bot不存在错误 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["qqNotExist"], fg=STATUS_BAR_COLOR["failed"] ) # 修改文本框为可修改 self.__set_login_tools_active(True) self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) return self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["connected"], fg=STATUS_BAR_COLOR["passed"] ) # 修改连接状态值 GlobalValues.is_connected = True # 修改上次连接键值对 ConfigOperation.modify_dict("lastConnection", { "host": GlobalValues.conn_host, "port": GlobalValues.conn_port, "authkey": GlobalValues.conn_authkey, "qq": GlobalValues.conn_qq }) # 修改文件中自动连接开关 ConfigOperation.modify_dict("autoConnect", self.auto_connect_var.get()) else: # 如果要断开连接 # 修改文本框为可修改 self.__set_login_tools_active(True) # 修改按钮名称 self.btn_connect.config(text=BTN_TEXT_CONN["connect"]) # 修改属性值 self.label_login_status_bar.config( text=LOGIN_STATUS_BAR_TEXT["disconnectSuccess"], fg=STATUS_BAR_COLOR["normal"] ) # 释放session Conn.release_session_key() # 修改连接状态值 GlobalValues.is_connected = False def __set_login_tools_active(self, active: bool): """ 修改界面上的一些内容为不可修改 :param active: bool,如果为False则禁用掉文本框,否则启用 :return: 无 """ if active: self.entry_host.config(state=ACTIVE) self.entry_port.config(state=ACTIVE) self.entry_authkey.config(state=ACTIVE) self.entry_qq.config(state=ACTIVE) self.checkbutton_auto_connect.config(state=ACTIVE) else: self.entry_host.config(state=DISABLED) self.entry_port.config(state=DISABLED) self.entry_authkey.config(state=DISABLED) self.entry_qq.config(state=DISABLED) self.checkbutton_auto_connect.config(state=DISABLED) def __on_close_root(self): """ 关闭窗口的事件 :return: 无 """ # 如果正在连接则释放连接 if GlobalValues.is_connected: Conn.release_session_key() # 杀掉root self.root.destroy() def __refresh(self): """ 用于刷新界面,在必要时调用 :return: 无 """ def refresh_login_list(): """ 刷新登录列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_login_list.delete(*self.treeview_login_list.get_children()) # 把登录列表内容添加到显示中 for one_record in LoginListOperation.get_list_from_file(): self.treeview_login_list.insert("", index=END, values=( one_record["host"], one_record["port"], one_record["authkey"], one_record["qq"] )) def refresh_op_list(): """ 刷新bot管理员qq列表 :return: 无 """ # 删除目前表中的所有内容 self.treeview_op_list.delete(*self.treeview_op_list.get_children()) # 把内容添加到显示中 for one_record in OpListOperation.get_list(): self.treeview_op_list.insert("", index=END, values=( one_record )) def refresh_config(): """ 刷新配置 :return: 无 """ # 重新获取config self.config_dict = ConfigOperation.get_dir_from_file() # 将文件中的内容显示到界面中 self.entry_command_head.delete(0, END) self.entry_command_head.insert(END, self.config_dict["commandHead"]) # 设置复选框默认勾选 self.debug_var.set(self.config_dict["debug"]) self.enable_var.set(self.config_dict["enable"]) # 将内容设置到全局变量 GlobalValues.command_head = self.config_dict["commandHead"] GlobalValues.debug_var = self.debug_var GlobalValues.enable_var = self.enable_var def refresh_plugin_list(): # 获取插件名称 plugin_names = PluginHandler.get_plugin_name_list() # 显示 self.treeview_plugin_list.delete(*self.treeview_plugin_list.get_children()) for name in plugin_names: self.treeview_plugin_list.insert("", index=END, values=( name )) # 调用刷新登录列表 refresh_login_list() # 调用刷新op列表 refresh_op_list() # 刷新config显示 refresh_config() # 刷新插件列表显示 refresh_plugin_list() def __on_click_add_to_login_list(self): """ 将填写内容添加到列表中 :return: 无 """ # 非空检测 if [ self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ] == [""] * 4: return # 调用添加登录项方法 LoginListOperation.add_to_list( self.entry_host.get(), self.entry_port.get(), self.entry_authkey.get(), self.entry_qq.get() ) # 刷新显示 self.__refresh() def __on_double_click_login_list_content(self): """ 双击登录列表项目时,自动填充到右侧 :return: 无 """ # 获取item的值 item_list = self.treeview_login_list.item(self.treeview_login_list.focus(), "values") # 获取需要的项目并设置 self.entry_host.delete(0, END) self.entry_host.insert(END, item_list[0]) self.entry_port.delete(0, END) self.entry_port.insert(END, item_list[1]) self.entry_authkey.delete(0, END) self.entry_authkey.insert(END, item_list[2]) self.entry_qq.delete(0, END) self.entry_qq.insert(END, item_list[3]) def __show_login_list_pop_up_menu(self, event): """ 显示右键菜单 :param event: 事件 :return: 无 """ def on_delete_event(item_id): """ 删除选项的事件 :return: 无 """ # 删除该项 LoginListOperation.remove_from_list(*self.treeview_login_list.item(item_id, "values")) self.treeview_login_list.delete(item_id) self.__refresh() # 获取选择对象 iid = self.treeview_login_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if iid: self.treeview_login_list.selection_set(iid) menu_pop_up = Menu(self.treeview_login_list, tearoff=False) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event(iid) ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_refresh_friend_list_event(self): """ 点击刷新好友列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 friend_list = Conn.get_friend_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_friend_list.delete(*self.treeview_friend_list.get_children()) # 解析friend_list for friend_block in friend_list: self.treeview_friend_list.insert("", index=END, values=( friend_block["id"], friend_block["nickname"], friend_block["remark"] )) def __on_click_refresh_group_list_event(self): """ 点击刷新群列表事件 :return: 无 """ try: # 如果未连接,则可能会抛出异常,此处直接弹出错误消息框 group_list = Conn.get_group_list() except: messagebox.showerror(message=REFRESH_ERROR_MSG) return # 删除列表内容 self.treeview_group_list.delete(*self.treeview_group_list.get_children()) # 解析group_list for group_block in group_list: self.treeview_group_list.insert("", index=END, values=( group_block["id"], group_block["name"], group_block["permission"] )) def __on_click_send_friend_message(self): """ 点击发送消息给好友按钮 :return: 无 """ # 获取到选中好友的值列表 value_list = self.treeview_friend_list.item(self.treeview_friend_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_friend_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_friend_message(qq, message_chain) self.text_friend_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_send_group_message(self): """ 点击发送消息给群按钮 :return: 无 """ # 获取到选中群的值列表 value_list = self.treeview_group_list.item(self.treeview_group_list.focus(), "values") try: # 获取qq并发送消息 qq = value_list[0] message_chain = MessageChain() text = self.text_group_send.get(1.0, END) if text == "\n": return message_chain.add_plain_text(text) Conn.send_group_message(qq, message_chain) self.text_group_send.delete(1.0, END) except: messagebox.showerror(message=SEND_ERROR_MSG) return def __on_click_add_op(self): """ 点击添加op按钮事件 :return: 无 """ content = self.entry_add_op.get() # 如果添加op的文本框中没有东西,则不添加 if content == "": return # 如果转换数字出错则不添加 try: op_qq = int(content) except ValueError: return # 添加到op列表中 OpListOperation.add_to_list(op_qq) # 刷新显示 self.__refresh() def __show_op_list_pop_up_menu(self, event): """ op列表右键菜单 :return: 无 """ def on_delete_event(): """ 删除选项的事件 :return: 无 """ # 删除该项 # 注意此处的强转,由于能够保证显示出来的内容一定只含有数字,故可以直接转换 OpListOperation.remove_from_list(int(self.treeview_op_list.item(op_qq, "values")[0])) self.treeview_op_list.delete(op_qq) self.__refresh() # 获取选择对象 op_qq = self.treeview_op_list.identify_row(event.y) # 如果有选择,则弹出右键菜单 if op_qq: menu_pop_up = Menu(self.treeview_op_list, tearoff=False) self.treeview_op_list.selection_set(op_qq) menu_pop_up.add_command( label=POP_UP_MENU_DELETE_STR, command=lambda: on_delete_event() ) menu_pop_up.post(event.x_root, event.y_root) def __on_click_save_config(self): """ 点击保存配置事件 :return: 无 """ content = self.entry_command_head.get() # 如果为空,则不存入,但是刷新 # 这样是为了保证点击后会显示原来的设置 if content == "": self.__refresh() return ConfigOperation.modify_dict("commandHead", content) ConfigOperation.modify_dict("debug", self.debug_var.get()) ConfigOperation.modify_dict("enable", self.enable_var.get()) # 刷新 self.__refresh() # 弹出对话框 messagebox.showinfo(message=MANAGE_GUIDE["successSaveCommandHeadMsg"]) def __auto_connect(self): if self.config_dict["autoConnect"]: self.__on_click_connect_event()
def __init__(self, master=None): Frame.__init__(self, master) self.player = StringVar() self.character = StringVar() self.dm = StringVar() self.str = StringVar() self.int = StringVar() self.wis = StringVar() self.dex = StringVar() self.con = StringVar() self.cha = StringVar() self.JPpoison = StringVar() self.JPwands = StringVar() self.JPparalysis = StringVar() self.JPbreath = StringVar() self.JPspell = StringVar() self.class_ = StringVar() self.race = StringVar() self.align = StringVar() self.AC = StringVar() self.HP = StringVar() self.maxHP = StringVar() self.XP_to_add = StringVar() self.XPbonus = StringVar() self.XPtotal = IntVar() self.level = StringVar() self.init_once() ( self.baseXP, self.mainCarRace, self.mainCarClass) = self.classDifferenciation() self.remainingXP = StringVar() self.remainingXP.set(self.getRemainingXP()) self.bonusXP = StringVar() self.bonusXP.set(self.getBonusXP()) self.freeze = IntVar() self.freeze.set(1) Label(self, text="Player Name:").grid(row=0, column=0, columnspan=2) Label(self, text="Character Name :").grid( row=0, column=4, columnspan=2) Label(self, text="DM Name:").grid(row=0, column=8, columnspan=2) Label(self, text="STR:").grid(row=1, column=0) Label(self, text="INT:").grid(row=2, column=0) Label(self, text="WIS:").grid(row=3, column=0) Label(self, text="DEX:").grid(row=4, column=0) Label(self, text="CON:").grid(row=5, column=0) Label(self, text="CHA:").grid(row=6, column=0) Label(self, text="Poison/Deathray:").grid(row=1, column=2) Label(self, text="Wands:").grid(row=2, column=2) Label(self, text="Paralysis:").grid(row=3, column=2) Label(self, text="Dragon Breath:").grid(row=4, column=2) Label(self, text="Spells:").grid(row=5, column=2) Label(self, text="Armor Class").grid(row=1, column=4, columnspan=1) Label(self, text="Health Points").grid(row=1, column=5, columnspan=3) Label(self, text=" / ").grid(row=2, column=6) Label(self, text="Class :").grid(row=3, column=4) Label(self, text="Race :").grid(row=4, column=4) Label(self, text="XP to add :").grid(row=7, column=0) Label(self, text="Remaining :").grid(row=8, column=0) Label(self, text="Bonus :").grid(row=7, column=2) Label(self, text="Alignment :").grid(row=3, column=6) Label(self, text="Level :").grid(row=9, column=0, columnspan=2) self.remainingLabel = Label( self, textvariable=self.remainingXP, relief=SUNKEN, width=5) self.remainingLabel.grid(row=8, column=1) self.bonusLabel = Label( self, textvariable=self.bonusXP, relief=SUNKEN, width=5) self.bonusLabel.grid(row=7, column=3) self.levelLabel = Label( self, textvariable=self.level, relief=SUNKEN, width=5) self.levelLabel.grid(row=9, column=2, columnspan=2) Eplayer = Entry(self, textvariable=self.player) Eplayer.grid(row=0, column=2, columnspan=2) Eplayer.bind(sequence='<KeyRelease>', func=self.refresh) Echaracter = Entry(self, textvariable=self.character) Echaracter.grid(row=0, column=6, columnspan=2) Echaracter.bind(sequence='<KeyRelease>', func=self.refresh) EDM = Entry(self, textvariable=self.dm) EDM.grid(row=0, column=10, columnspan=2) EDM.bind(sequence='<KeyRelease>', func=self.refresh) Estr = Entry(self, textvariable=self.str) Estr.grid(row=1, column=1) Estr.bind(sequence='<KeyRelease>', func=self.refresh) Eint = Entry(self, textvariable=self.int) Eint.grid(row=2, column=1) Eint.bind(sequence='<KeyRelease>', func=self.refresh) Ewis = Entry(self, textvariable=self.wis) Ewis.grid(row=3, column=1) Ewis.bind(sequence='<KeyRelease>', func=self.refresh) Edex = Entry(self, textvariable=self.dex) Edex.grid(row=4, column=1) Edex.bind(sequence='<KeyRelease>', func=self.refresh) Econ = Entry(self, textvariable=self.con) Econ.grid(row=5, column=1) Econ.bind(sequence='<KeyRelease>', func=self.refresh) Echa = Entry(self, textvariable=self.cha) Echa.grid(row=6, column=1) Echa.bind(sequence='<KeyRelease>', func=self.refresh) Entry(self, textvariable=self.JPpoison).grid(row=1, column=3) Entry(self, textvariable=self.JPwands).grid(row=2, column=3) Entry(self, textvariable=self.JPparalysis).grid(row=3, column=3) Entry(self, textvariable=self.JPbreath).grid(row=4, column=3) Entry(self, textvariable=self.JPspell).grid(row=5, column=3) Entry(self, textvariable=self.AC).grid(row=2, column=4) Entry(self, textvariable=self.HP).grid(row=2, column=5) Entry(self, textvariable=self.maxHP).grid(row=2, column=7) EXP = Entry(self, textvariable=self.XP_to_add) EXP.grid(row=7, column=1) EXP.bind(sequence='<KeyPress-Return>', func=self.addXP) OptionMenu( self, self.class_, "Class", "Warrior", "Wizard", "Thief", "Cleric").grid(row=3, column=5) OptionMenu( self, self.align, "Alignment", "Lawful Good", "Lawful Neutral", "Lawful Evil", "Neutral Good", "Neutral Neutral", "Neutral Evil", "Chaotic Good", "Chaotic Neutral", "Chaotic Evil").grid(row=3, column=7) OptionMenu( self, self.race, "Race", "Human", "Elf", "Dwarf", "Halfelin").grid(row=4, column=5) Button( self, text="Add XP", command=self.refresh, width=6).grid(row=10, column=3)
def __init__(self, parent, url=None, buttonSEC=False, buttonRSS=False): super(DialogURL, self).__init__(parent) self.parent = parent parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.accepted = False self.url = None self.transient(self.parent) self.title("Enter URL") self.urlVar = StringVar() self.urlVar.set(url if url is not None else "http://") frame = Frame(self) urlLabel = Label(frame, text=_("URL:"), underline=0) urlEntry = Entry(frame, textvariable=self.urlVar, width=60) urlEntry.focus_set() okButton = Button(frame, text=_("OK"), command=self.ok) cancelButton = Button(frame, text=_("Cancel"), command=self.close) if buttonSEC: usSecButton = Button(frame, text=_("SEC search"), command=self.usSec) usSecButton.grid(row=1, column=1, sticky=W, pady=3) ToolTip( usSecButton, text= _("Opens US SEC Edgar Company Search (in web browser)\n\n" "(1) Find the company in web browser,\n" "(2) Click 'documents' button for desired filing,\n" "(3) Find 'data files' panel, instance document row, 'document' column,\n" "(4) On instance document file name, right-click browser menu: 'copy shortcut',\n" "(5) Come back to this dialog window,\n" "(6) Ctrl-v (paste) shortcut into above URL text box,\n" "(7) Click ok button to load instance document"), wraplength=480) if buttonRSS: rssButton = Button(frame, text=_("SEC RSS"), command=self.rssFeed) rssButton.grid(row=1, column=1, pady=3) ToolTip(rssButton, text=_("Opens current US SEC Edgar RSS feed"), wraplength=480) urlLabel.grid(row=0, column=0, sticky=W, pady=3, padx=3) urlEntry.grid(row=0, column=1, columnspan=3, sticky=EW, pady=3, padx=3) okButton.grid(row=1, column=2, sticky=E, pady=3) ToolTip( okButton, text= _("Opens above URL from web cache, downloading to cache if necessary" ), wraplength=240) cancelButton.grid(row=1, column=3, sticky=EW, pady=3, padx=3) ToolTip(cancelButton, text=_("Cancel operation")) frame.grid(row=0, column=0, sticky=(N, S, E, W)) frame.columnconfigure(1, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100)) self.bind("<Alt-u>", lambda *ignore: urlEntry.focus_set()) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self)
class PlotDialog: """ Display plot dialog for plotting multiple plot """ def __init__(self, parent, plot1, plot2, marker=".", linestyle="solid", linewidth=1.5): """ PlotDialog constructor """ self.__plots = [plot1, plot2] self.__marker = marker self.__linestyle = linestyle self.__linewidth = linewidth top = self.top = tkinter.Toplevel(parent) logger.log( logging.INFO, "[PlotDialog] Comparing two plots " + str(plot1) + " " + str(plot2)) top_frame = tkinter.Frame(top, borderwidth=2, relief=tkinter.GROOVE) top_frame.pack(side=tkinter.TOP, fill=tkinter.X, padx=10, pady=10) self.__chkbx_g = tkinter.IntVar() self.__chkbx_g.set(1) self.__check_graph = Checkbutton(top_frame, text="Display graphs to compare", variable=self.__chkbx_g) self.__check_graph.grid(row=1, column=1, rowspan=1, padx=5, pady=5) self.__chkbx_d = tkinter.IntVar() self.__check_graph_diff = Checkbutton(top_frame, text="Display diff as graph", variable=self.__chkbx_d) self.__check_graph_diff.grid(row=1, column=2, rowspan=1, padx=5, pady=5) self.__chkbx_v = tkinter.IntVar() self.__check_graph_values = Checkbutton(top_frame, text="Display diff as values", variable=self.__chkbx_v) self.__check_graph_values.grid(row=2, column=2, rowspan=1, padx=5, pady=5) label_threshold = Label(top_frame, text="Diff threshold:", anchor="w") label_threshold.grid(row=1, column=3, padx=5, pady=5) self.__entry_threshold = Entry(top_frame, width=15) self.__entry_threshold.insert(tkinter.END, '0.1') self.__entry_threshold.grid(row=1, column=4, columnspan=1, rowspan=1, padx=5, pady=5) label_round = Label(top_frame, text="Diff round:", anchor="w") label_round.grid(row=2, column=3, padx=5, pady=5) self.__entry_round = Entry(top_frame, width=15) self.__entry_round.insert(tkinter.END, '2') self.__entry_round.grid(row=2, column=4, columnspan=1, rowspan=1, padx=5, pady=5) display_button = Button(top_frame, text="Display", command=self.display, width=15) display_button.grid(row=1, column=5, rowspan=1, padx=5, pady=5) clear_button = Button(top_frame, text="Clear", command=self.clear, width=15) clear_button.grid(row=2, column=5, rowspan=1, padx=5, pady=5) title_button = Button(top_frame, text="Add title", command=self.add_title, width=20) title_button.grid(row=1, column=6, columnspan=1, rowspan=1, padx=5, pady=5) graph_frame = tkinter.Frame(top, borderwidth=2, relief=tkinter.GROOVE) graph_frame.pack(side=tkinter.BOTTOM, padx=10, pady=10, fill=tkinter.BOTH, expand=True) figure = Figure(figsize=(8, 4)) figure.subplots_adjust(left=0.08, right=0.845, bottom=0.14) self.__graph = figure.add_subplot(111) self.__canvas = FigureCanvasTkAgg(figure, master=graph_frame) self.__canvas.draw() self.__canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1) toolbar = NavigationToolbar2Tk(self.__canvas, graph_frame) toolbar.update() self.__canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1) graph_compare_plot(self.__graph, plot1, plot2, self.__marker, self.__linestyle, self.__linewidth) self.__canvas.draw() def display(self): """ Display in the graph frame """ graph_clear(self.__graph) if self.__chkbx_g.get(): graph_compare_plot(self.__graph, self.__plots[0], self.__plots[1], self.__marker, self.__linestyle, self.__linewidth) if self.__chkbx_d.get(): graph_compare_plot_diff(self.__graph, self.__plots[0], self.__plots[1], self.__marker, self.__linestyle, self.__linewidth) if self.__chkbx_v.get(): graph_compare_plot_values(self.__graph, self.__plots[0], self.__plots[1], float(self.__entry_threshold.get()), bool(self.__chkbx_d.get()), int(self.__entry_round.get())) self.__canvas.draw() def add_title(self): """ Add title to the graph""" title = simpledialog.askstring("Graph Title", "What is the title of the Graph?", parent=self.top) if title is not None and title != "": graph_add_title(self.__graph, title) self.__canvas.draw() def clear(self): """ Clear the graph frame """ graph_clear(self.__graph) self.__canvas.draw()
class Query(Toplevel): """Base class for getting verified answer from a user. For this base class, accept any non-blank string. """ def __init__(self, parent, title, message, *, text0='', used_names={}, _htest=False, _utest=False): """Create popup, do not return until tk widget destroyed. Additional subclass init must be done before calling this unless _utest=True is passed to suppress wait_window(). title - string, title of popup dialog message - string, informational message to display text0 - initial value for entry used_names - names already in use _htest - bool, change box location when running htest _utest - bool, leave window hidden and not modal """ Toplevel.__init__(self, parent) self.withdraw() # Hide while configuring, especially geometry. self.parent = parent self.title(title) self.message = message self.text0 = text0 self.used_names = used_names self.transient(parent) self.grab_set() windowingsystem = self.tk.call('tk', 'windowingsystem') if windowingsystem == 'aqua': try: self.tk.call('::tk::unsupported::MacWindowStyle', 'style', self._w, 'moveableModal', '') except: pass self.bind("<Command-.>", self.cancel) self.bind('<Key-Escape>', self.cancel) self.protocol("WM_DELETE_WINDOW", self.cancel) self.bind('<Key-Return>', self.ok) self.bind("<KP_Enter>", self.ok) self.resizable(height=False, width=False) self.create_widgets() self.update_idletasks() # Needed here for winfo_reqwidth below. self.geometry( # Center dialog over parent (or below htest box). "+%d+%d" % (parent.winfo_rootx() + (parent.winfo_width() / 2 - self.winfo_reqwidth() / 2), parent.winfo_rooty() + ((parent.winfo_height() / 2 - self.winfo_reqheight() / 2) if not _htest else 150))) if not _utest: self.deiconify() # Unhide now that geometry set. self.wait_window() def create_widgets(self): # Call from override, if any. # Bind to self widgets needed for entry_ok or unittest. self.frame = frame = Frame(self, padding=10) frame.grid(column=0, row=0, sticky='news') frame.grid_columnconfigure(0, weight=1) entrylabel = Label(frame, anchor='w', justify='left', text=self.message) self.entryvar = StringVar(self, self.text0) self.entry = Entry(frame, width=30, textvariable=self.entryvar) self.entry.focus_set() self.error_font = Font(name='TkCaptionFont', exists=True, root=self.parent) self.entry_error = Label(frame, text=' ', foreground='red', font=self.error_font) self.button_ok = Button(frame, text='OK', default='active', command=self.ok) self.button_cancel = Button(frame, text='Cancel', command=self.cancel) entrylabel.grid(column=0, row=0, columnspan=3, padx=5, sticky=W) self.entry.grid(column=0, row=1, columnspan=3, padx=5, sticky=W + E, pady=[10, 0]) self.entry_error.grid(column=0, row=2, columnspan=3, padx=5, sticky=W + E) self.button_ok.grid(column=1, row=99, padx=5) self.button_cancel.grid(column=2, row=99, padx=5) def showerror(self, message, widget=None): #self.bell(displayof=self) (widget or self.entry_error)['text'] = 'ERROR: ' + message def entry_ok(self): # Example: usually replace. "Return non-blank entry or None." self.entry_error['text'] = '' entry = self.entry.get().strip() if not entry: self.showerror('blank line.') return None return entry def ok(self, event=None): # Do not replace. '''If entry is valid, bind it to 'result' and destroy tk widget. Otherwise leave dialog open for user to correct entry or cancel. ''' entry = self.entry_ok() if entry is not None: self.result = entry self.destroy() else: # [Ok] moves focus. (<Return> does not.) Move it back. self.entry.focus_set() def cancel(self, event=None): # Do not replace. "Set dialog result to None and destroy tk widget." self.result = None self.destroy()
class VadTest(Frame): """ A demo class that provides simple GUI for testing voice activity detection on microphone or wav file input. """ def __init__(self, featurizer_path, input_device, wav_file, sample_rate, auto_scale): """ Initialize the VadTest object: featurizer_path - path to the ELL featurizer to use input_device - id of the microphone to use wav_file - optional wav_file to use when you click play sample_rate - the sample rate to resample the incoming audio auto_scale - auto scale audio input to the range [-1, 1] """ super().__init__() self.FEATURIZER_PATH_KEY = "featurizer_path" self.WAV_FILE_KEY = "wav_file" self.main_thread = get_ident() self.output_clear_time = 5000 self.channels = 1 self.init_ui() self.auto_scale = auto_scale self.get_settings_file_name() self.load_settings() self.max_spectrogram_width = 120 self.spectrogram_image = None self.spectrogram_image_data = None self.show_spectrogram = True self.colormap_name = "inferno" self.min_value = 0.0 self.max_value = 1.0 self.update_minmax = True self.levels = [] self.signals = [] self.featurizer_path = None self.featurizer = None self.reading_input = False # Threads self.read_input_thread = None self.lock = Lock() self.main_thread = get_ident() self.message_queue = [] self.animation = None # featurizer if featurizer_path: self.featurizer_path = featurizer_path self.settings[self.FEATURIZER_PATH_KEY] = featurizer_path elif self.FEATURIZER_PATH_KEY in self.settings: self.featurizer_path = self.settings[self.FEATURIZER_PATH_KEY] self.sample_rate = sample_rate self.input_device = input_device self.wav_filename = None self.wav_file = None if wav_file: self.wav_filename = wav_file self.settings[self.WAV_FILE_KEY] = wav_file if self.wav_filename is None and self.WAV_FILE_KEY in self.settings: self.wav_filename = self.settings[self.WAV_FILE_KEY] self.wav_file_list = None self.speaker = None self.microphone = None self.save_settings() # in case we just changed it. if self.featurizer_path: self.load_featurizer_model(os.path.abspath(self.featurizer_path)) else: self.show_output("Please specify and load a feature model") self.update_ui() def init_ui(self): self.master.title("VAD Test") self.pack(side="top", fill=BOTH, expand=True) # VAD Controls section for controlling these VAD settings: controls_frame = LabelFrame(self, text="Controls", height=30) Label(controls_frame, text="tau_up:").grid(row=0, column=0) self.tau_up = Entry(controls_frame, width=15) self.tau_up.grid(row=1, column=0) Label(controls_frame, text="tau_down:").grid(row=0, column=1) self.tau_down = Entry(controls_frame, width=15) self.tau_down.grid(row=1, column=1) Label(controls_frame, text="threshold_up:").grid(row=0, column=2) self.threshold_up = Entry(controls_frame, width=15) self.threshold_up.grid(row=1, column=2) Label(controls_frame, text="threshold_down:").grid(row=0, column=3) self.threshold_down = Entry(controls_frame, width=15) self.threshold_down.grid(row=1, column=3) Label(controls_frame, text="large_input:").grid(row=0, column=4) self.large_input = Entry(controls_frame, width=15) self.large_input.grid(row=1, column=4) Label(controls_frame, text="gain_att:").grid(row=0, column=5) self.gain_att = Entry(controls_frame, width=15) self.gain_att.grid(row=1, column=5) Label(controls_frame, text="level_threshold:").grid(row=0, column=6) self.level_threshold = Entry(controls_frame, width=15) self.level_threshold.grid(row=1, column=6) controls_frame.pack(side=TOP) # Input section input_frame = LabelFrame(self, text="Input") input_frame.bind("-", self.on_minus_key) input_frame.bind("+", self.on_plus_key) input_frame.pack(fill=X) self.play_button = Button(input_frame, text="Play", command=self.on_play_button_click) self.play_button.pack(side=RIGHT, padx=4) self.rec_button = Button(input_frame, text="Rec", command=self.on_rec_button_click) self.rec_button.pack(side=RIGHT, padx=4) self.wav_filename_entry = Entry(input_frame, width=24) self.wav_filename_entry.pack(fill=X) self.wav_filename_entry.delete(0, END) # Feature section features_frame = LabelFrame(self, text="Features") features_frame.pack(fill=X) features_control_frame = Frame(features_frame) features_control_frame.pack(fill=X) load_features_button = Button(features_control_frame, text="Load", command=self.on_load_featurizer_model) load_features_button.pack(side=RIGHT) self.features_entry = Entry(features_control_frame, width=8) self.features_entry.pack(fill=X) self.features_entry.delete(0, END) viz_frame = Frame(features_frame) viz_frame.bind("%w", self.on_resized) viz_frame.pack(fill=X) self.features_figure = Figure(figsize=(5, 4), dpi=96) self.subplot = self.features_figure.add_subplot(211) self.subplot2 = self.features_figure.add_subplot(212) self.canvas = FigureCanvasTkAgg(self.features_figure, master=viz_frame) self.canvas.draw() self.canvas.show() self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=True) # Output section output_frame = LabelFrame(self, text="Output") output_frame.pack(fill=BOTH, expand=True) self.bind("<Configure>", self.on_resized) self.output_text = Text(output_frame) self.output_text.pack(fill=BOTH, padx=4, expand=True) def on_resized(self, event): window_size = event.width box = self.spectrogram_image.get_window_extent() scale = (box.x1 - box.x0) / self.max_spectrogram_width self.max_spectrogram_width = int((window_size * 0.8) / scale) self.setup_spectrogram_image() def load_featurizer_model(self, featurizer_path): """ load the given compiled ELL featurizer for use in processing subsequent audio input """ if featurizer_path: self.featurizer = featurizer.AudioTransform(featurizer_path, 40) self.setup_spectrogram_image() self.vad = vad.VoiceActivityDetector(self.sample_rate, self.featurizer.output_size) self.show_output("Feature input size: {}, output size: {}".format( self.featurizer.input_size, self.featurizer.output_size)) self.init_data() def setup_spectrogram_image(self): """ this need to be called if you load a new feature model, because the featurizer output size might have changed. """ if self.featurizer: dim = (self.featurizer.output_size, self.max_spectrogram_width) self.spectrogram_image_data = np.zeros(dim, dtype=float) self.subplot.clear() self.spectrogram_image = self.subplot.imshow( self.spectrogram_image_data, vmin=self.min_value, vmax=self.max_value, origin="lower", animated=True, cmap=pyplot.get_cmap(self.colormap_name)) def accumulate_spectrogram_image(self, feature_data): """ accumulate the feature data into the spectrogram image """ image_data = self.spectrogram_image_data feature_data = np.reshape(feature_data, [-1, 1]) new_image = np.hstack( (image_data, feature_data))[:, -image_data.shape[1]:] image_data[:, :] = new_image def set_spectrogram_image(self): """ update the spectrogram image and the min/max values """ self.lock.acquire() # protect access to the shared state if self.update_minmax and self.show_spectrogram: min_value = np.min(self.spectrogram_image_data) max_value = np.max(self.spectrogram_image_data) if np.isfinite(min_value) and np.isfinite(max_value): self.min_value = min_value self.max_value = max_value eps = 0.1 if self.max_value - self.min_value < eps: self.max_value = self.min_value + eps self.spectrogram_image.set_clim(self.min_value, self.max_value) self.spectrogram_image.set_data(self.spectrogram_image_data) self.lock.release() def on_load_featurizer_model(self): """ called when user clicks the Load button for the feature model """ filename = self.features_entry.get() filename = filename.strip('"') self.featurizer_path = filename self.get_sample_rate() self.settings[self.FEATURIZER_PATH_KEY] = filename self.save_settings() self.stop() self.load_featurizer_model(filename) def set_entry(self, e, value): s = str(value) if e.get() != s: e.delete(0, END) e.insert(0, s) def get_entry(self, e): v = e.get() return float(v) def update_ui(self): self.set_entry(self.wav_filename_entry, self.wav_filename) self.set_entry(self.features_entry, self.featurizer_path) self.set_entry(self.tau_up, vad.DEFAULT_TAU_UP) self.set_entry(self.tau_down, vad.DEFAULT_TAU_DOWN) self.set_entry(self.threshold_up, vad.DEFAULT_THRESHOLD_UP) self.set_entry(self.threshold_down, vad.DEFAULT_THRESHOLD_DOWN) self.set_entry(self.large_input, vad.DEFAULT_LARGE_INPUT) self.set_entry(self.gain_att, vad.DEFAULT_GAIN_ATT) self.set_entry(self.level_threshold, vad.DEFAULT_LEVEL_THRESHOLD) def read_ui_settings(self): self.vad.configure(self.get_entry(self.tau_up), self.get_entry(self.tau_down), self.get_entry(self.threshold_up), self.get_entry(self.threshold_down), self.get_entry(self.large_input), self.get_entry(self.gain_att), self.get_entry(self.level_threshold)) def init_data(self): """ initialize the spectrogram_image_data based on the newly loaded model info """ if self.featurizer: dim = (self.featurizer.output_size, self.max_spectrogram_width) self.spectrogram_image_data = np.zeros(dim, dtype=float) if self.spectrogram_image is not None: self.spectrogram_image.set_data(self.spectrogram_image_data) def get_settings_file_name(self): """ this app stores the various UI field values in a settings file in your temp folder so you don't always have to specify the full command line options """ import tempfile temp = tempfile.gettempdir() self.settings_file_name = os.path.join(temp, "ELL", "Audio", "vad_test.json") def load_settings(self): """ load the previously saved settings from disk, if any """ self.settings = {} try: if os.path.isfile(self.settings_file_name): with open(self.settings_file_name, "r") as f: self.settings = json.load(f) except: self.show_output("error loading settings: {}".format( self.settings_file_name)) self.settings = {} def save_settings(self): """ save the current settings to disk """ settings_dir = os.path.dirname(self.settings_file_name) if not os.path.isdir(settings_dir): os.makedirs(settings_dir) with open(self.settings_file_name, "w") as f: json.dump(self.settings, f, indent=2) def on_rec_button_click(self): """ called when user clicks the record button, same button is used to "stop" recording. """ if self.rec_button["text"] == "Rec": self.rec_button["text"] = "Stop" self.play_button["text"] = "Play" self.start_recording() else: self.rec_button["text"] = "Rec" self.on_stopped() def on_play_button_click(self): """ called when user clicks the record button, same button is used to "stop" playback """ if self.play_button["text"] == "Play": self.play_button["text"] = "Stop" self.rec_button["text"] = "Rec" self.on_play() else: self.play_button["text"] = "Play" self.on_stopped() def on_play(self): """ called when user clicks the Play button """ filename = self.wav_filename_entry.get() filename = filename.strip('"') self.wav_filename = filename self.settings[self.WAV_FILE_KEY] = filename self.save_settings() self.start_playing(filename) def on_stop(self): """ called when user clicks the Stop button """ self.reading_input = False if self.wav_file: self.wav_file.close() self.wav_file = None if self.read_input_thread: self.read_input_thread.join() self.read_input_thread = None self.stop() def on_stopped(self): """ called when we reach the end of the wav file playback """ self.play_button["text"] = "Play" self.on_stop() self.subplot2.clear() if (len(self.levels) > 0): levels = np.array(self.levels) levels /= np.max(levels) signals = np.array(self.signals) self.subplot2.plot(levels) self.subplot2.plot(signals) self.vad.reset() self.canvas.draw() self.canvas.show() self.levels = [] self.signals = [] def stop(self): """ called when user clicks the stop button, or we reach the end of a wav file input """ # close streams if self.animation: self.animation.event_source.stop() self.animation = None if self.microphone: self.microphone.close() if self.speaker: self.speaker.close() if self.wav_file: self.wav_file.close() self.wav_file = None self.reading_input = False def get_wav_list(self): if self.wav_filename and os.path.isfile(self.wav_filename): full_path = os.path.abspath(self.wav_filename) dir_name = os.path.dirname(full_path) if not self.wav_file_list: print("wav file name: {}".format(full_path)) print("looking for wav files in: {}".format(dir_name)) self.wav_file_list = [ x for x in os.listdir(dir_name) if os.path.splitext(x)[1] == ".wav" ] self.wav_file_list.sort() return self.wav_file_list def select_wav_file(self, filename): self.wav_filename = filename # show the file in the UI self.wav_filename_entry.delete(0, END) if self.wav_filename: self.wav_filename_entry.insert(0, self.wav_filename) # and automatically play the file. self.on_play() def on_minus_key(self, event): """ When user presses the plus button we reverse to the previous wav file in the current folder. This way you can easily step through all the training wav files """ if self.get_wav_list(): i = self.wav_file_list.index(os.path.basename(self.wav_filename)) if i - 1 >= 0: next_wav_file = self.wav_file_list[i - 1] dir_name = os.path.dirname(self.wav_filename) self.select_wav_file(os.path.join(dir_name, next_wav_file)) def on_plus_key(self, event): """ When user presses the plus button we advance to the next wav file in the current folder. This way you can easily step through all the training wav files """ if self.get_wav_list(): i = self.wav_file_list.index(os.path.basename(self.wav_filename)) if i + 1 < len(self.wav_file_list): next_wav_file = self.wav_file_list[i + 1] dir_name = os.path.dirname(self.wav_filename) self.select_wav_file(os.path.join(dir_name, next_wav_file)) def clear_output(self): """ remove some of the Output based a the timeout callback """ self.output_text.delete(1.0, 2.0) def process_output(self): """ show output that was queued by background thread """ self.lock.acquire() messages = self.message_queue self.message_queue = [] self.lock.release() for msg in messages: self.show_output(msg) def show_output(self, message): """ show output message, or queue it if we are on a background thread """ if self.main_thread != get_ident(): self.message_queue += [message] return for line in str(message).split('\n'): self.output_text.insert(END, "{}\n".format(line)) self.output_text.see("end") # scroll to end self.after(self.output_clear_time, self.clear_output) def start_playing(self, filename): """ Play a wav file, and classify the audio. Note we use a background thread to read the wav file and we setup a UI animation function to draw the sliding spectrogram image, this way the UI update doesn't interfere with the smoothness of the audio playback """ self.stop() self.read_ui_settings() self.reading_input = False self.wav_file = wav_reader.WavReader(self.sample_rate, self.channels, auto_scale=self.auto_scale) self.wav_file.open(filename, self.featurizer.input_size, self.speaker) self.setup_spectrogram_image() def update_func(frame_index): self.process_output() if not self.reading_input: self.after(1, self.on_stopped) self.set_spectrogram_image() return (self.spectrogram_image, ) if self.animation: self.animation.event_source.stop() self.reading_input = True # Start animation timer for updating the UI (e.g. spectrogram image) (30 fps is usually fine) self.animation = animation.FuncAnimation(self.features_figure, update_func, interval=33, blit=True) # start background thread to read and classify the audio. self.featurizer.open(self.wav_file) self.read_input_thread = Thread(target=self.on_read_features, args=()) self.read_input_thread.daemon = True self.read_input_thread.start() def start_recording(self): """ Start recording audio from the microphone nd classify the audio. Note we use a background thread to process the audio and we setup a UI animation function to draw the sliding spectrogram image, this way the UI update doesn't interfere with the smoothness of the microphone readings """ if self.microphone is None: self.microphone = microphone.Microphone(True, False) self.stop() self.read_ui_settings() num_channels = 1 self.microphone.open(self.featurizer.input_size, self.sample_rate, num_channels, self.input_device) def update_func(frame_index): # this is an animation callback to update the UI every 33 milliseconds. self.process_output() self.set_spectrogram_image() if not self.reading_input: self.after(1, self.on_stopped) return (self.spectrogram_image, ) if self.animation: self.animation.event_source.stop() self.reading_input = True # Start animation timer for updating the UI (e.g. spectrogram image) (30 fps is usually fine) self.animation = animation.FuncAnimation(self.features_figure, update_func, interval=33, blit=True) # start background thread to read and classify the recorded audio. self.featurizer.open(self.microphone) self.read_input_thread = Thread(target=self.on_read_features, args=()) self.read_input_thread.daemon = True self.read_input_thread.start() def on_read_features(self): """ this is the background thread entry point. So we read the feature data in a loop """ try: while self.reading_input and self.featurizer: feature_data = self.featurizer.read() if feature_data is None: break # eof else: signal = self.vad.process(feature_data) self.levels += [self.vad.level] self.signals += [signal] self.lock.acquire() if self.show_spectrogram: self.accumulate_spectrogram_image(feature_data) self.lock.release() except: errorType, value, traceback = sys.exc_info() print("### Exception reading input: " + str(errorType) + ": " + str(value) + " " + str(traceback)) while traceback: print(traceback.tb_frame.f_code) traceback = traceback.tb_next self.reading_input = False
class MainWindow(object): """Handles all the configuration and starts flashing window Args: master: Tkinter root window """ def __init__(self, master: Tk): self.master = master master.title('P300 speller configuration') self.p300_window = None # Variables self.usable_images = [] self.image_labels = [] self.flash_sequence = [] self.flash_image = None self.sequence_number = 0 self.lsl_output = None self.config = ConfigParams() # Widget definition self.changeable_widgets = [] self.config_file_label = Label(self.master, text='Config File:') self.config_file_label.grid(row=0, column=0) self.config_file_entry = Entry(self.master, textvariable=self.config.config_file_path) self.config_file_entry.grid(row=0, column=1, sticky=EW) self.changeable_widgets.append(self.config_file_entry) self.open_conf_btn = Button(self.master, text='Open config file', command=lambda: self.open_file_update_entry(self.config.config_file_path)) self.open_conf_btn.grid(row=0, column=2, sticky=EW) self.changeable_widgets.append(self.open_conf_btn) self.use_conf_btn = Button(self.master, text='Apply', command=self.config.read_from_file) self.use_conf_btn.grid(row=0, column=3) self.changeable_widgets.append(self.use_conf_btn) self.save_settings_btn = Button(self.master, text='Save', command=self.config.save_to_file) self.save_settings_btn.grid(row=0, column=4) self.changeable_widgets.append(self.save_settings_btn) self.images_folder_label = Label(self.master, text='Images folder:') self.images_folder_label.grid(row=1, column=0) self.images_folder_entry = Entry(self.master, textvariable=self.config.images_folder_path) self.images_folder_entry.grid(row=1, column=1, sticky=EW) self.changeable_widgets.append(self.images_folder_entry) self.open_images_dir_btn = Button(self.master, text='Open image folder', command=lambda: self.open_folder_update_entry( self.config.images_folder_path)) self.open_images_dir_btn.grid(row=1, column=2, sticky=EW) self.changeable_widgets.append(self.open_images_dir_btn) self.flash_image_label = Label(self.master, text='Flash image:') self.flash_image_label.grid(row=2, column=0) self.flash_image_file_entry = Entry(self.master, textvariable=self.config.flash_image_path) self.flash_image_file_entry.grid(row=2, column=1, sticky=EW) self.changeable_widgets.append(self.flash_image_file_entry) self.open_flash_dir_btn = Button(self.master, text='Open image', command=lambda: self.open_file_update_entry( self.config.flash_image_path)) self.open_flash_dir_btn.grid(row=2, column=2, sticky=EW) self.changeable_widgets.append(self.open_flash_dir_btn) self.imagesize_label = Label(self.master, text='Imagesize (px):') self.imagesize_label.grid(row=3, column=0) self.imagesize_entry = Entry(self.master, textvariable=self.config.imagesize) self.imagesize_entry.grid(row=3, column=1, sticky=W) self.changeable_widgets.append(self.imagesize_entry) self.number_of_rows_label = Label(self.master, text='Number of rows:') self.number_of_rows_label.grid(row=4, column=0) self.number_of_rows_entry = Entry(self.master, textvariable=self.config.number_of_rows) self.number_of_rows_entry.grid(row=4, column=1, sticky=W) self.changeable_widgets.append(self.number_of_rows_entry) self.number_of_columns_label = Label(self.master, text='Number of columns:') self.number_of_columns_label.grid(row=5, column=0) self.number_of_columns_entry = Entry(self.master, textvariable=self.config.number_of_columns) self.number_of_columns_entry.grid(row=5, column=1, sticky=W) self.changeable_widgets.append(self.number_of_columns_entry) self.lsl_streamname_label = Label(self.master, text='LSL Streamname:') self.lsl_streamname_label.grid(row=6, column=0) self.lsl_streamname_entry = Entry(self.master, textvariable=self.config.lsl_streamname) self.lsl_streamname_entry.grid(row=6, column=1, sticky=W) self.changeable_widgets.append(self.lsl_streamname_entry) self.flash_duration_label = Label(self.master, text='Flash duration (ms):') self.flash_duration_label.grid(row=7, column=0) self.flash_duration_entry = Entry(self.master, textvariable=self.config.flash_duration) self.flash_duration_entry.grid(row=7, column=1, sticky=W) self.changeable_widgets.append(self.flash_duration_entry) self.break_duration_label = Label(self.master, text='Break duration (ms):') self.break_duration_label.grid(row=8, column=0) self.break_duration_entry = Entry(self.master, textvariable=self.config.break_duration) self.break_duration_entry.grid(row=8, column=1, sticky=W) self.changeable_widgets.append(self.break_duration_entry) self.flash_mode_label = Label(self.master, text='Flashmode:') self.flash_mode_label.grid(row=9, column=0) self.flash_mode_1_rb = Radiobutton(self.master, text='Rows and Columns (Sequence not pseudorandom yet!)', variable=self.config.flash_mode, value=1) self.flash_mode_1_rb.grid(row=9, column=1, sticky=W) self.changeable_widgets.append(self.flash_mode_1_rb) self.flash_mode_2_rb = Radiobutton(self.master, text='Single images', variable=self.config.flash_mode, value=2) self.flash_mode_2_rb.grid(row=10, column=1, sticky=W) self.changeable_widgets.append(self.flash_mode_2_rb) self.set_flash_mode_rbs() self.text_console = Text(self.master) self.text_console.grid(row=11, column=0, rowspan=4, columnspan=5) self.text_console.configure(state='disabled') self.close_button = Button(self.master, text='Close', command=master.quit) self.close_button.grid(row=15, column=0) self.open_button = Button(self.master, text='Open', command=self.open_p300_window) self.open_button.grid(row=15, column=3) self.changeable_widgets.append(self.open_button) def set_flash_mode_rbs(self): if self.config.flash_mode.get() is 1: self.flash_mode_1_rb.select() else: self.flash_mode_2_rb.select() def open_folder_update_entry(self, entry_var): new_path = filedialog.askdirectory() if new_path is not '': entry_var.set(new_path) def open_file_update_entry(self, entry_var): new_path = filedialog.askopenfilename() if new_path is not '': entry_var.set(new_path) def print_to_console(self, text_to_print): if not isinstance(text_to_print, str): text_to_print = str(text_to_print) self.text_console.configure(state='normal') self.text_console.insert('end', text_to_print + '\n') self.text_console.configure(state='disabled') def disable_all_widgets(self): for widget in self.changeable_widgets: widget.configure(state='disabled') self.master.iconify() def enable_all_widgets(self): for widget in self.changeable_widgets: widget.configure(state='normal') self.master.deiconify() def open_p300_window(self): p300_window_master = Toplevel(self.master) self.p300_window = P300Window(p300_window_master, self, self.config) self.disable_all_widgets()
def __init__(self, master): # create dictionary of possible messages to deliver to user self.messages = {} self.messages['instructions'] = 'Type up to three input variables in the boxes below and click compute. ' \ 'Enter all variables in units based on meters, seconds, and degrees.' # create frame within main window to hold widgets mainframe = Frame(master) mainframe.grid() # create template of necessary variables for auto-generation dict_list = ['v', 'angle', 'vx', 'viy', 'vfy', 't', 'deltax', 'deltay'] # create label to hold instructions and other messages self.current_message = StringVar() self.current_message.set(self.messages['instructions']) Label(mainframe, textvariable=self.current_message).grid(row=0, columnspan=3, sticky='we') # create descriptive text labels (can't auto-generate from template) Label(mainframe, text='Launch Speed:', justify=RIGHT).grid(column=0, row=1, sticky='e') Label(mainframe, text='Launch Angle:').grid(column=0, row=2, sticky='e') Label(mainframe, text='Horizontal Velocity:').grid(column=0, row=3, sticky='e') Label(mainframe, text='Initial Vertical Velocity:').grid(column=0, row=4, sticky='e') Label(mainframe, text='Final Vertical Velocity:').grid(column=0, row=5, sticky='e') Label(mainframe, text='Time:').grid(column=0, row=6, sticky='e') Label(mainframe, text='Range').grid(column=0, row=7, sticky='e') Label(mainframe, text='Vertical Displacement:').grid(column=0, row=8, sticky='e') # create compute button Button(mainframe, text="Solve", command=self.compute).grid(row=9, columnspan=3, sticky='ew') # create dictionaries to store tk DoubleVars # user_entries stores information typed by the user # display_entries stores information returned from solve method self.user_entries = {} self.display_entries = {} # auto-generate necessary DoubleVars and necessary widgets in rows 1-8 for key in dict_list: self.user_entries[key] = DoubleVar(value='') self.display_entries[key] = StringVar(value='Not Calculated') temp = Entry(mainframe, textvariable=self.user_entries[key], width=10) temp.grid(column=1, row=dict_list.index(key) + 1) temp = Label(mainframe, textvariable=self.display_entries[key]) temp.grid(column=2, row=dict_list.index(key) + 1, sticky='e')
def initUI(self): self.parent.title("Calculator") Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 14') # set up internal padding of cells, left,top,right, bottom. From label # to edge of cell box self.columnconfigure(0, pad=3) self.columnconfigure(1, pad=3) self.columnconfigure(2, pad=3) self.columnconfigure(3, pad=3) self.rowconfigure(0, pad=3) self.rowconfigure(1, pad=3) self.rowconfigure(2, pad=3) self.rowconfigure(3, pad=3) self.rowconfigure(4, pad=3) # padding on each side of row. entry = Entry(self) entry.grid(row=0, columnspan=4, sticky=W+E) # unclear meaning. The colspan says the entry # field spans at least four columns, but the stick seems to # to do nothing. It is supposed to make it fill the grid space. cls = Button(self, text="Cls") cls.grid(row=1, column=0) bck = Button(self, text="Back") bck.grid(row=1, column=1) lbl = Button(self) lbl.grid(row=1, column=2) clo = Button(self, text="Close") clo.grid(row=1, column=3) sev = Button(self, text="7") sev.grid(row=2, column=0) eig = Button(self, text="8") eig.grid(row=2, column=1) nin = Button(self, text="9") nin.grid(row=2, column=2) div = Button(self, text="/") div.grid(row=2, column=3) fou = Button(self, text="4") fou.grid(row=3, column=0) fiv = Button(self, text="5") fiv.grid(row=3, column=1) six = Button(self, text="6") six.grid(row=3, column=2) mul = Button(self, text="*") mul.grid(row=3, column=3) one = Button(self, text="1") one.grid(row=4, column=0) two = Button(self, text="2") two.grid(row=4, column=1) thr = Button(self, text="3") thr.grid(row=4, column=2) mns = Button(self, text="-") mns.grid(row=4, column=3) zer = Button(self, text="0") zer.grid(row=5, column=0) dot = Button(self, text=".") dot.grid(row=5, column=1) equ = Button(self, text="=") equ.grid(row=5, column=2) pls = Button(self, text="+") pls.grid(row=5, column=3) self.pack()
class ModelFrame(LabelFrame): topPadding = 12 def __init__(self,parent): LabelFrame.__init__(self,parent,text="Model",borderwidth=5) self.selection = tkinter.IntVar() self.exponential = Radiobutton(self,text="Exponential model",variable=self.selection,value=Model.EXP.value,command=self.changeSelection) self.powerlaw = Radiobutton(self,text="Power law model",variable=self.selection,value=Model.POW.value,command=self.changeSelection) self.weibull = Radiobutton(self,text="Weibull model",variable=self.selection,value=Model.WEI.value,command=self.changeSelection) self.exponential.grid(row=0,column=0,sticky="W",padx=10,pady=(self.topPadding,5)) self.powerlaw.grid(row=1,column=0,sticky="W",padx=10,pady=5) self.weibull.grid(row=2,column=0,sticky="W",padx=10,pady=(5,0)) seperator = Separator(self, orient=tkinter.VERTICAL) seperator.grid(row=0, column=1, rowspan=3, sticky="NS", padx=(20,10), pady=(self.topPadding,0)) ## Exponential setup self.expNumberOfSegments_L = Label(self,text="Number of segments: ") self.expNumberOfSegments_E = Entry(self,width=5, justify="right") self.expNumberOfSegments_E.insert(0, settings.EXP_DEFAULT_NUMBER_OF_SEGMENTS) self.expWidgets = [self.expNumberOfSegments_L,self.expNumberOfSegments_E] ## Power law setup self.powProximalLimit_L = Label(self,text="Proximal limit of integration: ") self.powProximalLimit_E = Entry(self,width=5, justify="right") self.powDistalLimit_L = Label(self,text="Distal limit of integration: ") self.powDistalLimit_E = Entry(self,width=5, justify="right") self.powProximalLimit_E.insert(0, settings.POW_DEFAULT_PROXIMAL_LIMIT) self.powDistalLimit_E.insert(0, settings.POW_DEFAULT_DISTAL_LIMIT) self.powWidgets = [self.powProximalLimit_L,self.powProximalLimit_E, self.powDistalLimit_L,self.powDistalLimit_E] ## Weibull setup self.weiNumberOfRuns_L = Label(self,text="Number of runs: ") self.weiNumberOfRuns_E = Entry(self,width=5, justify="right") self.weiIterationsPerRun_L = Label(self,text="Iterations per run: ") self.weiIterationsPerRun_E = Entry(self,width=5, justify="right") self.weiEstimatedTime_L = Label(self,text="Estimated time (s): ") self.weiEstimatedTime_E = CustomEntry(self,width=5, justify="right") self.weiEstimatedTime_E.setUserEditable(False) self.weiLambdaLowerBoundL = Label(self,text="\u03BB lower bound:") self.weiLambdaUpperBoundL = Label(self,text="\u03BB upper bound:") self.weiLambdaLowerBoundE = Entry(self,width=5, justify="right") self.weiLambdaUpperBoundE = Entry(self,width=5, justify="right") self.weiKLowerBoundL = Label(self,text="k lower bound:") self.weiKUpperBoundL = Label(self,text="k upper bound:") self.weiKLowerBoundE = Entry(self,width=5, justify="right") self.weiKUpperBoundE = Entry(self,width=5, justify="right") self.weiNumberOfRuns_E.insert(0, settings.WEI_DEFAULT_NUMBER_OF_RUNS) self.weiIterationsPerRun_E.insert(0, settings.WEI_DEFAULT_ITERATIONS_PER_RUN) self.weiLambdaLowerBoundE.insert(0, settings.WEI_DEFAULT_LAMBDA_LOWER_BOUND) self.weiLambdaUpperBoundE.insert(0, settings.WEI_DEFAULT_LAMBDA_UPPER_BOUND) self.weiKLowerBoundE.insert(0, settings.WEI_DEFAULT_K_LOWER_BOUND) self.weiKUpperBoundE.insert(0, settings.WEI_DEFAULT_K_UPPER_BOUND) self.weiWidgets = [self.weiNumberOfRuns_L,self.weiNumberOfRuns_E, self.weiIterationsPerRun_L,self.weiIterationsPerRun_E, self.weiEstimatedTime_L,self.weiEstimatedTime_E, self.weiLambdaLowerBoundL,self.weiLambdaUpperBoundL,self.weiLambdaLowerBoundE,self.weiLambdaUpperBoundE, self.weiKLowerBoundL,self.weiKUpperBoundL,self.weiKLowerBoundE,self.weiKUpperBoundE] ## General self.currentWidgets = [] self.selection.set(Model.EXP.value) self.changeSelection() def changeSelection(self): for widget in self.currentWidgets: widget.grid_remove() modelType = Model(self.selection.get()) sX = 10 bX = 20 if modelType == Model.EXP: self.expNumberOfSegments_L.grid(row=0,column=2,padx=(bX,sX),pady=(self.topPadding,5),sticky="W") self.expNumberOfSegments_E.grid(row=0,column=3,padx=(sX,bX),pady=(self.topPadding,5),sticky="W") self.currentWidgets = self.expWidgets elif modelType == Model.POW: self.powProximalLimit_L.grid(row=0,column=2,padx=(bX,sX),pady=(self.topPadding,5),sticky="W") self.powProximalLimit_E.grid(row=0,column=3,padx=(sX,bX),pady=(self.topPadding,5),sticky="W") self.powDistalLimit_L.grid(row=1,column=2,padx=(bX,sX),pady=5,sticky="W") self.powDistalLimit_E.grid(row=1,column=3,padx=(sX,bX),pady=5,sticky="W") self.currentWidgets = self.powWidgets elif modelType == Model.WEI: self.weiNumberOfRuns_L.grid(row=0,column=2,padx=(bX,sX),pady=(self.topPadding,5),sticky="W") self.weiNumberOfRuns_E.grid(row=0,column=3,padx=(sX,bX),pady=(self.topPadding,5),sticky="W") self.weiIterationsPerRun_L.grid(row=1,column=2,padx=(bX,sX),pady=5,sticky="W") self.weiIterationsPerRun_E.grid(row=1,column=3,padx=(sX,bX),pady=5,sticky="W") self.weiEstimatedTime_L.grid(row=2,column=2,padx=(bX,sX),pady=5,sticky="W") self.weiEstimatedTime_E.grid(row=2,column=3,padx=(sX,bX),pady=5,sticky="W") self.weiLambdaLowerBoundL.grid(row=0,column=4,padx=(bX,sX),pady=(self.topPadding,5),sticky="W") self.weiLambdaLowerBoundE.grid(row=0,column=5,padx=(sX,bX),pady=(self.topPadding,5)) self.weiLambdaUpperBoundL.grid(row=1,column=4,padx=(bX,sX),pady=5,sticky="W") self.weiLambdaUpperBoundE.grid(row=1,column=5,padx=(sX,bX),pady=5) self.weiKLowerBoundL.grid(row=0,column=6,padx=(bX,sX),pady=(self.topPadding,5),sticky="W") self.weiKLowerBoundE.grid(row=0,column=7,padx=(sX,sX),pady=(self.topPadding,5)) self.weiKUpperBoundL.grid(row=1,column=6,padx=(bX,sX),pady=5,sticky="W") self.weiKUpperBoundE.grid(row=1,column=7,padx=(sX,sX),pady=5) self.currentWidgets = self.weiWidgets def getModelDetails(self): modelType = Model(self.selection.get()) values = [modelType] if modelType == Model.EXP: numberOfSegments = helper_functions.validateValue( self.expNumberOfSegments_E.get(), "The number of exponential segments must be 1 \u2264 n \u2264 " + str(settings.EXP_MAX_NUMBER_OF_SEGMENTS), "int", lowerBound=1, upperBound=settings.EXP_MAX_NUMBER_OF_SEGMENTS) values.append(numberOfSegments) elif modelType == Model.POW: proximalLimitKM = helper_functions.validateValue( self.powProximalLimit_E.get(), "The proximal limit of integration must be 0 \u2264 x \u2264 \u221E", "float", strictLowerBound=0, strictUpperBound=float('inf')) proximalLimitKM /= SQRT_PI distalLimitKM = helper_functions.validateValue( self.powDistalLimit_E.get(), "The distal limit of integration must be prox \u2264 x \u2264 \u221E", "float", strictLowerBound=proximalLimitKM, strictUpperBound=float('inf')) distalLimitKM /= SQRT_PI values.extend([proximalLimitKM,distalLimitKM]) elif modelType == Model.WEI: numberOfRuns = helper_functions.validateValue( self.weiNumberOfRuns_E.get(), "The number of runs must be greater than 0", "int", strictLowerBound=0) iterationsPerRun = helper_functions.validateValue( self.weiIterationsPerRun_E.get(), "The number of iterations must be greater than 0", "int", strictLowerBound=0) lambdaLowerBound = helper_functions.validateValue( self.weiLambdaLowerBoundE.get(), "The lower bound for \u03BB must be a decimal", "float") lambdaUpperBound = helper_functions.validateValue( self.weiLambdaUpperBoundE.get(), "The upper bound for \u03BB must be greater than the lower bound", "float", strictLowerBound=lambdaLowerBound) kLowerBound = helper_functions.validateValue( self.weiKLowerBoundE.get(), "The lower bound for k must be numeric and less than 2", "float", strictUpperBound=2) kUpperBound = helper_functions.validateValue( self.weiKUpperBoundE.get(), "The upper bound for k must be greater than the lower bound and less than or equal to 2", "float", strictLowerBound=kLowerBound, upperBound=2) values.extend([numberOfRuns,iterationsPerRun,[[lambdaLowerBound,lambdaUpperBound],[kLowerBound,kUpperBound]]]) return values
def build(self): """widget construction Parameters ---------- None Results ------- None """ fr1 = LabelFrame(self.fr0, text='rgb') fr1.grid(column=0, row=0, sticky='news') rl0 = Label(fr1, text='red ') rl0.grid(column=0, row=0, sticky='s') self.rcan = Canvas(fr1, width=self.canvas_w, height=self.canvas_h, bd=0, highlightthickness=0) self.rcan.grid(column=1, row=0, sticky='s') rsc = TtkScale(fr1, from_=0, to=255, variable=self.rvar, orient='horizontal', length=self.scale_l, command=self.rhandle, tickinterval=20) rsc.grid(column=1, row=1, sticky='news') rsb = Spinbox(fr1, from_=0, to=255, textvariable=self.rvar, command=self.rhandle, width=5) rsb.grid(column=2, row=1, sticky='nw') rel = Label(fr1, height=1) rel.grid(column=2, row=2) gl0 = Label(fr1, text='green') gl0.grid(column=0, row=3) self.gcan = Canvas(fr1, width=self.canvas_w, height=self.canvas_h, bd=0, highlightthickness=0) self.gcan.grid(column=1, row=3, sticky='s') gsc = TtkScale(fr1, from_=0, to=255, variable=self.gvar, orient='horizontal', length=self.scale_l, command=self.ghandle, tickinterval=20) gsc.grid(column=1, row=4, sticky='news') gsb = Spinbox(fr1, from_=0, to=255, textvariable=self.gvar, command=self.ghandle, width=5) gsb.grid(column=2, row=4, sticky='nw') gel = Label(fr1, height=1) gel.grid(column=2, row=5) bl0 = Label(fr1, text='blue ') bl0.grid(column=0, row=6, sticky='s') self.bcan = Canvas(fr1, width=self.canvas_w, height=self.canvas_h, bd=0, highlightthickness=0) self.bcan.grid(column=1, row=6, sticky='n') bsc = TtkScale(fr1, from_=0, to=255, variable=self.bvar, orient='horizontal', length=self.scale_l, command=self.bhandle, tickinterval=20) bsc.grid(column=1, row=7, sticky='news') bsb = Spinbox(fr1, from_=0, to=255, textvariable=self.bvar, command=self.bhandle, width=5) bsb.grid(column=2, row=7, sticky='nw') bel = Label(fr1, height=1) bel.grid(column=2, row=8) fr3 = LabelFrame(self.fr0, text='colour mix') fr3.grid(column=1, row=0, sticky='nw') self.cmcan = cmcan = Canvas(fr3, width=30, height=30, bd=0, highlightthickness=0) cmcan.grid(column=0, row=0, sticky='n', columnspan=2) cmcan.grid_propagate(0) vdraw_gradient(self.cmcan, (255, 0, 0), alpha=255) cml = Label(fr3, text='hash\nvalue') cml.grid(column=0, row=1) ent0 = Entry(fr3, width=8, textvariable=self.evar) ent0.grid(column=1, row=1) fr2 = LabelFrame(self.fr0, text='opacity') fr2.grid(column=0, row=1, sticky='news') al0 = Label(fr2, text='alpha') al0.grid(column=0, row=0, sticky='s') self.acan = Canvas(fr2, width=self.canvas_w, height=self.canvas_h, bd=0, highlightthickness=0) self.acan.grid(column=1, row=0, sticky='n') asc = TtkScale(fr2, from_=0, to=255, variable=self.avar, orient='horizontal', length=self.scale_l, command=self.ahandle, tickinterval=20) asc.grid(column=1, row=1, sticky='news') asb = Spinbox(fr2, from_=0, to=255, textvariable=self.avar, command=self.ahandle, width=5) asb.grid(column=2, row=1, sticky='nw') ael = Label(fr2, text=' ', height=1) ael.grid(column=2, row=2, sticky='s') draw_gradient(self.rcan, (0, 0, 0), (255, 0, 0), width=self.canvas_w) draw_gradient(self.gcan, (255, 0, 0), (255, 255, 0), width=self.canvas_w) draw_gradient(self.bcan, (255, 0, 0), (255, 0, 255), width=self.canvas_w) draw_agradient(self.acan, (127, 127, 127), (255, 0, 0), width=self.canvas_w)
class HelpSource(Query): "Get menu name and help source for Help menu." # Used in ConfigDialog.HelpListItemAdd/Edit, (941/9) def __init__(self, parent, title, *, menuitem='', filepath='', used_names={}, _htest=False, _utest=False): """Get menu entry and url/local file for Additional Help. User enters a name for the Help resource and a web url or file name. The user can browse for the file. """ self.filepath = filepath message = 'Name for item on Help menu:' super().__init__( parent, title, message, text0=menuitem, used_names=used_names, _htest=_htest, _utest=_utest) def create_widgets(self): super().create_widgets() frame = self.frame pathlabel = Label(frame, anchor='w', justify='left', text='Help File Path: Enter URL or browse for file') self.pathvar = StringVar(self, self.filepath) self.path = Entry(frame, textvariable=self.pathvar, width=40) browse = Button(frame, text='Browse', width=8, command=self.browse_file) self.path_error = Label(frame, text=' ', foreground='red', font=self.error_font) pathlabel.grid(column=0, row=10, columnspan=3, padx=5, pady=[10,0], sticky=W) self.path.grid(column=0, row=11, columnspan=2, padx=5, sticky=W+E, pady=[10,0]) browse.grid(column=2, row=11, padx=5, sticky=W+S) self.path_error.grid(column=0, row=12, columnspan=3, padx=5, sticky=W+E) def askfilename(self, filetypes, initdir, initfile): # htest # # Extracted from browse_file so can mock for unittests. # Cannot unittest as cannot simulate button clicks. # Test by running htest, such as by running this file. return filedialog.Open(parent=self, filetypes=filetypes)\ .show(initialdir=initdir, initialfile=initfile) def browse_file(self): filetypes = [ ("HTML Files", "*.htm *.html", "TEXT"), ("PDF Files", "*.pdf", "TEXT"), ("Windows Help Files", "*.chm"), ("Text Files", "*.txt", "TEXT"), ("All Files", "*")] path = self.pathvar.get() if path: dir, base = os.path.split(path) else: base = None if platform[:3] == 'win': dir = os.path.join(os.path.dirname(executable), 'Doc') if not os.path.isdir(dir): dir = os.getcwd() else: dir = os.getcwd() file = self.askfilename(filetypes, dir, base) if file: self.pathvar.set(file) item_ok = SectionName.entry_ok # localize for test override def path_ok(self): "Simple validity check for menu file path" path = self.path.get().strip() if not path: #no path specified self.showerror('no help file path specified.', self.path_error) return None elif not path.startswith(('www.', 'http')): if path[:5] == 'file:': path = path[5:] if not os.path.exists(path): self.showerror('help file path does not exist.', self.path_error) return None if platform == 'darwin': # for Mac Safari path = "file://" + path return path def entry_ok(self): "Return apparently valid (name, path) or None" self.entry_error['text'] = '' self.path_error['text'] = '' name = self.item_ok() path = self.path_ok() return None if name is None or path is None else (name, path)
""" print(text) index = int(index) if text.isupper() and index == 0: return True if input in (",", ".", "'", " ") and index > 0: return True if inp.isalnum() and index > 0: return True if text == "": return True else: return False vcmd = root.register(is_okay) entsv = StringVar() ent0 = Entry(lf0, validate='key', validatecommand=(vcmd, '%P', '%S', '%i'), textvariable=entsv) ent0.bind("<Return>", end_input) ent0.grid(row=1, column=0, padx=10) ent0.focus() mess_lbl = Label(lf0, text='Start with capital letter, <Return> to confirm') mess_lbl.grid(row=2, column=0, pady=10, padx=10) root.mainloop()
class FunctionDialog: """ Display function dialog for creating plot from math functions """ def __init__(self, parent, function="x*x", xmin=1.0, xmax=10.0, discr=100, xlabel="x", ylabel="x*x"): """ FunctionDialog constructor """ top = self.top = tkinter.Toplevel(parent) self.__entry_function_label = Label(top, text='Enter the function:', width=25) self.__entry_function_label.grid(row=2, column=1, columnspan=2, rowspan=1, padx=5, pady=5) self.__entry_function = Entry(top, width=50) self.__entry_function.insert(tkinter.END, function) self.__entry_function.grid(row=2, column=3, columnspan=4, rowspan=1, padx=5, pady=5) self.__entry_xmin_label = Label(top, text='X min:', width=10) self.__entry_xmin_label.grid(row=3, column=1, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_xmin = Entry(top, width=10) self.__entry_xmin.insert(tkinter.END, xmin) self.__entry_xmin.grid(row=3, column=2, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_xmax_label = Label(top, text='X max:', width=10) self.__entry_xmax_label.grid(row=4, column=1, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_xmax = Entry(top, width=10) self.__entry_xmax.insert(tkinter.END, xmax) self.__entry_xmax.grid(row=4, column=2, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_discr_label = Label(top, text='Discr:', width=10) self.__entry_discr_label.grid(row=3, column=5, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_discr = Entry(top, width=10) self.__entry_discr.insert(tkinter.END, discr) self.__entry_discr.grid(row=3, column=6, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_xlabel_label = Label(top, text='X label:', width=10) self.__entry_xlabel_label.grid(row=3, column=3, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_xlabel = Entry(top, width=10) self.__entry_xlabel.insert(tkinter.END, xlabel) self.__entry_xlabel.grid(row=3, column=4, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_ylabel_label = Label(top, text='Y label:', width=10) self.__entry_ylabel_label.grid(row=4, column=3, columnspan=1, rowspan=1, padx=5, pady=5) self.__entry_ylabel = Entry(top, width=10) self.__entry_ylabel.insert(tkinter.END, ylabel) self.__entry_ylabel.grid(row=4, column=4, columnspan=1, rowspan=1, padx=5, pady=5) self.__plot_button = Button(top, text='Plot', command=self.create_plot_from_function, width=35) self.__plot_button.grid(row=5, column=1, columnspan=3, rowspan=1, padx=5, pady=5) self.__cancel_button = Button(top, text='Cancel', command=self.quit, width=35) self.__cancel_button.grid(row=5, column=4, columnspan=3, rowspan=1, padx=5, pady=5) self.__plot = None def create_plot_from_function(self): """ create plot from math functions """ logger.log( logging.INFO, "[FunctionDialog] Creating plot from math function " + self.__entry_function.get()) self.__plot = PlotCreator.get_instance().plot_from_function( self.__entry_function.get(), self.__entry_xmin.get(), self.__entry_xmax.get(), self.__entry_discr.get(), self.__entry_xlabel.get(), self.__entry_ylabel.get()) self.__plot.set_function(str(self.__entry_function.get())) self.quit() def get_plot(self): """ Get the plot """ return self.__plot def quit(self): """ Exit the dialog """ self.top.destroy()
def initUI(self): self.parent.title("Calculator") Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10') self.pack(fill=BOTH, expand=1) self.columnconfigure(0, pad=3) self.columnconfigure(1, pad=3) self.columnconfigure(2, pad=3) self.columnconfigure(3, pad=3) self.rowconfigure(0, pad=3) self.rowconfigure(1, pad=3) self.rowconfigure(2, pad=3) self.rowconfigure(3, pad=3) self.rowconfigure(4, pad=3) entry = Entry(self) entry.grid(row=0, columnspan=4, sticky=E + W + S + N) cls = Button(self, text="Cls") cls.grid(row=1, column=0, sticky=E + W + S + N) bck = Button(self, text="Back") bck.grid(row=1, column=1, sticky=E + W + S + N) lbl = Button(self) lbl.grid(row=1, column=2, sticky=E + W + S + N) clo = Button(self, text="Close") clo.grid(row=1, column=3, sticky=E + W + S + N) sev = Button(self, text="7") sev.grid(row=2, column=0, sticky=E + W + S + N) eig = Button(self, text="8") eig.grid(row=2, column=1, sticky=E + W + S + N) nin = Button(self, text="9") nin.grid(row=2, column=2, sticky=E + W + S + N) div = Button(self, text="/") div.grid(row=2, column=3, sticky=E + W + S + N) fou = Button(self, text="4") fou.grid(row=3, column=0, sticky=E + W + S + N) fiv = Button(self, text="5") fiv.grid(row=3, column=1, sticky=E + W + S + N) six = Button(self, text="6") six.grid(row=3, column=2, sticky=E + W + S + N) mul = Button(self, text="*") mul.grid(row=3, column=3, sticky=E + W + S + N) one = Button(self, text="1") one.grid(row=4, column=0, sticky=E + W + S + N) two = Button(self, text="2") two.grid(row=4, column=1, sticky=E + W + S + N) thr = Button(self, text="3") thr.grid(row=4, column=2, sticky=E + W + S + N) mns = Button(self, text="-") mns.grid(row=4, column=3, sticky=E + W + S + N) zer = Button(self, text="0") zer.grid(row=5, column=0, sticky=E + W + S + N) dot = Button(self, text=".") dot.grid(row=5, column=1, sticky=E + W + S + N) equ = Button(self, text="=") equ.grid(row=5, column=2, sticky=E + W + S + N) pls = Button(self, text="+") pls.grid(row=5, column=3, sticky=E + W + S + N)
def __init__(self, tester): self.tester = tester self.mainWin = tester.cntlr parent = self.mainWin.parent super(DialogTransformTester, self).__init__(parent) self.parent = parent parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.selectedGroup = None self.transient(self.parent) self.title(_("Transformation Tester")) frame = Frame(self) # load grid trRegLabel = label(frame, 0, 0, _("Registry:")) trReg = self.tester.trRegs[-1] # default is latest self.trRegName = gridCombobox(frame, 1, 0, value=trReg, values=self.tester.trRegs, comboboxselected=self.dialogTrRegComboBoxSelected) trRegToolTipMessage = _("Select Transformation Registry") ToolTip(self.trRegName, text=trRegToolTipMessage, wraplength=360) ToolTip(trRegLabel, text=trRegToolTipMessage, wraplength=360) trNameLabel = label(frame, 0, 1, _("Transform:")) self.trNameName = gridCombobox(frame, 1, 1, value="", values=self.tester.getTrNames(trReg), comboboxselected=self.dialogTrNameComboBoxSelected) trRegToolTipMessage = _("Select or enter transform") ToolTip(self.trRegName, text=trRegToolTipMessage, wraplength=360) ToolTip(trRegLabel, text=trRegToolTipMessage, wraplength=360) sourceLabel = label(frame, 0, 2, _("Source text:")) ToolTip(sourceLabel, text=_("Enter the source text which is to be transformed. "), wraplength=240) self.sourceVar = StringVar() self.sourceVar.set("") sourceEntry = Entry(frame, textvariable=self.sourceVar, width=50) sourceLabel.grid(row=2, column=0, sticky=W) sourceEntry.grid(row=2, column=1, sticky=EW, pady=3, padx=3) resultLabel = label(frame, 1, 3, _("Result:")) ToolTip(sourceLabel, text=_("Transformation result. "), wraplength=240) self.resultVar = StringVar() self.resultVar.set("") resultEntry = Entry(frame, textvariable=self.resultVar, width=50) resultLabel.grid(row=3, column=0, sticky=W) resultEntry.grid(row=3, column=1, sticky=EW, pady=3, padx=3) self.mainWin.showStatus(None) btnPad = 2 if self.mainWin.isMSW else 0 # buttons too narrow on windows okButton = Button(frame, text=_("Transform"), width=8 + btnPad, command=self.dialogOk) cancelButton = Button(frame, text=_("Done"), width=4 + btnPad, command=self.dialogClose) cancelButton.grid(row=4, column=0, sticky=E, columnspan=2, pady=3, padx=3) okButton.grid(row=4, column=0, sticky=E, columnspan=2, pady=3, padx=64) ToolTip(okButton, text=_("Transform the source entered. "), wraplength=240) ToolTip(cancelButton, text=_("Close this dialog. "), wraplength=240) frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(1, weight=3) frame.columnconfigure(2, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) self.geometry("+{0}+{1}".format(dialogX+150,dialogY+100)) #self.bind("<Return>", self.ok) #self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.dialogClose) self.grab_set() self.wait_window(self)
def initUI(self): self.parent.title("Calculator") Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10') self.columnconfigure(0, pad=3) self.columnconfigure(1, pad=3) self.columnconfigure(2, pad=3) self.columnconfigure(3, pad=3) self.columnconfigure(4, pad=3) self.columnconfigure(5, pad=3) self.rowconfigure(0, pad=3) entry1 = Entry(self) #entry.grid(row=0, columnspan=4, sticky=W+E) entry1.insert(0, "0") entry2 = Entry(self) entry2.insert(0, "0") Team_1_Score = 0 Team_2_Score = 0 def Addition_1(): nonlocal Team_1_Score Team_1_Score += 1 entry1.delete(0, 3) entry1.insert(0, Team_1_Score) F = open("Team1.txt", "w") F.write(str(Team_1_Score)) F.close() def Substraction_1(): nonlocal Team_1_Score Team_1_Score -= 1 entry1.delete(0, 3) entry1.insert(0, Team_1_Score) F = open("Team1.txt", "w") F.write(str(Team_1_Score)) F.close() def Addition_2(): nonlocal Team_2_Score Team_2_Score += 1 entry2.delete(0, 3) entry2.insert(0, Team_2_Score) F = open("Team2.txt", "w") F.write(str(Team_2_Score)) F.close() def Substraction_2(): nonlocal Team_2_Score Team_2_Score -= 1 entry2.delete(0, 3) entry2.insert(0, Team_2_Score) F = open("Team2.txt", "w") F.write(str(Team_2_Score)) F.close() def display_1(): return Team_1_Score def display_2(): return Team_2_Score One_Pls = Button(self, text="+", command = Addition_1) One_Pls.grid(row=0, column=0) One_Mns = Button(self, text="-", command = Substraction_1) One_Mns.grid(row=0, column=1) #One_Display = Button(self, text="=", command = display_1) entry1.grid(row=0, column=2) Two_Pls = Button(self, text="+", command = Addition_2) Two_Pls.grid(row=0, column=3) Two_Mns = Button(self, text="-", command = Substraction_2) Two_Mns.grid(row=0, column=4) #Two_Display = Button(self, text="=", command = display_2) entry2.grid(row=0, column=5) self.pack()