def fillInfo(self, curRow: int, path: Path, name: str = None) -> None: rowLbl = zerofrmt(curRow) bg = self.litBg if (curRow % 2) else self.defBg # create container frm = Frame(master=self.scrFrm, bg=bg, relief='sunken', bd=1) frm.columnconfigure(1, weight=1) frm.grid(column=0, row=curRow, sticky='ew') # create spinbox sbox = Spinbox(master=frm, width=3, bg=bg, format=(f'%0{rndto}d' if rndto > 1 else ''), takefocus=False, from_=1, to=self.lblRow, increment=-1, repeatdelay=(10**5), validate='key', validatecommand=self.checkValid) sbox.grid(column=0, row=0) def btnpress(f=frm, s=sbox): self.updateList(f, s, True) def commit(_, f=frm, s=sbox): self.updateList(f, s) def cancel(_, f=frm, s=sbox): self.cancelChange(f, s) sbox.configure(command=btnpress) sbox.delete(0, 'end') if name: sbox.insert(0, rowLbl) else: name = path.name sbox.bind('<Return>', commit) sbox.bind('<Escape>', cancel) # create name label lbl = Label(master=frm, text=name, bg=bg) lbl.grid(column=1, row=0, sticky='w') # save to data dict self.data[rowLbl] = dict(frm=frm, sbox=sbox, lbl=lbl, path=path, name=name)
def show_list_edit(self): self.__menu = Frame(self.__window) self.__menu.configure() self.__menu.pack(fill=BOTH, expand=True) line1 = Frame(self.__menu) line1.pack(side=TOP, fill=X, expand=False, padx=5, pady=15) near_sorted_btn = Button(line1) near_sorted_btn.configure(text="create nearly sorted list", command=self.__create_nearly_sorted_list) near_sorted_btn.pack(side=LEFT) true_random_btn = Button(line1) true_random_btn.configure(text="create random list", command=self.__create_absolutely_random_list) true_random_btn.pack(side=LEFT) few_unique_btn = Button(line1) few_unique_btn.configure(text="create few unique", command=self.__create_few_unique) few_unique_btn.pack(side=LEFT) max_field = Spinbox(line1, from_=1, to=100) max_field.configure(textvariable=self.__max_var, width=9) max_field.pack(side=RIGHT) min_field = Spinbox(line1, from_=1, to=100) min_field.configure(textvariable=self.__min_var, width=9) min_field.pack(side=RIGHT) line2 = Frame(self.__menu) line2.pack(side=TOP, fill=X, expand=False, padx=5, pady=15) list_field = Entry(line2) list_field.configure(textvariable=self.__list_string_var) list_field.pack(fill=X, expand=True, side=LEFT) reverse_btn = Button(line2) reverse_btn.configure(text="reverse", command=self.__reverse) reverse_btn.pack(side=RIGHT) line3 = Frame(self.__menu) line3.pack(fill=X, expand=False, padx=5, pady=15) submit_btn = Button(line3) submit_btn.configure(text="submit", command=self.submit) submit_btn.pack(side=TOP) information = Text(self.__menu) information.insert( END, "You can enter a list of numbers that should be sorted into the input field. \ Use a ';' to separate them. \ You can also generate nearly sorted or absolutely random lists with the buttons above,\ The fields beside them let you enter the minimal and maximal value of the generated list.\ By clicking on 'Submit', the list in the inputfield becomes the list to sort and the animation starts" ) information.configure(state=DISABLED, relief=FLAT, wrap=WORD) information.pack(side=BOTTOM, fill=X, padx=5, pady=10)
def updateList(self, frm: Frame, sbox: Spinbox, btn: bool = False) -> None: # get data start = frm.grid_info()['row'] oldInfo = self.data.pop(zerofrmt(start)) # get spinbox value moveToLbl = str(sbox.get()) if moveToLbl == zerofrmt(start): return elif not moveToLbl: if start < self.lblRow: start = (self.lblRow + 1) moveToLbl = zerofrmt(self.lastRow) self.focus_set() else: return elif btn and int(moveToLbl) == self.lblRow: sbox.delete(0, 'end') start = (self.lblRow + 1) moveToLbl = zerofrmt(self.lastRow) self.after(0, self.focus_set) elif btn and abs(start - int(moveToLbl)) > 1: self.moveInterim(start, zerofrmt(self.lblRow + 1), True) start = 0 moveToLbl = zerofrmt(self.maxRow) sbox.delete(0, 'end') sbox.insert(0, moveToLbl) elif not btn: if len(moveToLbl) != rndto: moveToLbl = zerofrmt(moveToLbl) sbox.delete(0, 'end') sbox.insert(0, moveToLbl) if start == self.lastRow: self.moveInterim(start, zerofrmt(self.lblRow + 1), True) sbox.selection_range(0, 'end') if moveToLbl == zerofrmt(start): return if moveToLbl in self.data: self.moveInterim(start, moveToLbl, False) moveToRow = int(moveToLbl) bg = self.litBg if (moveToRow % 2) else self.defBg frm.grid(row=moveToRow) frm.configure(bg=bg) sbox.configure(bg=bg) oldInfo['lbl'].configure(bg=bg) self.data[moveToLbl] = oldInfo
class ConfigTimeFrame(RootFrame): def __init__(self, *args, **kw): super(ConfigTimeFrame, self).__init__(*args, **kw) #image de fond self.canevas.create_image(self.canevas_width / 2, self.canevas_height / 2, anchor=CENTER, image=self.photo) #label suivant self.labelSuivant = Label(self, text="Suivant", relief=RAISED) self.labelSuivant.configure(font=self.font, fg=self.colorOrange, bg="white") #time spinbox self.spinboxTime = Spinbox(self, from_=10, to=120, increment=10) self.spinboxTime.focus() self.spinboxTime.configure(font=self.font, fg=self.colorBlue, bg="white") #config time self.labelConfigTime = Label( self, text="Entrer la durée de l'analyse en minute") self.labelConfigTime.configure(font=self.font, fg=self.colorBlue, bg="white") #display self.labelConfigTime.pack(side="top") self.spinboxTime.pack(side="top") self.labelSuivant.pack(side="top") def getTimeConfigured(self): return int(self.spinboxTime.get()) #this method is call by provider action def incrementTimeConfigured(self, event): self.spinboxTime.invoke('buttonup') #this method is call by provider action def decrementTimeConfigured(self, event): self.spinboxTime.invoke('buttondown')
class Settings(Frame): def __init__(self, master, widget, items, modifying=False): super().__init__(master, bg="#435661") self.widget = widget self.modifying = modifying self.record = {} self.index = 0 self.spin_relx = None self.spin_rely = None self.spin_relw = None self.spin_relh = None self.label_arguments = None self.entry_arguments = None self.listbox = None self.entry_name = None self.set_layout() self.set_bindings() self.set_listbox(items) self.set_spinboxes() def set_layout(self): # self-explanatory Label(self, background='#435661', text='relx:', foreground='#defffc') \ .place(relx=0.145, rely=0.0125, relwidth=0.1625, relheight=0.025, anchor='nw') Label(self, background='#435661', foreground='#defffc', text='rely:') \ .place(relx=0.6845, rely=0.0135, relwidth=0.155, relheight=0.0225, anchor='nw') Label(self, background='#435661', text='relwidth:', foreground='#defffc') \ .place(relx=0.044, rely=0.089, relwidth=0.37, relheight=0.02125, anchor='nw') Label(self, background='#435661', foreground='#defffc', text='relheight:') \ .place(relx=0.667, rely=0.0875, relwidth=0.195, relheight=0.02375, anchor='nw') self.spin_relx = Spinbox(self, readonlybackground='#defffc', highlightthickness=0, foreground='#435661', from_=0, command=self.mod_relx, to_=1, increment=0.001, justify='center') self.spin_relx.place(relx=0.085, rely=0.0425, relwidth=0.295, relheight=0.03375, anchor='nw') self.spin_rely = Spinbox(self, readonlybackground='#defffc', foreground='#435661', justify='center', highlightthickness=0, command=self.mod_rely, from_=0, to_=1, increment=0.001) self.spin_rely.place(relx=0.6135, rely=0.0425, relwidth=0.3005, relheight=0.03375, anchor='nw') self.spin_relw = Spinbox(self, readonlybackground='#defffc', foreground='#435661', justify='center', highlightthickness=0, command=self.mod_relwidth, from_=0, to_=1, increment=0.001) self.spin_relw.place(relx=0.084, rely=0.1175, relwidth=0.295, relheight=0.035, anchor='nw') self.spin_relh = Spinbox(self, readonlybackground='#defffc', foreground='#435661', justify='center', highlightthickness=0, command=self.mod_relheight, from_=0, to_=1, increment=0.001) self.spin_relh.place(relx=0.6115, rely=0.1177, relwidth=0.304, relheight=0.035, anchor='nw') self.label_arguments = Label(self, background='#557282', foreground='#defffc') self.label_arguments.place(relx=0.086, rely=0.1832, relwidth=0.8305, relheight=0.06125, anchor='nw') self.entry_arguments = Entry(self, background='#defffc', foreground='#435661', justify='center') self.entry_arguments.place(relx=0.22, rely=0.2625, relwidth=0.545, relheight=0.04375, anchor='nw') self.listbox = Listbox(self, background='#557282', foreground='#defffc', borderwidth=0) self.listbox.place(relx=0.085, rely=0.3275, relwidth=0.83, relheight=0.4062, anchor='nw') myButton(self, command=lambda *a: self.set_value(), text='OK') \ .place(relx=0.8245, rely=0.2672, relwidth=0.13, relheight=0.0355, anchor='nw') Label(self, background='#435661', foreground='#defffc', text='Name:', anchor='w') \ .place(relx=0.083, rely=0.766, relwidth=0.1205, relheight=0.035, anchor='nw') self.entry_name = Entry(self, background='#defffc', foreground='#435661', justify='center') self.entry_name.place(relx=0.245, rely=0.7662, relwidth=0.5225, relheight=0.035, anchor='nw') self.entry_name.bind("<Return>", lambda *a: self.confirm()) myButton(self, command=lambda *a: self.confirm(), text='CONFIRM') \ .place(relx=0.201, rely=0.8575, relwidth=0.6155, relheight=0.0825, anchor='nw') def set_bindings(self): # self-explanatory self.entry_arguments.bind("<Return>", lambda *a: self.set_value()) self.listbox.bind("<ButtonRelease-1>", lambda *a: self.listbox_clicked()) self.master.root.bind("<Left>", lambda event: self.pressed_left_right(-1)) self.master.root.bind("<Right>", lambda event: self.pressed_left_right(1)) self.master.root.bind("<Up>", lambda event: self.pressed_up_down(-1)) self.master.root.bind("<Down>", lambda event: self.pressed_up_down(1)) def set_spinboxes(self): # self-explanatory self.spin_relx.delete(0, "end") self.spin_rely.delete(0, "end") self.spin_relw.delete(0, "end") self.spin_relh.delete(0, "end") self.spin_relx.insert("end", self.widget.place_info()["relx"]) self.spin_rely.insert("end", self.widget.place_info()["rely"]) self.spin_relw.insert("end", self.widget.place_info()["relwidth"]) self.spin_relh.insert("end", self.widget.place_info()["relheight"]) self.spin_relx.configure(state="readonly") self.spin_rely.configure(state="readonly") self.spin_relw.configure(state="readonly") self.spin_relh.configure(state="readonly") def mod_relx(self): # Changes widget's relx parameter accordingly value = float(self.spin_relx.get()) self.widget.place_configure(relx=value) def mod_rely(self): # Changes widget's rely parameter accordingly value = float(self.spin_rely.get()) self.widget.place_configure(rely=value) def mod_relwidth(self): # Changes widget's relwidth parameter accordingly value = float(self.spin_relw.get()) self.widget.place_configure(relwidth=value) def mod_relheight(self): # Changes widget's relheight parameter accordingly value = float(self.spin_relh.get()) self.widget.place_configure(relheight=value) def pressed_left_right(self, factor): value = float(self.spin_relx.get()) self.spin_relx.configure(state="normal") self.spin_relx.delete(0, "end") self.spin_relx.insert("end", value + factor * 0.001) self.spin_relx.configure(state="readonly") self.widget.place_configure(relx=value + factor * 0.001) def pressed_up_down(self, factor): value = float(self.spin_rely.get()) self.spin_rely.configure(state="normal") self.spin_rely.delete(0, "end") self.spin_rely.insert("end", value + factor * 0.001) self.spin_rely.configure(state="readonly") self.widget.place_configure(rely=value + factor * 0.001) def set_listbox(self, items): for item in items: self.listbox.insert("end", item) self.record[item] = self.widget.cget(item) def listbox_clicked(self): # Changes entry_arguments's text and label_arguments's text, sets focus on entry_name self.index = self.listbox.curselection()[0] parameter = list(self.record.keys())[self.index] value = self.record[parameter] self.entry_arguments.delete(0, "end") self.entry_arguments.insert("end", value) self.label_arguments.configure(text=f"{parameter} = {value}") self.entry_arguments.focus_set() def set_value(self): # Sets entry_arguments's value as widget's argument, it needs to be evaluated first to avoid errors parameter = list(self.record.keys())[self.index] value = self.entry_arguments.get() try: evaluated_value = eval(value) self.record[parameter] = evaluated_value except: evaluated_value = value self.record[parameter] = f"{evaluated_value}" self.widget.configure({parameter: evaluated_value}) self.label_arguments.configure(text=f"{parameter} = {value}") def confirm(self): # Checks if entry_name isn't empty or already used and then sends it to the master.Writer # After that it quits with .destroy() name = self.entry_name.get().replace(" ", "") if not self.modifying: if name and name not in self.master.record_of_names: self.master.record_of_names[name] = self.widget widget_cls = self.widget.winfo_class() self.master.writer.define_widget(name, widget_cls, self.widget.place_info()) self.master.writer.begin_configure(name) for key, value in self.record.items(): if value: self.master.writer.write_configure( name, key, f"'{value}'") self.master.writer.end_configure(name) self.master.root.unbind("<Down>") self.master.root.unbind("<Up>") self.master.root.unbind("<Left>") self.master.root.unbind("<Right>") self.destroy() else: widget_cls = self.widget.winfo_class() try: self.master.writer.define_widget(name, widget_cls, self.widget.place_info(), True) self.master.writer.begin_configure(name) except KeyError: self.entry_name.delete(0, "end") self.entry_name.insert("end", "NOME SBAGLIATO") return None for key, value in self.record.items(): if value: self.master.writer.write_configure(name, key, f"'{value}'") self.master.writer.end_configure(name) self.master.root.unbind("<Down>") self.master.root.unbind("<Up>") self.master.root.unbind("<Left>") self.master.root.unbind("<Right>") self.destroy()
class Settings_for_frame(Frame): def __init__(self, master, board, tag, board_dims): super().__init__(master, bg="#435661") self.board = board self.board_width, self.board_height = board_dims self.tag = tag self.background = "white" self.record = {} self.index = 0 self.spin_relx = None self.spin_rely = None self.spin_relw = None self.spin_relh = None self.label_arguments = None self.entry_arguments = None self.listbox = None self.entry_name = None self.set_layout() self.set_bindings() self.set_listbox() self.set_spinboxes() def set_layout(self): # self-explanatory Label(self, background='#435661', text='relx:', foreground='#defffc') \ .place(relx=0.145, rely=0.0125, relwidth=0.1625, relheight=0.025, anchor='nw') Label(self, background='#435661', foreground='#defffc', text='rely:') \ .place(relx=0.6845, rely=0.0135, relwidth=0.155, relheight=0.0225, anchor='nw') Label(self, background='#435661', text='relwidth:', foreground='#defffc') \ .place(relx=0.044, rely=0.089, relwidth=0.37, relheight=0.02125, anchor='nw') Label(self, background='#435661', foreground='#defffc', text='relheight:') \ .place(relx=0.667, rely=0.0875, relwidth=0.195, relheight=0.02375, anchor='nw') self.spin_relx = Spinbox(self, readonlybackground='#defffc', highlightthickness=0, foreground='#435661', from_=0, command=self.mod, to_=1, increment=0.001, justify='center') self.spin_relx.place(relx=0.085, rely=0.0425, relwidth=0.295, relheight=0.03375, anchor='nw') self.spin_rely = Spinbox(self, readonlybackground='#defffc', foreground='#435661', justify='center', highlightthickness=0, command=self.mod, from_=0, to_=1, increment=0.001) self.spin_rely.place(relx=0.6135, rely=0.0425, relwidth=0.3005, relheight=0.03375, anchor='nw') self.spin_relw = Spinbox(self, readonlybackground='#defffc', foreground='#435661', justify='center', highlightthickness=0, command=self.mod, from_=0, to_=1, increment=0.001) self.spin_relw.place(relx=0.084, rely=0.1175, relwidth=0.295, relheight=0.035, anchor='nw') self.spin_relh = Spinbox(self, readonlybackground='#defffc', foreground='#435661', justify='center', highlightthickness=0, command=self.mod, from_=0, to_=1, increment=0.001) self.spin_relh.place(relx=0.6115, rely=0.1177, relwidth=0.304, relheight=0.035, anchor='nw') self.label_arguments = Label(self, background='#557282', foreground='#defffc') self.label_arguments.place(relx=0.086, rely=0.1832, relwidth=0.8305, relheight=0.06125, anchor='nw') self.entry_arguments = Entry(self, background='#defffc', foreground='#435661', justify='center') self.entry_arguments.place(relx=0.22, rely=0.2625, relwidth=0.545, relheight=0.04375, anchor='nw') self.listbox = Listbox(self, background='#557282', foreground='#defffc', borderwidth=0) self.listbox.place(relx=0.085, rely=0.3275, relwidth=0.83, relheight=0.4062, anchor='nw') myButton(self, command=lambda *a: self.set_value(), text='OK') \ .place(relx=0.8245, rely=0.2672, relwidth=0.13, relheight=0.0355, anchor='nw') Label(self, background='#435661', foreground='#defffc', text='Name:', anchor='w') \ .place(relx=0.083, rely=0.766, relwidth=0.1205, relheight=0.035, anchor='nw') self.entry_name = Entry(self, background='#defffc', foreground='#435661', justify='center') self.entry_name.place(relx=0.245, rely=0.7662, relwidth=0.5225, relheight=0.035, anchor='nw') myButton(self, command=lambda *a: self.confirm(), text='CONFIRM') \ .place(relx=0.201, rely=0.8575, relwidth=0.6155, relheight=0.0825, anchor='nw') def set_bindings(self): # self-explanatory self.entry_arguments.bind("<Return>", lambda *a: self.set_value()) self.listbox.bind("<ButtonRelease-1>", lambda *a: self.listbox_clicked()) def set_spinboxes(self): # self-explanatory self.spin_relx.delete(0, "end") self.spin_rely.delete(0, "end") self.spin_relw.delete(0, "end") self.spin_relh.delete(0, "end") self.spin_relx.insert("end", self.master.fake_frame_place_info["relx"]) self.spin_rely.insert("end", self.master.fake_frame_place_info["rely"]) self.spin_relw.insert("end", self.master.fake_frame_place_info["relwidth"]) self.spin_relh.insert("end", self.master.fake_frame_place_info["relheight"]) self.spin_relx.configure(state="readonly") self.spin_rely.configure(state="readonly") self.spin_relw.configure(state="readonly") self.spin_relh.configure(state="readonly") def mod(self): relx = float(self.spin_relx.get()) rely = float(self.spin_rely.get()) relw = float(self.spin_relw.get()) relh = float(self.spin_relh.get()) x, y = int(relx * self.board_width), int(rely * self.board_height) width, height = int(relw * self.board_width), int(relh * self.board_height) self.board.delete(self.tag) self.board.create_rectangle(x, y, x + width, y + height, width=0, fill=self.background, tag=self.tag) def set_listbox(self): self.listbox.insert("end", "background") self.record["background"] = self.master.fake_frame_background def listbox_clicked(self): # Changes entry_arguments's text and label_arguments's text, sets focus on entry_name self.index = self.listbox.curselection()[0] parameter = list(self.record.keys())[self.index] value = self.record[parameter] self.entry_arguments.delete(0, "end") self.entry_arguments.insert("end", value) self.label_arguments.configure(text=f"{parameter} = {value}") self.entry_arguments.focus_set() def set_value(self): parameter = list(self.record.keys())[self.index] value = self.entry_arguments.get() try: evaluated_value = eval(value) self.record[parameter] = evaluated_value except: evaluated_value = value self.record[parameter] = f"{evaluated_value}" self.background = evaluated_value self.mod() self.label_arguments.configure(text=f"{parameter} = {value}") def fake_place_info(self): relx = float(self.spin_relx.get()) rely = float(self.spin_rely.get()) relw = float(self.spin_relw.get()) relh = float(self.spin_relh.get()) return { "relx": relx, "rely": rely, "relwidth": relw, "relheight": relh, "anchor": "nw" } def confirm(self): name = self.entry_name.get().replace(" ", "") if name and name not in self.master.record_of_names: self.master.record_of_names[name] = Frame(self.board) widget_cls = "Frame" self.master.writer.define_widget(name, widget_cls, self.fake_place_info()) self.master.writer.begin_configure(name) for key, value in self.record.items(): if value: self.master.writer.write_configure(name, key, f"'{value}'") self.master.writer.end_configure(name) self.destroy()
class MyApp(Frame): def __init__(self): self.root = Tk() Frame.__init__(self, self.root) # high level GUI configuration self.root.geometry('800x600') self.root.resizable(width=1, height=1) self.root.option_add('*tearOff', False) # keeps file menus from looking weird # members related to the background thread and operator instance self.long_thread = None self.background_operator = None # tk variables we can access later self.label_string = StringVar() self.build_dir_1_var = StringVar() self.build_dir_2_var = StringVar() self.run_period_option = StringVar() self.run_period_option.set(RunOptions.DONT_FORCE) self.reporting_frequency = StringVar() self.reporting_frequency.set(ReportingFrequency.HOURLY) # widgets that we might want to access later self.build_dir_1_button = None self.build_dir_2_button = None self.run_button = None self.stop_button = None self.build_dir_1_label = None self.build_dir_1_var.set('/eplus/repos/1eplus/builds') # "<Select build dir 1>") self.build_dir_2_label = None self.build_dir_2_var.set('/eplus/repos/1eplus/builds') # "<Select build dir 2>") self.progress = None self.log_message_listbox = None self.results_tree = None self.num_threads_spinner = None self.full_idf_listbox = None self.move_idf_to_active_button = None self.active_idf_listbox = None self.remove_idf_from_active_button = None self.idf_select_all_button = None self.idf_deselect_all_button = None self.idf_select_n_random_button = None self.run_period_option_menu = None self.reporting_frequency_option_menu = None # some data holders self.tree_folders = dict() self.valid_idfs_in_listing = False self.run_button_color = '#008000' # initialize the GUI self.init_window() # wire up the background thread pub.subscribe(self.status_handler, PubSubMessageTypes.STATUS) pub.subscribe(self.finished_handler, PubSubMessageTypes.FINISHED) pub.subscribe(self.cancelled_handler, PubSubMessageTypes.CANCELLED) def init_window(self): # changing the title of our master widget self.root.title("EnergyPlus Regression Tool 2") self.root.protocol("WM_DELETE_WINDOW", self.client_exit) # create the menu menu = Menu(self.root) self.root.config(menu=menu) file_menu = Menu(menu) file_menu.add_command(label="Exit", command=self.client_exit) menu.add_cascade(label="File", menu=file_menu) # main notebook holding everything main_notebook = ttk.Notebook(self.root) # run configuration pane_run = Frame(main_notebook) group_build_dir_1 = LabelFrame(pane_run, text="Build Directory 1") group_build_dir_1.pack(fill=X, padx=5) self.build_dir_1_button = Button(group_build_dir_1, text="Change...", command=self.client_build_dir_1) self.build_dir_1_button.grid(row=1, column=1, sticky=W) self.build_dir_1_label = Label(group_build_dir_1, textvariable=self.build_dir_1_var) self.build_dir_1_label.grid(row=1, column=2, sticky=E) group_build_dir_2 = LabelFrame(pane_run, text="Build Directory 2") group_build_dir_2.pack(fill=X, padx=5) self.build_dir_2_button = Button(group_build_dir_2, text="Change...", command=self.client_build_dir_2) self.build_dir_2_button.grid(row=1, column=1, sticky=W) self.build_dir_2_label = Label(group_build_dir_2, textvariable=self.build_dir_2_var) self.build_dir_2_label.grid(row=1, column=2, sticky=E) group_run_options = LabelFrame(pane_run, text="Run Options") group_run_options.pack(fill=X, padx=5) Label(group_run_options, text="Number of threads for suite: ").grid(row=1, column=1, sticky=E) self.num_threads_spinner = Spinbox(group_run_options, from_=1, to_=48) # validate later self.num_threads_spinner.grid(row=1, column=2, sticky=W) Label(group_run_options, text="Test suite run configuration: ").grid(row=2, column=1, sticky=E) self.run_period_option_menu = OptionMenu(group_run_options, self.run_period_option, *RunOptions.get_all()) self.run_period_option_menu.grid(row=2, column=2, sticky=W) Label(group_run_options, text="Minimum reporting frequency: ").grid(row=3, column=1, sticky=E) self.reporting_frequency_option_menu = OptionMenu( group_run_options, self.reporting_frequency, *ReportingFrequency.get_all() ) self.reporting_frequency_option_menu.grid(row=3, column=2, sticky=W) main_notebook.add(pane_run, text='Configuration') # now let's set up a list of checkboxes for selecting IDFs to run pane_idfs = Frame(main_notebook) group_idf_tools = LabelFrame(pane_idfs, text="IDF Selection Tools") group_idf_tools.pack(fill=X, padx=5) self.idf_select_all_button = Button( group_idf_tools, text="Refresh", command=self.client_idf_refresh ) self.idf_select_all_button.pack(side=LEFT, expand=1) self.idf_select_all_button = Button( group_idf_tools, text="Select All", command=self.idf_select_all ) self.idf_select_all_button.pack(side=LEFT, expand=1) self.idf_deselect_all_button = Button( group_idf_tools, text="Deselect All", command=self.idf_deselect_all ) self.idf_deselect_all_button.pack(side=LEFT, expand=1) self.idf_select_n_random_button = Button( group_idf_tools, text="Select N Random", command=self.idf_select_random ) self.idf_select_n_random_button.pack(side=LEFT, expand=1) group_full_idf_list = LabelFrame(pane_idfs, text="Full IDF List") group_full_idf_list.pack(fill=X, padx=5) scrollbar = Scrollbar(group_full_idf_list) self.full_idf_listbox = Listbox(group_full_idf_list, yscrollcommand=scrollbar.set) self.full_idf_listbox.bind('<Double-1>', self.idf_move_to_active) self.full_idf_listbox.pack(fill=BOTH, side=LEFT, expand=True) scrollbar.pack(fill=Y, side=LEFT) scrollbar.config(command=self.full_idf_listbox.yview) self.move_idf_to_active_button = Button( pane_idfs, text="↓ Add to Active List ↓", command=self.idf_move_to_active ) self.move_idf_to_active_button.pack(side=TOP, fill=X, expand=True) self.remove_idf_from_active_button = Button( pane_idfs, text="↑ Remove from Active List ↑", command=self.idf_remove_from_active ) self.remove_idf_from_active_button.pack(side=TOP, fill=X, expand=True) group_active_idf_list = LabelFrame(pane_idfs, text="Active IDF List") group_active_idf_list.pack(fill=X, padx=5) scrollbar = Scrollbar(group_active_idf_list) self.active_idf_listbox = Listbox(group_active_idf_list, yscrollcommand=scrollbar.set) self.active_idf_listbox.bind('<Double-1>', self.idf_remove_from_active) self.active_idf_listbox.pack(fill=BOTH, side=LEFT, expand=True) scrollbar.pack(fill=Y, side=LEFT) scrollbar.config(command=self.active_idf_listbox.yview) self.build_idf_listing(initialize=True) main_notebook.add(pane_idfs, text="IDF Selection") # set up a scrolled listbox for the log messages frame_log_messages = Frame(main_notebook) group_log_messages = LabelFrame(frame_log_messages, text="Log Message Tools") group_log_messages.pack(fill=X, padx=5) Button(group_log_messages, text="Clear Log Messages", command=self.clear_log).pack(side=LEFT, expand=1) Button(group_log_messages, text="Copy Log Messages", command=self.copy_log).pack(side=LEFT, expand=1) scrollbar = Scrollbar(frame_log_messages) self.log_message_listbox = Listbox(frame_log_messages, yscrollcommand=scrollbar.set) self.add_to_log("Program started!") self.log_message_listbox.pack(fill=BOTH, side=LEFT, expand=True) scrollbar.pack(fill=Y, side=LEFT) scrollbar.config(command=self.log_message_listbox.yview) main_notebook.add(frame_log_messages, text="Log Messages") # set up a tree-view for the results frame_results = Frame(main_notebook) scrollbar = Scrollbar(frame_results) self.results_tree = ttk.Treeview(frame_results, columns=("Base File", "Mod File", "Diff File")) self.results_tree.heading("#0", text="Results") self.results_tree.column('#0', minwidth=200, width=200) self.results_tree.heading("Base File", text="Base File") self.results_tree.column("Base File", minwidth=100, width=100) self.results_tree.heading("Mod File", text="Mod File") self.results_tree.column("Mod File", minwidth=100, width=100) self.results_tree.heading("Diff File", text="Diff File") self.results_tree.column("Diff File", minwidth=100, width=100) self.build_results_tree() self.results_tree.pack(fill=BOTH, side=LEFT, expand=True) scrollbar.pack(fill=Y, side=LEFT) scrollbar.config(command=self.results_tree.yview) main_notebook.add(frame_results, text="Run Control and Results") # pack the main notebook on the window main_notebook.pack(fill=BOTH, expand=1) # status bar at the bottom frame_status = Frame(self.root) self.run_button = Button(frame_status, text="Run", bg=self.run_button_color, command=self.client_run) self.run_button.pack(side=LEFT, expand=0) self.stop_button = Button(frame_status, text="Stop", command=self.client_stop, state='disabled') self.stop_button.pack(side=LEFT, expand=0) self.progress = ttk.Progressbar(frame_status) self.progress.pack(side=LEFT, expand=0) label = Label(frame_status, textvariable=self.label_string) self.label_string.set("Initialized") label.pack(side=LEFT, anchor=W) frame_status.pack(fill=X) def run(self): self.root.mainloop() def build_idf_listing(self, initialize=False, desired_selected_idfs=None): # clear any existing ones self.active_idf_listbox.delete(0, END) self.full_idf_listbox.delete(0, END) # now rebuild them self.valid_idfs_in_listing = False path_1 = Path(self.build_dir_1_var.get()) path_2 = Path(self.build_dir_2_var.get()) if path_1.exists() and path_2.exists(): idf_dir_1 = dummy_get_idf_dir(path_1) idfs_dir_1 = dummy_get_idfs_in_dir(idf_dir_1) idf_dir_2 = dummy_get_idf_dir(path_2) idfs_dir_2 = dummy_get_idfs_in_dir(idf_dir_2) common_idfs = idfs_dir_1.intersection(idfs_dir_2) for idf in sorted(common_idfs): self.full_idf_listbox.insert(END, str(idf)) self.valid_idfs_in_listing = True elif initialize: self.full_idf_listbox.insert(END, "This will be the master list") self.full_idf_listbox.insert(END, "Select build folders to fill listing") elif path_1.exists(): self.full_idf_listbox.insert(END, "Cannot update master list master list") self.full_idf_listbox.insert(END, "Build folder path #2 is invalid") self.full_idf_listbox.insert(END, "Select build folders to fill listing") elif path_2.exists(): self.full_idf_listbox.insert(END, "Cannot update master list master list") self.full_idf_listbox.insert(END, "Build folder path #1 is invalid") self.full_idf_listbox.insert(END, "Select build folders to fill listing") else: self.full_idf_listbox.insert(END, "Cannot update master list master list") self.full_idf_listbox.insert(END, "Both build folders are invalid") self.full_idf_listbox.insert(END, "Select build folders to fill listing") if desired_selected_idfs is None: ... # add things to the listbox def build_results_tree(self, results=None): self.results_tree.delete(*self.results_tree.get_children()) for root in ResultsTreeRoots.get_all(): self.tree_folders[root] = self.results_tree.insert( parent="", index='end', text=root, values=("", "", "") ) if results: self.results_tree.insert( parent=self.tree_folders[root], index="end", text="Pretend", values=("These", "Are", "Real") ) else: self.results_tree.insert( parent=self.tree_folders[root], index="end", text="Run test for results", values=("", "", "") ) def add_to_log(self, message): self.log_message_listbox.insert(END, f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]: {message}") def clear_log(self): self.log_message_listbox.delete(0, END) def copy_log(self): messages = self.log_message_listbox.get(0, END) message_string = '\n'.join(messages) self.root.clipboard_append(message_string) def client_idf_refresh(self): self.build_idf_listing() def idf_move_to_active(self, _): if not self.valid_idfs_in_listing: simpledialog.messagebox.showerror("IDF Selection Error", "Invalid build folders or IDF list") return current_selection = self.full_idf_listbox.curselection() if not current_selection: simpledialog.messagebox.showerror("IDF Selection Error", "No IDF Selected") return currently_selected_idf = self.full_idf_listbox.get(current_selection) try: self.active_idf_listbox.get(0, "end").index(currently_selected_idf) simpledialog.messagebox.showwarning("IDF Selection Warning", "IDF already exists in active list") return except ValueError: pass # the value error indicates it was _not_ found, so this is success self.active_idf_listbox.insert(END, currently_selected_idf) self.idf_refresh_count_status(currently_selected_idf, True) def idf_remove_from_active(self, event=None): if not self.valid_idfs_in_listing: simpledialog.messagebox.showerror("IDF Selection Error", "Invalid build folders or IDF list") return current_selection = self.active_idf_listbox.curselection() if not current_selection: if event: return simpledialog.messagebox.showerror("IDF Selection Error", "No IDF Selected") return self.active_idf_listbox.delete(current_selection) self.idf_refresh_count_status(current_selection, False) def idf_select_all(self): self.idf_deselect_all() if not self.valid_idfs_in_listing: simpledialog.messagebox.showerror("IDF Selection Error", "Invalid build folders or IDF list") return all_idfs = self.full_idf_listbox.get(0, END) for idf in all_idfs: self.active_idf_listbox.insert(END, idf) self.idf_refresh_count_status() def idf_deselect_all(self): if not self.valid_idfs_in_listing: simpledialog.messagebox.showerror("IDF Selection Error", "Invalid build folders or IDF list") return self.active_idf_listbox.delete(0, END) self.idf_refresh_count_status() def idf_select_random(self): if not self.valid_idfs_in_listing: simpledialog.messagebox.showerror("IDF Selection Error", "Invalid build folders or IDF list") return potential_number_to_select = simpledialog.askinteger("Input Amount", "How many would you like to select?") if not potential_number_to_select: return self.idf_deselect_all() number_to_select = int(potential_number_to_select) number_of_idf_files = self.full_idf_listbox.size() if number_of_idf_files <= number_to_select: # just take all of them self.idf_select_all() else: # down select randomly indices_to_take = random.sample(range(number_of_idf_files), number_to_select) idfs_to_take = list() for i in indices_to_take: idf_to_get = self.full_idf_listbox.get(i) idfs_to_take.append(idf_to_get) for idf_to_get in sorted(idfs_to_take): self.active_idf_listbox.insert(END, idf_to_get) self.idf_refresh_count_status() def idf_refresh_count_status(self, test_case=None, checked=False): if not self.valid_idfs_in_listing: return num_total = self.full_idf_listbox.size() num_active = self.active_idf_listbox.size() if test_case: chk_string = "Checked" if checked else "Unchecked" if checked: self.label_string.set(f"{chk_string} {test_case} ({num_active}/{num_total} selected)") else: self.label_string.set(f"{num_active}/{num_total} selected") def set_gui_status_for_run(self, is_running: bool): if is_running: run_button_state = 'disabled' stop_button_state = 'normal' else: run_button_state = 'normal' stop_button_state = 'disabled' self.build_dir_1_button.configure(state=run_button_state) self.build_dir_2_button.configure(state=run_button_state) self.run_button.configure(state=run_button_state) self.idf_select_all_button.configure(state=run_button_state) self.idf_deselect_all_button.configure(state=run_button_state) self.idf_select_n_random_button.configure(state=run_button_state) self.move_idf_to_active_button.configure(state=run_button_state) self.remove_idf_from_active_button.configure(state=run_button_state) self.run_period_option_menu.configure(state=run_button_state) self.reporting_frequency_option_menu.configure(state=run_button_state) self.num_threads_spinner.configure(state=run_button_state) self.stop_button.configure(state=stop_button_state) def client_build_dir_1(self): selected_dir = filedialog.askdirectory() if selected_dir: self.build_dir_1_var.set(selected_dir) self.build_idf_listing() def client_build_dir_2(self): selected_dir = filedialog.askdirectory() if selected_dir: self.build_dir_2_var.set(selected_dir) self.build_idf_listing() def client_run(self): if self.long_thread: messagebox.showerror("Cannot run another thread, wait for the current to finish -- how'd you get here?!?") return potential_num_threads = self.num_threads_spinner.get() try: num_threads = int(potential_num_threads) except ValueError: messagebox.showerror("Invalid Configuration", "Number of threads must be an integer") return idfs_to_run = list() for i in self.active_idf_listbox.get(0, END): idfs_to_run.append(i) self.background_operator = BackgroundOperation(num_threads, idfs_to_run) self.background_operator.get_ready_to_go( MyApp.status_listener, MyApp.finished_listener, MyApp.cancelled_listener ) self.set_gui_status_for_run(True) self.long_thread = Thread(target=self.background_operator.run) self.add_to_log("Starting a new set of tests") self.long_thread.start() def client_stop(self): self.add_to_log("Attempting to cancel") self.label_string.set("Attempting to cancel...") self.background_operator.please_stop() def client_exit(self): if self.long_thread: messagebox.showerror("Uh oh!", "Cannot exit program while operations are running; abort them then exit") return exit() def client_done(self): self.set_gui_status_for_run(False) self.long_thread = None # -- Callbacks from the background thread coming via PyPubSub @staticmethod def status_listener(status, object_completed, percent_complete): """Operates on background thread, just issues a pubsub message""" pub.sendMessage( PubSubMessageTypes.STATUS, status=status, object_completed=object_completed, percent_complete=percent_complete) def status_handler(self, status, object_completed, percent_complete): self.add_to_log(object_completed) self.progress['value'] = percent_complete self.label_string.set(f"Hey, status update: {str(status)}") @staticmethod def finished_listener(results_dict): """Operates on background thread, just issues a pubsub message""" pub.sendMessage(PubSubMessageTypes.FINISHED, results=results_dict) def finished_handler(self, results): self.add_to_log("All done, finished") self.label_string.set("Hey, all done!") self.build_results_tree(results) self.client_done() @staticmethod def cancelled_listener(): """Operates on background thread, just issues a pubsub message""" pub.sendMessage(PubSubMessageTypes.CANCELLED) def cancelled_handler(self): self.add_to_log("Cancelled!") self.label_string.set("Properly cancelled!") self.client_done()
class SettingsFrame(Frame): ''' Frame inheritance class for application settings and controls. ''' def __init__(self, app, *args, **kwargs): ''' Constructor. ''' self.__app = app # Reference to main application class self.__master = self.__app.get_master() # Reference to root class (Tk) Frame.__init__(self, self.__master, *args, **kwargs) self._show_advanced = False self._settings = {} self._ports = () self._port = StringVar() self._port_desc = StringVar() self._baudrate = IntVar() self._databits = IntVar() self._stopbits = DoubleVar() self._parity = StringVar() self._rtscts = IntVar() self._xonxoff = IntVar() self._protocol = IntVar() self._raw = IntVar() self._autoscroll = IntVar() self._maxlines = IntVar() self._webmap = IntVar() self._mapzoom = IntVar() self._units = StringVar() self._format = StringVar() self._datalog = IntVar() self._record_track = IntVar() self._noports = True self._validsettings = True self._logpath = None self._trackpath = None self._img_conn = ImageTk.PhotoImage(Image.open(ICON_CONN)) self._img_disconn = ImageTk.PhotoImage(Image.open(ICON_DISCONN)) self._img_ubxconfig = ImageTk.PhotoImage(Image.open(ICON_UBXCONFIG)) self._img_dataread = ImageTk.PhotoImage(Image.open(ICON_LOGREAD)) self._body() self._do_layout() self._get_ports() self._reset() def _body(self): ''' Set up frame and widgets. ''' for i in range(4): self.grid_columnconfigure(i, weight=1) self.grid_rowconfigure(0, weight=1) self.option_add("*Font", self.__app.font_sm) # Serial port settings self._frm_basic = Frame(self) self._lbl_port = Label(self._frm_basic, text="Port") self._lbx_port = Listbox(self._frm_basic, border=2, relief="sunken", bg=ENTCOL, width=28, height=5, justify=LEFT, exportselection=False) self._scr_portv = Scrollbar(self._frm_basic, orient=VERTICAL) self._scr_porth = Scrollbar(self._frm_basic, orient=HORIZONTAL) self._lbx_port.config(yscrollcommand=self._scr_portv.set) self._lbx_port.config(xscrollcommand=self._scr_porth.set) self._scr_portv.config(command=self._lbx_port.yview) self._scr_porth.config(command=self._lbx_port.xview) self._lbx_port.bind("<<ListboxSelect>>", self._on_select_port) self._lbl_baudrate = Label(self._frm_basic, text="Baud rate") self._spn_baudrate = Spinbox(self._frm_basic, values=(BAUDRATES), width=8, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._baudrate) self._btn_toggle = Button(self._frm_basic, text=ADVOFF, width=3, command=self._toggle_advanced) self._frm_advanced = Frame(self) self._lbl_databits = Label(self._frm_advanced, text="Data Bits") self._spn_databits = Spinbox(self._frm_advanced, values=(8, 7, 6, 5), width=3, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._databits) self._lbl_stopbits = Label(self._frm_advanced, text="Stop Bits") self._spn_stopbits = Spinbox(self._frm_advanced, values=(2, 1.5, 1), width=3, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._stopbits) self._lbl_parity = Label(self._frm_advanced, text="Parity") self._spn_parity = Spinbox(self._frm_advanced, values=("None", "Even", "Odd", "Mark", "Space"), width=6, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._parity) self._chk_rts = Checkbutton(self._frm_advanced, text="RTS/CTS", variable=self._rtscts) self._chk_xon = Checkbutton(self._frm_advanced, text="Xon/Xoff", variable=self._xonxoff) self._frm_buttons = Frame(self) self._btn_connect = Button(self._frm_buttons, width=45, height=35, image=self._img_conn, command=lambda: self.__app.serial_handler.connect()) self._btn_disconnect = Button(self._frm_buttons, width=45, height=35, image=self._img_disconn, command=lambda: self.__app.serial_handler.disconnect(), state=DISABLED) self._btn_connect_file = Button(self._frm_buttons, width=45, height=35, image=self._img_dataread, command=lambda: self._on_data_stream()) self._lbl_status_preset = Label(self._frm_buttons, font=self.__app.font_md2, text='') # Other configuration options self._frm_options = Frame(self) self._lbl_protocol = Label(self._frm_options, text=LBLPROTDISP) self._rad_nmea = Radiobutton(self._frm_options, text="NMEA", variable=self._protocol, value=NMEA_PROTOCOL) self._rad_ubx = Radiobutton(self._frm_options, text="UBX", variable=self._protocol, value=UBX_PROTOCOL) self._rad_all = Radiobutton(self._frm_options, text="ALL", variable=self._protocol, value=MIXED_PROTOCOL) self._lbl_consoledisplay = Label(self._frm_options, text=LBLDATADISP) self._rad_parsed = Radiobutton(self._frm_options, text="Parsed", variable=self._raw, value=0) self._rad_raw = Radiobutton(self._frm_options, text="Raw", variable=self._raw, value=1) self._lbl_format = Label(self._frm_options, text="Degrees Format") self._spn_format = Spinbox(self._frm_options, values=(DDD, DMS, DMM), width=6, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._format) self._lbl_units = Label(self._frm_options, text="Units") self._spn_units = Spinbox(self._frm_options, values=(UMM, UIK, UI, UMK), width=13, state=READONLY, readonlybackground=ENTCOL, wrap=True, textvariable=self._units) self._chk_scroll = Checkbutton(self._frm_options, text="Autoscroll", variable=self._autoscroll) self._spn_maxlines = Spinbox(self._frm_options, values=("100", "200", "500", "1000", "2000"), width=6, readonlybackground=ENTCOL, wrap=True, textvariable=self._maxlines, state=READONLY) self._chk_webmap = Checkbutton(self._frm_options, text="Web Map Zoom", variable=self._webmap) self._scl_mapzoom = Scale(self._frm_options, from_=1, to=20, orient=HORIZONTAL, relief="sunken", bg=ENTCOL, variable=self._mapzoom) self._chk_datalog = Checkbutton(self._frm_options, text=LBLDATALOG, variable=self._datalog, command=lambda: self._on_data_log()) self._chk_recordtrack = Checkbutton(self._frm_options, text=LBLTRACKRECORD, variable=self._record_track, command=lambda: self._on_record_track()) self._lbl_ubxconfig = Label(self._frm_options, text=LBLUBXCONFIG) self._btn_ubxconfig = Button(self._frm_options, width=45, height=35, text='UBX', image=self._img_ubxconfig, command=lambda: self._on_ubx_config(), state=DISABLED) def _do_layout(self): ''' Position widgets in frame. ''' self._frm_basic.grid(column=0, row=0, columnspan=4, sticky=(W, E)) self._lbl_port.grid(column=0, row=0, sticky=(W)) self._lbx_port.grid(column=1, row=0, sticky=(W, E), padx=3, pady=3) self._scr_portv.grid(column=2, row=0, sticky=(N, S)) self._scr_porth.grid(column=1, row=1, sticky=(E, W)) self._lbl_baudrate.grid(column=0, row=2, sticky=(W)) self._spn_baudrate.grid(column=1, row=2, sticky=(W), padx=3, pady=3) self._btn_toggle.grid(column=2, row=2, sticky=(E)) self._frm_advanced.grid_forget() self._lbl_databits.grid(column=0, row=0, sticky=(W)) self._spn_databits.grid(column=1, row=0, sticky=(W), padx=3, pady=3) self._lbl_stopbits.grid(column=2, row=0, sticky=(W)) self._spn_stopbits.grid(column=3, row=0, sticky=(W), padx=3, pady=3) self._lbl_parity.grid(column=0, row=1, sticky=(W)) self._spn_parity.grid(column=1, row=1, sticky=(W), padx=3, pady=3) self._chk_rts.grid(column=2, row=1, sticky=(W)) self._chk_xon.grid(column=3, row=1, sticky=(W), padx=3, pady=3) ttk.Separator(self).grid(column=0, row=2, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_buttons.grid(column=0, row=3, columnspan=4, sticky=(W, E)) self._btn_connect.grid(column=0, row=0, padx=3, pady=3) self._btn_connect_file.grid(column=1, row=0, padx=3, pady=3) self._btn_disconnect.grid(column=3, row=0, padx=3, pady=3) ttk.Separator(self).grid(column=0, row=7, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._frm_options.grid(column=0, row=8, columnspan=4, sticky=(W, E)) self._lbl_protocol.grid(column=0, row=0, padx=3, pady=3, sticky=(W)) self._rad_nmea.grid(column=1, row=0, padx=0, pady=0, sticky=(W)) self._rad_ubx.grid(column=2, row=0, padx=0, pady=0, sticky=(W)) self._rad_all.grid(column=3, row=0, padx=0, pady=0, sticky=(W)) self._lbl_consoledisplay.grid(column=0, row=1, padx=2, pady=3, sticky=(W)) self._rad_parsed.grid(column=1, row=1, padx=1, pady=3, sticky=(W)) self._rad_raw.grid(column=2, row=1, padx=2, pady=3, sticky=(W)) self._lbl_format.grid(column=0, row=2, padx=3, pady=3, sticky=(W)) self._spn_format.grid(column=1, row=2, padx=2, pady=3, sticky=(W)) self._lbl_units.grid(column=0, row=3, padx=3, pady=3, sticky=(W)) self._spn_units.grid(column=1, row=3, columnspan=3, padx=2, pady=3, sticky=(W)) self._chk_scroll.grid(column=0, row=4, padx=3, pady=3, sticky=(W)) self._spn_maxlines.grid(column=1, row=4, columnspan=3, padx=3, pady=3, sticky=(W)) self._chk_webmap.grid(column=0, row=5, sticky=(W)) self._scl_mapzoom.grid(column=1, row=5, columnspan=3, sticky=(W)) self._chk_datalog.grid(column=0, row=6, padx=3, pady=3, sticky=(W)) self._chk_recordtrack.grid(column=0, row=7, padx=3, pady=3, sticky=(W)) ttk.Separator(self._frm_options).grid(column=0, row=8, columnspan=4, padx=3, pady=3, sticky=(W, E)) self._lbl_ubxconfig.grid(column=0, row=9, padx=3, pady=3, sticky=(W)) self._btn_ubxconfig.grid(column=1, row=9, padx=3, pady=3, sticky=(W)) def _on_select_port(self, *args, **kwargs): ''' Get selected port from listbox and set global variable. ''' idx = self._lbx_port.curselection() if idx == "": idx = 0 port_orig = self._lbx_port.get(idx) port = port_orig[0:port_orig.find(":")] desc = port_orig[port_orig.find(":") + 1:] if desc == '': desc = "device" self._port.set(port) self._port_desc.set(desc) def _on_ubx_config(self, *args, **kwargs): ''' Open UBX configuration dialog panel. ''' self.__app.ubxconfig() def _on_data_log(self): ''' Start or stop data logger ''' if self._datalog.get() == 1: self._logpath = self.__app.file_handler.set_logfile_path() if self._logpath is not None: self.__app.set_status("Data logging enabled: " + self._logpath, "green") else: self._datalog.set(False) else: self._logpath = None self._datalog.set(False) # self.__app.file_handler.close_logfile() self.__app.set_status("Data logging disabled", "blue") def _on_record_track(self): ''' Start or stop track recorder ''' if self._record_track.get() == 1: self._trackpath = self.__app.file_handler.set_trackfile_path() if self._trackpath is not None: self.__app.set_status("Track recording enabled: " + self._trackpath, "green") else: self._record_track.set(False) else: self._trackpath = None self._record_track.set(False) # self.__app.file_handler.close_trackfile() self.__app.set_status("Track recording disabled", "blue") def _on_data_stream(self): ''' Start data file streamer ''' self._logpath = self.__app.file_handler.open_logfile_input() if self._logpath is not None: self.__app.set_status("") self.__app.serial_handler.connect_file() def _toggle_advanced(self): ''' Toggle advanced serial port settings panel on or off ''' self._show_advanced = not self._show_advanced if self._show_advanced: self._frm_advanced.grid(column=0, row=1, columnspan=3, sticky=(W, E)) self._btn_toggle.config(text=ADVON) else: self._frm_advanced.grid_forget() self._btn_toggle.config(text=ADVOFF) def _get_ports(self): ''' Populate list of available serial ports using pyserial comports tool. If no ports found, disable all connection-dependent widgets. Attempt to preselect the first port that has a recognisable GPS designation in its description (usually only works on Posix platforms - Windows doesn't parse UART device desc or HWID) ''' self._ports = sorted(comports()) init_idx = 0 port = '' desc = '' if len(self._ports) > 0: for idx, (port, desc, _) in enumerate(self._ports, 1): self._lbx_port.insert(idx, port + ": " + desc) for kgp in KNOWNGPS: if kgp in desc: init_idx = idx break self._noports = False else: self._noports = True self.set_controls(NOPORTS) self._lbx_port.activate(init_idx) self._port.set(port) self._port_desc.set(desc) def _reset(self): ''' Reset settings to defaults. ''' self._baudrate.set(BAUDRATES[4]) # 9600 self._databits.set(8) self._stopbits.set(1) self._parity.set("None") self._rtscts.set(False) self._xonxoff.set(False) self._protocol.set(MIXED_PROTOCOL) self._format.set(DDD) self._units.set(UMM) self._autoscroll.set(1) self._maxlines.set(300) self._raw.set(False) self._webmap.set(False) self._mapzoom.set(10) self._datalog.set(False) self._record_track.set(False) def set_controls(self, status): ''' ...for the heart of the sun. Public method to enable and disable serial port controls depending on connection status. ''' self._lbl_port.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._lbx_port.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._lbl_baudrate.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_baudrate.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._lbl_databits.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_databits.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._lbl_stopbits.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_stopbits.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._lbl_parity.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._spn_parity.configure(state=(READONLY if status == DISCONNECTED else DISABLED)) self._chk_rts.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._chk_xon.configure(state=(NORMAL if status == DISCONNECTED else DISABLED)) self._btn_connect.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE, NOPORTS) \ else NORMAL)) self._btn_disconnect.config(state=(DISABLED if status in \ (DISCONNECTED, NOPORTS) else NORMAL)) self._chk_datalog.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE, NOPORTS) \ else NORMAL)) self._chk_recordtrack.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE) \ else NORMAL)) self._btn_connect_file.config(state=(DISABLED if status in \ (CONNECTED, CONNECTED_FILE) \ else NORMAL)) self._btn_ubxconfig.config(state=(DISABLED if status in \ (DISCONNECTED, CONNECTED_FILE, NOPORTS) \ else NORMAL)) self.__app.menu.options_menu.entryconfig(0, state=(DISABLED if status in \ (CONNECTED_FILE, DISCONNECTED, NOPORTS) \ else NORMAL)) def get_settings(self): ''' Public method returns all settings as a dict. ''' self._settings['port'] = self._port.get() self._settings['noports'] = self._noports self._settings['port_desc'] = self._port_desc.get() self._settings['baudrate'] = self._baudrate.get() self._settings['databits'] = self._databits.get() self._settings['stopbits'] = self._stopbits.get() self._settings['parity'] = self._parity.get() self._settings['rtscts'] = self._rtscts.get() self._settings['xonxoff'] = self._xonxoff.get() self._settings['protocol'] = self._protocol.get() self._settings['raw'] = self._raw.get() self._settings['autoscroll'] = self._autoscroll.get() self._settings['maxlines'] = self._maxlines.get() self._settings['webmap'] = self._webmap.get() self._settings['mapzoom'] = self._mapzoom.get() self._settings['units'] = self._units.get() self._settings['format'] = self._format.get() self._settings['logpath'] = self._logpath self._settings['datalogging'] = self._datalog.get() self._settings['recordtrack'] = self._record_track.get() return self._settings def get_size(self): ''' Get current frame size. ''' self.update_idletasks() # Make sure we know about any resizing return (self.winfo_width(), self.winfo_height())
class Wt_Select_Dialog(_Dialog): def body(self, master): dialogframe = Frame(master, width=446, height=152) self.dialogframe = dialogframe dialogframe.pack() self.make_Button_1(self.dialogframe) # edit below self.make_Button_2(self.dialogframe) # edit below self.make_Button_3(self.dialogframe) # edit below self.make_Button_4(self.dialogframe) # edit below self.make_Button_5(self.dialogframe) # edit below self.make_Button_6(self.dialogframe) # edit below self.make_Frame_1(self.dialogframe) # edit below self.make_Label_1(self.dialogframe) # edit below self.make_Message_1(self.dialogframe) # edit below self.make_Message_2(self.dialogframe) # edit below self.make_Message_3(self.dialogframe) # edit below self.make_Label_2(self.Frame_1) # edit below self.make_Spinbox_1(self.Frame_1) # edit below def make_Button_1(self, frame): self.Button_1 = Button(frame, text="1", width="6") self.Button_1.grid(row=3, column=1) self.Button_1.bind("<ButtonRelease-1>", self.Button_1_Click) def make_Button_2(self, frame): self.Button_2 = Button(frame, text="2", width="6") self.Button_2.grid(row=3, column=2) self.Button_2.bind("<ButtonRelease-1>", self.Button_2_Click) def make_Button_3(self, frame): self.Button_3 = Button(frame, text="3", width="6") self.Button_3.grid(row=3, column=3) self.Button_3.bind("<ButtonRelease-1>", self.Button_3_Click) def make_Button_4(self, frame): self.Button_4 = Button(frame, text="4", width="6") self.Button_4.grid(row=3, column=4) self.Button_4.bind("<ButtonRelease-1>", self.Button_4_Click) def make_Button_5(self, frame): self.Button_5 = Button(frame, text="5", width="6") self.Button_5.grid(row=3, column=5) self.Button_5.bind("<ButtonRelease-1>", self.Button_5_Click) def make_Button_6(self, frame): self.Button_6 = Button(frame, text="0", width="6") self.Button_6.grid(row=3, column=0) self.Button_6.bind("<ButtonRelease-1>", self.Button_6_Click) def make_Frame_1(self, frame): self.Frame_1 = Frame(frame, width="60", height="50") self.Frame_1.grid(row=5, column=0, columnspan="6") def make_Label_1(self, frame): self.Label_1 = Label(frame, text="Select Weight for %s" % self.label_text, width="40", font="Times\ New\ Roman 14 bold roman") self.Label_1.grid(row=1, column=0, columnspan="6") def make_Message_1(self, frame): self.Message_1 = Message( frame, text= "Weight affects how widgets expand and contract on window resize.", width="400") self.Message_1.grid(row=6, column=0, columnspan="6") def make_Message_2(self, frame): self.Message_2 = Message( frame, text= "Each widget will still need to set the sticky property (e.g. ns, ew, nsew)", width="400") self.Message_2.grid(row=7, column=0, columnspan="6") def make_Message_3(self, frame): self.Message_3 = Message( frame, width="400", text="Use numbered \"Quick-Set\" buttons or set Spinbox and hit OK." ) self.Message_3.grid(row=2, column=0, columnspan="6") def make_Label_2(self, frame): self.Label_2 = Label(frame, text="Select any Value", width="15") self.Label_2.grid(row=2, column=1) def make_Spinbox_1(self, frame): self.Spinbox_1 = Spinbox(frame, to="100", text="Spinbox_1", width="10", from_="1", font="Courier\ New 14 normal roman") self.Spinbox_1.grid(row=2, column=2) self.Spinbox_1_StringVar = StringVar() self.Spinbox_1.configure(textvariable=self.Spinbox_1_StringVar, to="10", from_="1") self.Spinbox_1_StringVar.set("6") self.Spinbox_1_StringVar_traceName = self.Spinbox_1_StringVar.trace_variable( "w", self.Spinbox_1_StringVar_Callback) def Button_1_Click(self, event): #bind method for component ID=Button_1 self.Spinbox_1_StringVar.set("1") self.ok() def Button_2_Click(self, event): #bind method for component ID=Button_2 self.Spinbox_1_StringVar.set("2") self.ok() def Button_3_Click(self, event): #bind method for component ID=Button_3 self.Spinbox_1_StringVar.set("3") self.ok() def Button_4_Click(self, event): #bind method for component ID=Button_4 self.Spinbox_1_StringVar.set("4") self.ok() def Button_5_Click(self, event): #bind method for component ID=Button_5 self.Spinbox_1_StringVar.set("5") self.ok() def Button_6_Click(self, event): #bind method for component ID=Button_6 self.Spinbox_1_StringVar.set("0") self.ok() def Spinbox_1_StringVar_Callback(self, varName, index, mode): pass def validate(self): self.result = {} # return a dictionary of results self.result["weight"] = self.Spinbox_1_StringVar.get() return 1 def apply(self): pass
class ReviewFitPage(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.controller = parent title = Label(self,text="Fit Review",font=("Arial",14,"bold")) title.grid(row=0,column=0,columnspan=6) self.f = Figure(figsize=(5,5), dpi=100) self.a = self.f.add_subplot(111) Label(self, text="Left Bound:").grid(row=1,column=6) Label(self, text="Right Bound:").grid(row=1,column=7) peakSelectorButton = Button(self, text="Manually Choose Element", command=self.send_to_mes) peakSelectorButton.grid(row=5,column=6) integrateButton = Button(self, text="Manually Integrate and Choose Element", command = self.send_to_mi) integrateButton.grid(row=5,column=7) acceptButton = Button(self, text="Fit looks good, let the program continue", command=self.submit) acceptButton.grid(row=6,column=6) ignoreButton = Button(self, text="Ignore this data", command = lambda:self.controller.peakCounter.set(self.controller.peakCounter.get()+1)) ignoreButton.grid(row=6,column=7) self.KnownPeaksFrame = Frame(self) Label(self.KnownPeaksFrame, text="Peak Information (Center, Amplitude, Width)").grid(row=0, column=0, columnspan=2) self.newPeakEntry = Entry(self.KnownPeaksFrame) self.newPeakEntry.grid(row=1,column=0) self.newPeakEntry.insert(0,"Enter Peak Energy") self.newPeakEntry.bind("<FocusIn>",self.clear_new_entry) Button(self.KnownPeaksFrame, text="Add", command=lambda:self.add_peak(self.newPeakEntry.get())).grid(row=1,column=1) self.KnownPeaksFrame.grid(row=3,column=6, columnspan=2) Button(self, text="Reanalyze", command=self.reanalyze).grid(row=4,column=6,columnspan=2) self.energies = [] self.cps = [] self.slope = 0 self.intercept = 0 self.ctrs = [] self.annots = [] self.fill = None self.peakGUIList = [] self.removeBtns = [] def populate_values(self, startInd, endInd, peaks, variances): self.a.cla() self.startInd = startInd self.energies = self.controller.file1Energies[startInd-20:endInd+21] self.cps = self.controller.file1CPS[startInd-20:endInd+21] self.variances = list(variances) if len(peaks) > 0: self.ctrs = np.array(peaks[2::3]) self.amps = np.array(peaks[3::3]) self.wids = np.array(peaks[4::3]) self.slope = peaks[0] self.intercept = peaks[1] poss = chain.from_iterable(self.get_possibilites(True)) poss = list(k for k,_ in groupby(poss)) self.peaks = list(peaks[2:]) fitX = np.arange(self.energies[20],self.energies[-20],.01) self.fitX = fitX backgroundY = fitX * peaks[0] + np.array([peaks[1]]*len(fitX)) self.backgroundY = backgroundY fitY = self.controller.multiple_gaussian_and_secant(fitX,*peaks) self.a.plot(fitX, fitY, "r-", label = "Fit") fullAmps = self.amps + (peaks[0] * self.ctrs + peaks[1]) self.peakPoints = self.a.plot(self.ctrs, fullAmps,"go",label="Found Peaks",picker=6)[0] self.peakPoints.set_pickradius(10) self.backgroundLine = self.a.plot(fitX,backgroundY,"k-", label = "Background") self.f.canvas.mpl_connect('motion_notify_event', self.on_plot_hover) self.a.plot(self.energies, self.cps,"bo", label="Observed Data") self.a.set_xlim(self.energies[20],self.energies[-20]) self.canvas = FigureCanvasTkAgg(self.f, self) self.canvas.draw() self.canvas.get_tk_widget().grid(row=1,column=0,columnspan=6, rowspan=6) self.a.legend(loc='upper right', prop={'size': 8}) toolbarFrame = Frame(self) toolbarFrame.grid(row=7,column=0,columnspan=6, sticky="w") toolbar = NavigationToolbar2Tk(self.canvas, toolbarFrame) self.spinboxLeftVal = DoubleVar() self.spinboxLeft = Spinbox(self, values=self.energies[:-20], command = self.update_right, textvariable = self.spinboxLeftVal) self.spinboxLeft.bind("<Return>",lambda x:self.update_right()) self.spinboxLeft.bind("<FocusOut>",lambda x:self.update_right()) self.spinboxLeftVal.set(self.energies[20]) self.spinboxLeft.grid(row=2,column=6) self.spinboxRightVal = DoubleVar() self.spinboxRight = Spinbox(self, values = self.energies[21:], command = self.update_left, textvariable = self.spinboxRightVal) self.spinboxRight.bind("<Return>",lambda x:self.update_left()) self.spinboxRight.bind("<FocusOut>",lambda x:self.update_left()) self.spinboxRightVal.set(self.energies[-20]) self.spinboxRight.grid(row=2,column=7) for i in self.peakGUIList: i.destroy() for i in self.removeBtns: i.destroy() self.peakGUIList = [] self.removeBtns = [] for i in range(len(self.ctrs)): self.peakGUIList.append(Label(self.KnownPeaksFrame, text="{:5f}, {:5f}, {:5f}".format(self.ctrs[i],self.amps[i],self.wids[i]))) self.removeBtns.append(Button(self.KnownPeaksFrame, text="Remove", command=lambda temp=i:self.remove_peak(temp))) self.peakGUIList[i].grid(row=i+2,column=0) self.removeBtns[i].grid(row=i+2,column=1) def remove_peak(self, ind): self.peakGUIList[ind].destroy() del self.peakGUIList[ind] self.removeBtns[-1].destroy() del self.removeBtns[-1] def add_peak(self, loc): try: loc = float(loc) except ValueError: return None self.reset_new_entry() i=0 while self.energies[i] < loc: i += 1 self.peakGUIList.append(Label(self.KnownPeaksFrame, text="{:5f}, {:5f}, 1.00".format(self.energies[i], self.cps[i]))) self.removeBtns.append(Button(self.KnownPeaksFrame, text="Remove", command=lambda temp=len(self.peakGUIList)-1:self.remove_peak(temp))) self.peakGUIList[-1].grid(row=len(self.peakGUIList)+1, column=0) self.removeBtns[-1].grid(row=len(self.peakGUIList)+1, column=1) def on_plot_hover(self, e): cont, ind = self.peakPoints.contains(e) if cont and self.fill == None: x = self.peakPoints.get_xdata()[ind["ind"][0]] y = self.peakPoints.get_ydata()[ind["ind"][0]] - (self.slope * x + self.intercept) self.fill = self.a.fill_between(self.fitX, self.backgroundY, self.backgroundY + self.controller.multiple_gaussian(self.fitX, x, y, self.wids[np.where(self.ctrs == x)[0][0]]), facecolor='red', alpha=0.5) self.canvas.draw() else: if self.fill != None: self.fill.remove() self.fill = None self.canvas.draw() #TODO: add manual entry flag, and call it with a keybind from the spinboxes def update_left(self): temp = self.spinboxLeftVal.get() if self.spinboxRightVal.get() > self.energies[-1]: messagebox.showinfo("Out of Bounds","Please enter an X value within the currently plotted points") self.spinboxRightVal.set(self.energies[-20]) return None try: newRange = self.energies[:np.where(self.energies==self.spinboxRightVal.get())[0][0]] except IndexError: newRange = self.energies[:binary_search_find_nearest(self.energies, self.spinboxRightVal.get())] self.spinboxLeft.configure(values=newRange) self.spinboxLeftVal.set(temp) def update_right(self): temp = self.spinboxRightVal.get() if self.spinboxLeftVal.get() < self.energies[0]: messagebox.showinfo("Out of Bounds","Please enter an X value within the currently plotted points") self.spinboxLeftVal.set(self.energies[20]) return None try: newRange = self.energies[np.where(self.energies==self.spinboxLeftVal.get())[0][0]+1:] except IndexError: newRange = self.energies[binary_search_find_nearest(self.energies, self.spinboxLeftVal.get()):] self.spinboxRight.configure(values=newRange) self.spinboxRightVal.set(temp) def reanalyze(self): try: lowIndex = np.where(self.energies==self.spinboxLeftVal.get())[0][0] highIndex = np.where(self.energies==self.spinboxRightVal.get())[0][0] + 1 except IndexError: lowIndex = binary_search_find_nearest(self.energies, self.spinboxLeftVal.get()) highIndex = binary_search_find_nearest(self.energies, self.spinboxRightVal.get()) guesses = [[float(j) for j in i.cget("text").split(", ")] for i in self.peakGUIList] guesses = list(chain.from_iterable(guesses)) guesses = [self.slope, self.intercept] + guesses try: popt, pcov = curve_fit(self.controller.multiple_gaussian_and_secant, xdata = self.energies[lowIndex:highIndex], ydata = self.cps[lowIndex:highIndex], p0 = np.array(guesses)) self.populate_values(self.startInd - 20 + lowIndex, self.startInd - 20 + highIndex, popt, np.diag(pcov)[2:]) except RuntimeError: messagebox.showwarning("No fit found", "No good peak fit could be determined. Try entering fewer centroids.") def clear_new_entry(self, _): self.newPeakEntry.delete(0,"end") def reset_new_entry(self): self.newPeakEntry.delete(0,"end") self.newPeakEntry.insert(0,"Enter Peak Energy") def get_possibilites(self, MP): if MP:#Multiple peaks return [self.controller.get_possibilites_list(c) for c in self.ctrs] else: return self.controller.get_possibilites_list((self.energies[20]+self.energies[-20])/2) def send_to_mi(self): #TODO: get left and right selectors try: left = float(self.spinboxLeftVal.get()) right = float(self.spinboxRightVal.get()) except ValueError: messagebox.showinfo("Bad Input","Please enter in-range floating point numbers for the bounds.") if left < self.energies[0] or right > self.energies[-1]: messagebox.showinfo("Bad Input","Please enter in-range floating point numbers for the bounds.") return None r = binary_search_find_nearest(self.energies, right) l = binary_search_find_nearest(self.energies, left) self.controller.show_frame(ManualIntegrationPage) self.controller.frames[ManualIntegrationPage].populate_values(self.energies[l:r], self.cps[l:r]) self.controller.frames[ManualIntegrationPage].add_peak_selector(self.get_possibilites(False)) def send_to_mes(self): cpsNoBgd = [j - (self.energies[i] * self.slope + self.intercept) for i,j in enumerate(self.cps)] self.controller.show_frame(ManualElementSelect) self.controller.frames[ManualElementSelect].populate_values(self.energies[20:-20], cpsNoBgd[20:-20]) self.controller.frames[ManualElementSelect].add_peak_selectors(self.peaks,self.get_possibilites(True),self.variances) def submit(self): self.controller.add_auto_peaks(self.peaks, list(self.variances)) self.controller.increment_peak_counter()
class Form(Toplevel): def __init__(self, master, event, new=False): Toplevel.__init__(self, master) self.minsize(410, 402) if master.winfo_ismapped(): self.transient(master) self.protocol('WM_DELETE_WINDOW', self.cancel) self._only_nb = self.register(only_nb) self.event = event if new: self.title(_('New Event')) else: self.title(_('Edit Event')) self._new = new self._task = BooleanVar(self, bool(event['Task'])) self._whole_day = BooleanVar(self, event['WholeDay']) # --- style style = Style(self) active_bg = style.lookup('TEntry', 'selectbackground', ('focus', )) self.alarms = [] notebook = Notebook(self) notebook.pack(fill='both', expand=True) Button(self, text=_('Ok'), command=self.ok).pack(pady=(10, 6), padx=4) # --- event settings frame_event = Frame(notebook) notebook.add(frame_event, text=_('Event'), sticky='eswn', padding=4) frame_event.columnconfigure(1, weight=1) frame_event.rowconfigure(5, weight=1) self.img_moins = PhotoImage(master=self, file=IM_DEL) self.img_bell = PhotoImage(master=self, file=IM_BELL) Label(frame_event, text=_('Summary')).grid(row=0, column=0, padx=4, pady=6, sticky='e') Label(frame_event, text=_('Place')).grid(row=1, column=0, padx=4, pady=6, sticky='e') Label(frame_event, text=_('Start')).grid(row=2, column=0, padx=4, pady=6, sticky='e') self._end_label = Label(frame_event, text=_('End')) self._end_label.grid(row=3, column=0, padx=4, pady=6, sticky='e') frame_task = Frame(frame_event) frame_task.grid(row=4, column=1, padx=4, pady=6, sticky='w') Label(frame_event, text=_('Description')).grid(row=5, column=0, padx=4, pady=6, sticky='e') Label(frame_event, text=_('Category')).grid(row=6, column=0, padx=4, pady=6, sticky='e') Button(frame_event, image=self.img_bell, command=self.add_reminder, padding=0).grid(row=7, column=0, padx=4, pady=6, sticky='en') self.summary = Entry(frame_event, width=35) self.summary.insert(0, self.event['Summary']) self.summary.grid(row=0, column=1, padx=4, pady=6, sticky='ew') self.place = Entry(frame_event, width=35) self.place.insert(0, self.event['Place']) self.place.grid(row=1, column=1, padx=4, pady=6, sticky='ew') frame_start = Frame(frame_event) frame_start.grid(row=2, column=1, padx=4, pady=6, sticky='w') frame_end = Frame(frame_event) frame_end.grid(row=3, column=1, padx=4, pady=6, sticky='w') txt_frame = Frame(frame_event, style='txt.TFrame', border=1, relief='sunken') self.desc = Text(txt_frame, width=35, height=4, highlightthickness=0, relief='flat', selectbackground=active_bg) self.desc.insert('1.0', self.event['Description']) self.desc.pack(fill='both', expand=True) txt_frame.grid(row=5, column=1, padx=4, pady=6, sticky='ewsn') cats = list(CONFIG.options('Categories')) width = max([len(cat) for cat in cats]) self.category = Combobox(frame_event, width=width + 2, values=cats, state='readonly') self.category.set(event['Category']) self.category.grid(row=6, column=1, padx=4, pady=6, sticky='w') self.frame_alarms = Frame(frame_event) self.frame_alarms.grid(row=7, column=1, sticky='w') # --- *--- task Checkbutton(frame_task, text=_('Task'), command=self._change_label, variable=self._task).pack(side='left') self.task_progress = Combobox(frame_task, state='readonly', width=9, values=(_('Pending'), _('In Progress'), _('Completed'), _('Cancelled'))) self.task_progress.pack(side='left', padx=(8, 4)) self.in_progress = Combobox( frame_task, state='readonly', width=5, values=['{}%'.format(i) for i in range(0, 110, 10)]) self.in_progress.pack(side='left', padx=4) if not event['Task']: self.task_progress.set(_('Pending')) self.in_progress.set('0%') elif '%' in event['Task']: self.task_progress.set(_('In Progress')) self.in_progress.set(event['Task']) else: self.task_progress.set(_(event['Task'])) self.in_progress.set('0%') # calendar settings prop = { op: CONFIG.get('Calendar', op) for op in CONFIG.options('Calendar') } prop['font'] = "Liberation\ Sans 9" prop.update(selectforeground='white', selectbackground=active_bg) locale = CONFIG.get('General', 'locale') # --- *--- start date self.start_date = self.event['Start'] self.start_entry = DateEntry(frame_start, locale=locale, width=10, justify='center', year=self.start_date.year, month=self.start_date.month, day=self.start_date.day, **prop) self.start_hour = Combobox(frame_start, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(24)]) self.start_hour.set('%02d' % self.start_date.hour) self.start_min = Combobox(frame_start, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(0, 60, 5)]) self.start_min.set('%02d' % self.start_date.minute) self.start_entry.pack(side='left', padx=(0, 18)) self.start_hour.pack(side='left', padx=(4, 0)) self.start_date = self.start_date.date() Label(frame_start, text=':').pack(side='left') self.start_min.pack(side='left', padx=(0, 4)) Checkbutton(frame_start, text=_("whole day"), variable=self._whole_day, command=self._toggle_whole_day).pack(side='left', padx=4) # --- *--- end date self.end_date = self.event['End'] self.end_entry = DateEntry(frame_end, justify='center', locale=locale, width=10, year=self.end_date.year, month=self.end_date.month, day=self.end_date.day, **prop) self.end_hour = Combobox(frame_end, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(24)]) self.end_hour.set('%02d' % self.end_date.hour) self.end_min = Combobox(frame_end, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(0, 60, 5)]) self.end_min.set('%02d' % self.end_date.minute) self.end_entry.pack(side='left', padx=(0, 18)) self.end_hour.pack(side='left', padx=(4, 0)) Label(frame_end, text=':').pack(side='left') self.end_min.pack(side='left', padx=(0, 4)) self.end_date = self.end_date.date() for date in self.event['Reminders'].values(): self.add_reminder(date) self._toggle_whole_day() # --- repetition settings frame_rep = Frame(notebook) notebook.add(frame_rep, text=_('Repetition'), padding=4, sticky='eswn') frame_rep.columnconfigure(0, weight=1) frame_rep.columnconfigure(1, weight=1) frame_rep.rowconfigure(1, weight=1) self._repeat = BooleanVar(self, bool(self.event['Repeat'])) repeat = { 'Frequency': 'year', 'Limit': 'always', 'NbTimes': 1, 'EndDate': (datetime.now() + timedelta(days=1)).date(), 'WeekDays': [self.start_date.isocalendar()[2] - 1] } repeat.update(self.event['Repeat']) self._repeat_freq = StringVar(self, repeat['Frequency']) Checkbutton(frame_rep, text=_('Repeat event'), variable=self._repeat, command=self._toggle_rep).grid(row=0, column=0, columnspan=2, padx=4, pady=6, sticky='w') # --- *--- Frequency frame_freq = LabelFrame(frame_rep, text=_('Frequency')) frame_freq.grid(row=1, column=0, sticky='eswn', padx=(0, 3)) self._lfreq = Label(frame_freq, text=_('Every:')) self._lfreq.grid(row=0, column=0, padx=4, pady=2, sticky='e') self._freqs = [] for i, val in enumerate(['Year', 'Month', 'Week']): r = Radiobutton(frame_freq, text=_(val), variable=self._repeat_freq, value=val.lower(), command=self._toggle_wd) r.grid(row=i, column=1, padx=4, pady=2, sticky='nw') self._freqs.append(r) frame_days = Frame(frame_freq) frame_days.grid(row=2, column=2, padx=4, pady=2, sticky='nw') self._week_days = [] days = get_day_names("wide", locale=locale) days = [days[i] for i in range(7)] for day in days: ch = Checkbutton(frame_days, text=day) ch.pack(anchor='w') self._week_days.append(ch) for d in repeat['WeekDays']: self._week_days[int(d)].state(('selected', )) # --- *--- Limit frame_lim = LabelFrame(frame_rep, text=_('Limit')) frame_lim.grid(row=1, column=1, sticky='eswn', padx=(3, 0)) frame_lim.grid(row=1, column=1, sticky='eswn', padx=(3, 0)) self._repeat_lim = StringVar(self, repeat['Limit']) # always r1 = Radiobutton(frame_lim, text=_('Always'), value='always', variable=self._repeat_lim, command=self._toggle_lim) r1.grid(row=0, column=0, sticky='w') # until r2 = Radiobutton(frame_lim, text=_('Until'), value='until', variable=self._repeat_lim, command=self._toggle_lim) r2.grid(row=1, column=0, sticky='w') until_date = repeat['EndDate'] self.until_entry = DateEntry(frame_lim, width=10, justify='center', locale=locale, year=until_date.year, month=until_date.month, day=until_date.day, **prop) self.until_entry.grid(row=1, column=1, columnspan=2, sticky='w', padx=(4, 10), pady=2) # after r3 = Radiobutton(frame_lim, text=_('After'), value='after', variable=self._repeat_lim, command=self._toggle_lim) r3.grid(row=2, column=0, sticky='w') frame_after = Frame(frame_lim, style='txt.TFrame', relief='sunken', border=1) self.s_after = Spinbox(frame_after, from_=0, to=100, width=3, justify='center', relief='flat', highlightthickness=0, validate='key', validatecommand=(self._only_nb, '%P'), disabledbackground='white') self.s_after.pack() self.s_after.delete(0, 'end') self.s_after.insert(0, str(repeat['NbTimes'])) frame_after.grid(row=2, column=1, padx=4, pady=2, sticky='w') self._llim = Label(frame_lim, text=_('times')) self._llim.grid(row=2, column=2, padx=0, pady=2, sticky='w') self._rb_lim = [r1, r2, r3] self._toggle_rep() self._change_label() # --- bindings self.bind('<Configure>') self.task_progress.bind('<<ComboboxSelected>>', self._toggle_in_progress) self.start_entry.bind('<<DateEntrySelected>>', self._select_start) self.end_entry.bind('<<DateEntrySelected>>', self._select_end) self.start_hour.bind("<<ComboboxSelected>>", self._select_start_hour) self.start_min.bind("<<ComboboxSelected>>", self._select_start_min) self.end_min.bind("<<ComboboxSelected>>", self._select_end_time) self.end_hour.bind("<<ComboboxSelected>>", self._select_end_time) self.bind_class("TCombobox", "<<ComboboxSelected>>", self.__clear_selection, add=True) # self.wait_visibility(self) # self.grab_set() self.summary.focus_set() def _toggle_lim(self, val=True): if val: val = self._repeat_lim.get() if val == 'until': self.s_after.configure(state='disabled') self._llim.state(('disabled', )) self.until_entry.state(('!disabled', )) elif val == 'after': self._llim.state(('!disabled', )) self.s_after.configure(state='normal') self.until_entry.state(('disabled', )) else: self.s_after.configure(state='disabled') self._llim.state(('disabled', )) self.until_entry.state(('disabled', )) def _toggle_rep(self): rep = self._repeat.get() state = state = '!' * int(rep) + "disabled" for r in self._freqs: r.state((state, )) for r in self._rb_lim: r.state((state, )) self._lfreq.state((state, )) self._toggle_wd(rep) self._toggle_lim(rep) def _toggle_wd(self, val=True): if val: val = self._repeat_freq.get() state = '!' * int(val == 'week') + "disabled" for ch in self._week_days: ch.state((state, )) def _toggle_whole_day(self): if self._whole_day.get(): self.start_min.set('00') self.start_hour.set('00') self.end_min.set('59') self.end_hour.set('23') self.start_min.state(("disabled", )) self.start_hour.state(("disabled", )) self.end_min.state(("disabled", )) self.end_hour.state(("disabled", )) else: self.start_min.state(("!disabled", )) self.start_hour.state(("!disabled", )) self.end_min.state(("!disabled", )) self.end_hour.state(("!disabled", )) def _toggle_in_progress(self, event=None): if self.task_progress.get() == _('In Progress'): self.in_progress.state(('!disabled', )) else: if self.task_progress.get() == _('Completed'): self.in_progress.set('100%') self.in_progress.state(('disabled', )) def _change_label(self): if self._task.get(): self.task_progress.state(('!disabled', )) self._toggle_in_progress() self._end_label.configure(text=_('Deadline')) else: self.task_progress.state(('disabled', )) self.in_progress.state(('disabled', )) self._end_label.configure(text=_('End')) def _on_move(self, event): self.start_cal.withdraw() self.end_cal.withdraw() self.until_cal.withdraw() @staticmethod def __clear_selection(event): combo = event.widget combo.selection_clear() def _select_start(self, event=None): dt = self.start_entry.get_date() - self.start_date self.end_date = self.end_date + dt self.end_entry.set_date(self.end_date) self.start_date = self.start_entry.get_date() def _select_end(self, event=None): self.end_date = self.end_entry.get_date() start = self.start_entry.get_date() if start >= self.end_date: self.start_date = self.end_date self.start_entry.set_date(self.end_date) start_time = time(int(self.start_hour.get()), int(self.start_min.get())) end_time = time(int(self.start_hour.get()), int(self.end_min.get())) if start_time > end_time: self.start_hour.set(self.end_hour.get()) self.start_min.set(self.end_min.get()) def _select_start_hour(self, event): h = int(self.start_hour.get()) self.end_hour.set('%02d' % ((h + 1) % 24)) def _select_start_min(self, event): m = int(self.start_min.get()) self.end_min.set('%02d' % m) def _select_end_time(self, event): if self.start_entry.get() == self.end_entry.get(): start_time = time(int(self.start_hour.get()), int(self.start_min.get())) end_time = time(int(self.end_hour.get()), int(self.end_min.get())) if start_time > end_time: self.start_hour.set(self.end_hour.get()) self.start_min.set(self.end_min.get()) def add_reminder(self, date=None): def remove(): self.alarms.remove((when, what)) rem.destroy() rem = Frame(self.frame_alarms) frame_when = Frame(rem, style='txt.TFrame', relief='sunken', border=1) when = Spinbox(frame_when, from_=0, to=59, width=3, justify='center', relief='flat', highlightthickness=0, validate='key', validatecommand=(self._only_nb, '%P')) when.pack() when.delete(0, 'end') what = Combobox(rem, width=8, state='readonly', values=(_('minutes'), _('hours'), _('days'))) if date: hour = int(self.start_hour.get()) minute = int(self.start_min.get()) dt = datetime.combine(self.start_entry.get_date(), time(hour=hour, minute=minute)) - date if dt.days > 0: when.insert(0, str(dt.days)) what.set(_('days')) else: h, m, s = str(dt).split(':') if h != "0": when.insert(0, h) what.set(_('hours')) else: when.insert(0, str(int(m))) what.set(_('minutes')) else: when.insert(0, '15') what.set(_('minutes')) self.alarms.append((when, what)) Label(rem, text=_('Reminder:')).pack(side='left', padx=4, pady=4) frame_when.pack(side='left', pady=4, padx=4) what.pack(side='left', pady=4, padx=4) Button(rem, image=self.img_moins, padding=0, command=remove).pack(side='left', padx=4, pady=4) rem.pack() def ok(self): summary = self.summary.get() if not summary: showerror(_("Error"), _("The field 'Summary' cannot be empty."), parent=self) return self.event['Summary'] = summary self.event['Place'] = self.place.get() self.event['Start'] = "%s %s:%s" % ( self.start_entry.get_date().strftime("%Y-%m-%d"), self.start_hour.get(), self.start_min.get()) self.event['End'] = "%s %s:%s" % (self.end_entry.get_date().strftime( "%Y-%m-%d"), self.end_hour.get(), self.end_min.get()) self.event['Description'] = self.desc.get('1.0', 'end') self.event['Category'] = self.category.get() if not self._task.get(): self.event['Task'] = False else: prog = self.task_progress.get() if prog == _('In Progress'): self.event['Task'] = self.in_progress.get() else: self.event['Task'] = TASK_REV_TRANSLATION[prog] self.event["WholeDay"] = self._whole_day.get() if not self._repeat.get(): self.event['Repeat'] = {} else: days = [] for i in range(7): if "selected" in self._week_days[i].state(): days.append(i) repeat = { 'Frequency': self._repeat_freq.get(), 'Limit': self._repeat_lim.get(), 'NbTimes': int(self.s_after.get()), 'EndDate': self.until_entry.get_date(), 'WeekDays': days } self.event['Repeat'] = repeat self.event.reminder_remove_all() for when, what in self.alarms: dt = int(when.get()) unit = FREQ_REV_TRANSLATION[what.get()] date = self.event['Start'] - timedelta(**{unit: dt}) self.event.reminder_add(date) if self._new: self.master.event_add(self.event) else: self.master.event_configure(self.event.iid) self.destroy() def cancel(self): if not self._new: self.master.widgets['Calendar'].add_event(self.event) self.destroy()
class _full_combo: def __init__(self, master): grid_frame = Frame( master ) self.grid_frame = grid_frame grid_frame.pack(expand=1, fill=BOTH) self.master = master self.x, self.y, self.w, self.h = 10, 10, 519, 326 self.master.title("full_combo") self.RadioGroup_1_StringVar = StringVar() self.make_Button_1( self.grid_frame ) # Button: at Main(1,1) self.make_Notebook_1( self.grid_frame ) # Notebook: at Main(1,2) self.make_Tab_1( self.Notebook_1 ) # Tab: Small : at Notebook_1(1,1) self.make_Tab_2( self.Notebook_1 ) # Tab: Medium : at Notebook_1(1,2) self.make_Tab_3( self.Notebook_1 ) # Tab: Large : at Notebook_1(1,3) self.make_Canvas_1( self.Tab_1 ) # Canvas: at Tab_1(1,3) self.make_Frame_1( self.Tab_1 ) # Frame: at Tab_1(1,2) self.make_Checkbutton_2( self.Frame_1 ) # Checkbutton: at Frame_1(1,1) self.make_Combobox_2( self.Frame_1 ) # Combobox: Mine Yours Ours : at Frame_1(2,1) self.make_Entry_2( self.Frame_1 ) # Entry: at Frame_1(3,1) self.make_LabelFrame_1( self.Tab_2 ) # LabelFrame: Left : at Tab_2(1,1) self.make_LabelFrame_2( self.Tab_2 ) # LabelFrame: Right : at Tab_2(1,2) self.make_Listbox_1( self.LabelFrame_1 ) # Listbox: at LabelFrame_1(1,1) self.make_Message_1( self.LabelFrame_1 ) # Message: at LabelFrame_1(2,1) self.make_Menubutton_1( self.LabelFrame_2 ) # Menubutton: at LabelFrame_2(1,1) self.make_Notebook_2( self.LabelFrame_2 ) # Notebook: at LabelFrame_2(2,1) self.make_Tab_4( self.Notebook_2 ) # Tab: at Notebook_2(1,1) self.make_Tab_5( self.Notebook_2 ) # Tab: at Notebook_2(1,2) self.make_RadioGroup_1( self.Tab_4 ) # RadioGroup: at Tab_4(1,1) self.make_Radiobutton_1( self.RadioGroup_1 ) # Radiobutton: 1 : at RadioGroup_1(2,1) self.make_Radiobutton_2( self.RadioGroup_1 ) # Radiobutton: 2 : at RadioGroup_1(3,1) self.make_Radiobutton_3( self.RadioGroup_1 ) # Radiobutton: 3 : at RadioGroup_1(4,1) self.make_Radiobutton_4( self.RadioGroup_1 ) # Radiobutton: 4 : at RadioGroup_1(5,1) self.make_Scale_1( self.Tab_5 ) # Scale: 2.5 to 7.5 : at Tab_5(2,1) self.make_Spinbox_1( self.Tab_5 ) # Spinbox: 1 to 10 : at Tab_5(3,1) self.make_Button_2( self.Tab_3 ) # Button: at Tab_3(3,1) self.make_Text_1( self.Tab_3 ) # Text: at Tab_3(2,1) self.make_Treeview_1( self.Tab_3 ) # Treeview: at Tab_3(2,2) self.grid_frame.rowconfigure(1, weight=1) self.Tab_1.rowconfigure(1, weight=1) self.Tab_2.rowconfigure(1, weight=1) self.LabelFrame_1.columnconfigure(1, weight=1) self.grid_frame.columnconfigure(2, weight=1) self.Tab_2.columnconfigure(2, weight=1) self.Tab_1.columnconfigure(3, weight=1) self.Tab_2.columnconfigure(1, weight=1) self.RadioGroup_1_StringVar.set("1") self.RadioGroup_1_StringVar_traceName = self.RadioGroup_1_StringVar.trace_variable("w", self.RadioGroup_1_StringVar_Callback) # >>>>>>insert any user code below this comment for section "top_of_init" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Button_1" def make_Button_1(self, frame): """ Button: at Main(1,1)""" self.Button_1 = Button( frame , text="Button_1", width="15", anchor="e") self.Button_1.grid(row=1, column=1, sticky="s") # >>>>>>insert any user code below this comment for section "make_Button_1" self.Button_1.bind("<ButtonRelease-1>", self.Button_1_Click) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Notebook_1" def make_Notebook_1(self, frame): """ Notebook: at Main(1,2)""" self.Notebook_1 = Notebook ( frame , width="400", height="300") self.Notebook_1.grid(row=1, column=2, sticky="nsew") # >>>>>>insert any user code below this comment for section "make_Notebook_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Tab_1" def make_Tab_1(self, frame): """ Tab: Small : at Notebook_1(1,1)""" self.Tab_1 = Frame( frame ) self.Notebook_1.add( self.Tab_1, text="Small" ) # >>>>>>insert any user code below this comment for section "make_Tab_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Tab_2" def make_Tab_2(self, frame): """ Tab: Medium : at Notebook_1(1,2)""" self.Tab_2 = Frame( frame ) self.Notebook_1.add( self.Tab_2, text="Medium" ) # >>>>>>insert any user code below this comment for section "make_Tab_2" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Tab_3" def make_Tab_3(self, frame): """ Tab: Large : at Notebook_1(1,3)""" self.Tab_3 = Frame( frame ) self.Notebook_1.add( self.Tab_3, text="Large" ) # >>>>>>insert any user code below this comment for section "make_Tab_3" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Canvas_1" def make_Canvas_1(self, frame): """ Canvas: at Tab_1(1,3)""" self.Canvas_1 = Canvas( frame , height="50", width="60") self.Canvas_1.grid(row=1, column=3, sticky="nsew") # >>>>>>insert any user code below this comment for section "make_Canvas_1" self.Canvas_1.config(bg='#ffffcc') self.Canvas_1.bind("<ButtonRelease-1>", self.Canvas_1_Click) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Frame_1" def make_Frame_1(self, frame): """ Frame: at Tab_1(1,2)""" self.Frame_1 = Frame( frame , width="60", height="50") self.Frame_1.grid(row=1, column=2, sticky="n") # >>>>>>insert any user code below this comment for section "make_Frame_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Checkbutton_2" def make_Checkbutton_2(self, frame): """ Checkbutton: at Frame_1(1,1)""" self.Checkbutton_2 = Checkbutton( frame , text="Checkbutton_2", width="15", anchor="e") self.Checkbutton_2.grid(row=1, column=1) self.Checkbutton_2_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Checkbutton_2" self.Checkbutton_2.configure(variable=self.Checkbutton_2_StringVar, onvalue="yes", offvalue="no") self.Checkbutton_2_StringVar.set("no") self.Checkbutton_2_StringVar_traceName = self.Checkbutton_2_StringVar.trace_variable("w", self.Checkbutton_2_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Combobox_2" def make_Combobox_2(self, frame): """ Combobox: Mine Yours Ours : at Frame_1(2,1)""" self.Combobox_2 = Combobox( frame , text="Combobox_2", values="Mine Yours Ours") self.Combobox_2.grid(row=2, column=1) self.Combobox_2_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Combobox_2" self.Combobox_2.configure(textvariable=self.Combobox_2_StringVar) self.Combobox_2_StringVar.set( "Mine" ) self.Combobox_2_StringVar_traceName = self.Combobox_2_StringVar.trace_variable("w", self.Combobox_2_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Entry_2" def make_Entry_2(self, frame): """ Entry: at Frame_1(3,1)""" self.Entry_2 = Entry( frame , width="15") self.Entry_2.grid(row=3, column=1) self.Entry_2_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Entry_2" self.Entry_2.configure(textvariable=self.Entry_2_StringVar) self.Entry_2_StringVar_traceName = self.Entry_2_StringVar.trace_variable("w", self.Entry_2_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_LabelFrame_1" def make_LabelFrame_1(self, frame): """ LabelFrame: Left : at Tab_2(1,1)""" self.LabelFrame_1 = LabelFrame( frame , text="Left", width="60", height="50") self.LabelFrame_1.grid(row=1, column=1, sticky="nsew") # >>>>>>insert any user code below this comment for section "make_LabelFrame_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_LabelFrame_2" def make_LabelFrame_2(self, frame): """ LabelFrame: Right : at Tab_2(1,2)""" self.LabelFrame_2 = LabelFrame( frame , text="Right", width="60", height="50") self.LabelFrame_2.grid(row=1, column=2, sticky="nsew") # >>>>>>insert any user code below this comment for section "make_LabelFrame_2" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Listbox_1" def make_Listbox_1(self, frame): """ Listbox: at LabelFrame_1(1,1)""" self.Listbox_1 = Listbox( frame , height="12", width="30") self.Listbox_1.grid(row=1, column=1) # >>>>>>insert any user code below this comment for section "make_Listbox_1" # Edit the Listbox Entries self.Listbox_1.insert(END, "apples") self.Listbox_1.insert(END, "oranges") self.Listbox_1.insert(END, "grapes") self.Listbox_1.bind("<ButtonRelease-1>", self.Listbox_1_Click) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Message_1" def make_Message_1(self, frame): """ Message: at LabelFrame_1(2,1)""" self.Message_1 = Message( frame , text="Message_1", width="55", anchor="e") self.Message_1.grid(row=2, column=1, sticky="ew") # >>>>>>insert any user code below this comment for section "make_Message_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Menubutton_1" def make_Menubutton_1(self, frame): """ Menubutton: at LabelFrame_2(1,1)""" self.Menubutton_1 = Menubutton( frame , text="Menubutton_1", width="15", anchor="e") self.Menubutton_1.grid(row=1, column=1) self.Menubutton_1_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Menubutton_1" self.Menubutton_1.configure(textvariable=self.Menubutton_1_StringVar, text="Select") self.Menubutton_1_StringVar.set("Select") self.Menubutton_1_StringVar_traceName = self.Menubutton_1_StringVar.trace_variable("w", self.Menubutton_1_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Notebook_2" def make_Notebook_2(self, frame): """ Notebook: at LabelFrame_2(2,1)""" self.Notebook_2 = Notebook ( frame , width="400", height="300") self.Notebook_2.grid(row=2, column=1) # >>>>>>insert any user code below this comment for section "make_Notebook_2" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Tab_4" def make_Tab_4(self, frame): """ Tab: at Notebook_2(1,1)""" self.Tab_4 = Frame( frame ) self.Notebook_2.add( self.Tab_4, text="Tab_4" ) # >>>>>>insert any user code below this comment for section "make_Tab_4" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Tab_5" def make_Tab_5(self, frame): """ Tab: at Notebook_2(1,2)""" self.Tab_5 = Frame( frame ) self.Notebook_2.add( self.Tab_5, text="Tab_5" ) # >>>>>>insert any user code below this comment for section "make_Tab_5" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_RadioGroup_1" def make_RadioGroup_1(self, frame): """ RadioGroup: at Tab_4(1,1)""" self.RadioGroup_1 = LabelFrame( frame , width="60", height="50") self.RadioGroup_1.grid(row=1, column=1) # >>>>>>insert any user code below this comment for section "make_RadioGroup_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Radiobutton_1" def make_Radiobutton_1(self, frame): """ Radiobutton: 1 : at RadioGroup_1(2,1)""" self.Radiobutton_1 = Radiobutton( frame , text="Radiobutton_1", value="1", width="15", anchor="e") self.Radiobutton_1.grid(row=2, column=1) # >>>>>>insert any user code below this comment for section "make_Radiobutton_1" self.Radiobutton_1.configure(variable=self.RadioGroup_1_StringVar) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Radiobutton_2" def make_Radiobutton_2(self, frame): """ Radiobutton: 2 : at RadioGroup_1(3,1)""" self.Radiobutton_2 = Radiobutton( frame , text="Radiobutton_2", value="2", width="15") self.Radiobutton_2.grid(row=3, column=1) # >>>>>>insert any user code below this comment for section "make_Radiobutton_2" self.Radiobutton_2.configure(variable=self.RadioGroup_1_StringVar) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Radiobutton_3" def make_Radiobutton_3(self, frame): """ Radiobutton: 3 : at RadioGroup_1(4,1)""" self.Radiobutton_3 = Radiobutton( frame , text="Radiobutton_3", value="3", width="15") self.Radiobutton_3.grid(row=4, column=1) # >>>>>>insert any user code below this comment for section "make_Radiobutton_3" self.Radiobutton_3.configure(variable=self.RadioGroup_1_StringVar) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Radiobutton_4" def make_Radiobutton_4(self, frame): """ Radiobutton: 4 : at RadioGroup_1(5,1)""" self.Radiobutton_4 = Radiobutton( frame , text="Radiobutton_4", value="4", width="15") self.Radiobutton_4.grid(row=5, column=1) # >>>>>>insert any user code below this comment for section "make_Radiobutton_4" self.Radiobutton_4.configure(variable=self.RadioGroup_1_StringVar) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Scale_1" def make_Scale_1(self, frame): """ Scale: 2.5 to 7.5 : at Tab_5(2,1)""" self.Scale_1 = Scale( frame , digits="3", tickinterval="1", to="7.5", from_="2.5", resolution=".5") self.Scale_1.grid(row=2, column=1) self.Scale_1_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Scale_1" self.Scale_1.configure(variable=self.Scale_1_StringVar) self.Scale_1_StringVar_traceName = self.Scale_1_StringVar.trace_variable("w", self.Scale_1_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Spinbox_1" def make_Spinbox_1(self, frame): """ Spinbox: 1 to 10 : at Tab_5(3,1)""" self.Spinbox_1 = Spinbox( frame , to="10", text="Spinbox_1", width="15", from_="1") self.Spinbox_1.grid(row=3, column=1) self.Spinbox_1_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Spinbox_1" self.Spinbox_1.configure(textvariable=self.Spinbox_1_StringVar, to="10", from_="1") self.Spinbox_1_StringVar.set("1") self.Spinbox_1_StringVar_traceName = self.Spinbox_1_StringVar.trace_variable("w", self.Spinbox_1_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Button_2" def make_Button_2(self, frame): """ Button: at Tab_3(3,1)""" self.Button_2 = Button( frame , text="Button_2", width="15") self.Button_2.grid(row=3, column=1) # >>>>>>insert any user code below this comment for section "make_Button_2" self.Button_2.bind("<ButtonRelease-1>", self.Button_2_Click) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Text_1" def make_Text_1(self, frame): """ Text: at Tab_3(2,1)""" lbframe = Frame( frame ) self.Text_1_frame = lbframe vbar=Scrollbar(lbframe, orient=VERTICAL) self.Text_1 = Text(lbframe, width="40", height="12", yscrollcommand=vbar.set) vbar.config(command=self.Text_1.yview) vbar.grid(row=0, column=1, sticky='ns') self.Text_1.grid(row=0, column=0) self.Text_1_frame.grid(row=2, column=1) # >>>>>>insert any user code below this comment for section "make_Text_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Treeview_1" def make_Treeview_1(self, frame): """ Treeview: at Tab_3(2,2)""" self.Treeview_1 = Treeview( frame ) self.Treeview_1.grid(row=2, column=2) # >>>>>>insert any user code below this comment for section "make_Treeview_1" self.Treeview_1.insert('', 'end', 'widgets', text='Widget Tour') # Same thing, but inserted as first child: self.Treeview_1.insert('', 0, 'gallery', text='Treeview_1') # Inserted underneath an existing node: self.Treeview_1.insert('widgets', 'end', text='Button') self.Treeview_1.insert('widgets', 'end', text='Canvas') self.Treeview_1.insert('widgets', 'end', text='Checkbutton') self.Treeview_1.insert('widgets', 'end', text='Combobox') self.Treeview_1.insert('widgets', 'end', text='Entry') self.Treeview_1.insert('widgets', 'end', text='Frame') self.Treeview_1.insert('widgets', 'end', text='Label') self.Treeview_1.insert('widgets', 'end', text='LabelFrame') self.Treeview_1.insert('widgets', 'end', text='Listbox') self.Treeview_1.insert('widgets', 'end', text='Menubutton') self.Treeview_1.insert('widgets', 'end', text='Message') self.Treeview_1.insert('widgets', 'end', text='Notebook') self.Treeview_1.insert('widgets', 'end', text='OptionMenu') self.Treeview_1.insert('widgets', 'end', text='Progressbar') self.Treeview_1.insert('widgets', 'end', text='RadioGroup') self.Treeview_1.insert('widgets', 'end', text='Radiobutton') self.Treeview_1.insert('widgets', 'end', text='Scale') self.Treeview_1.insert('widgets', 'end', text='Separator') self.Treeview_1.insert('widgets', 'end', text='Spinbox') self.Treeview_1.insert('widgets', 'end', text='Tab') self.Treeview_1.insert('widgets', 'end', text='Text') self.Treeview_1.insert('widgets', 'end', text='Treeview') # Treeview chooses the id: id = self.Treeview_1.insert('', 'end', text='Tutorial') self.Treeview_1.insert(id, 'end', text='Tree') self.Treeview_1.bind("<ButtonRelease-1>", self.Treeview_1_Click) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Button_1_Click" def Button_1_Click(self, event): #bind method for component ID=Button_1 """ Button: at Main(1,1)""" pass # >>>>>>insert any user code below this comment for section "Button_1_Click" # replace, delete, or comment-out the following print( "executed method Button_1_Click" ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Canvas_1_Click" def Canvas_1_Click(self, event): #bind method for component ID=Canvas_1 """ Canvas: at Tab_1(1,3)""" pass # >>>>>>insert any user code below this comment for section "Canvas_1_Click" # replace, delete, or comment-out the following print( "executed method Canvas_1_Click" ) print( "clicked in canvas at x,y =",event.x,event.y ) w = int(self.Canvas_1.cget("width")) h = int(self.Canvas_1.cget("height")) self.Canvas_1.create_rectangle((2, 2, w+1, h+1), outline="blue") self.Canvas_1.create_line(0, 0, w+2, h+2, fill="red") x = int(event.x) y = int(event.y) print( "event x,y=",x,y ) self.Canvas_1.create_text(x,y, text="NE", fill="green", anchor=NE) self.Canvas_1.create_text(x,y, text="SW", fill="magenta", anchor=SW) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Listbox_1_Click" def Listbox_1_Click(self, event): #bind method for component ID=Listbox_1 """ Listbox: at LabelFrame_1(1,1)""" pass # >>>>>>insert any user code below this comment for section "Listbox_1_Click" # replace, delete, or comment-out the following print( "executed method Listbox_1_Click" ) print( "current selection(s) =",self.Listbox_1.curselection() ) labelL = [] for i in self.Listbox_1.curselection(): labelL.append( self.Listbox_1.get(i)) print( "current label(s) =",labelL ) # use self.Listbox_1.insert(0, "item zero") # self.Listbox_1.insert(index, "item i") # OR # self.Listbox_1.insert(END, "item end") # to insert items into the list box # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Button_2_Click" def Button_2_Click(self, event): #bind method for component ID=Button_2 """ Button: at Tab_3(3,1)""" pass # >>>>>>insert any user code below this comment for section "Button_2_Click" # replace, delete, or comment-out the following print( "executed method Button_2_Click" ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Treeview_1_Click" def Treeview_1_Click(self, event): #bind method for component ID=Treeview_1 """ Treeview: at Tab_3(2,2)""" pass # >>>>>>insert any user code below this comment for section "Treeview_1_Click" # replace, delete, or comment-out the following print( "executed method Treeview_1_Click" ) curItem = self.Treeview_1.focus() print( "current Treeview item(s) =",self.Treeview_1.item( curItem ) ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Checkbutton_2_StringVar_traceName" def Checkbutton_2_StringVar_Callback(self, varName, index, mode): """ Checkbutton: at Frame_1(1,1)""" pass # >>>>>>insert any user code below this comment for section "Checkbutton_2_StringVar_traceName" # replace, delete, or comment-out the following print( "Checkbutton_2_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.Checkbutton_2_StringVar.get() ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Combobox_2_StringVar_traceName" def Combobox_2_StringVar_Callback(self, varName, index, mode): """ Combobox: Mine Yours Ours : at Frame_1(2,1)""" pass # >>>>>>insert any user code below this comment for section "Combobox_2_StringVar_traceName" # replace, delete, or comment-out the following print( "Combobox_2_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.Combobox_2_StringVar.get() ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Entry_2_StringVar_traceName" def Entry_2_StringVar_Callback(self, varName, index, mode): """ Entry: at Frame_1(3,1)""" pass # >>>>>>insert any user code below this comment for section "Entry_2_StringVar_traceName" # replace, delete, or comment-out the following print( "Entry_2_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.Entry_2_StringVar.get() ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Menubutton_1_StringVar_traceName" def Menubutton_1_StringVar_Callback(self, varName, index, mode): """ Menubutton: at LabelFrame_2(1,1)""" pass # >>>>>>insert any user code below this comment for section "Menubutton_1_StringVar_traceName" # replace, delete, or comment-out the following print( "Menubutton_1_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.Menubutton_1_StringVar.get() ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Scale_1_StringVar_traceName" def Scale_1_StringVar_Callback(self, varName, index, mode): """ Scale: 2.5 to 7.5 : at Tab_5(2,1)""" pass # >>>>>>insert any user code below this comment for section "Scale_1_StringVar_traceName" # replace, delete, or comment-out the following print( "Scale_1_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.Scale_1_StringVar.get() ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Spinbox_1_StringVar_traceName" def Spinbox_1_StringVar_Callback(self, varName, index, mode): """ Spinbox: 1 to 10 : at Tab_5(3,1)""" pass # >>>>>>insert any user code below this comment for section "Spinbox_1_StringVar_traceName" # replace, delete, or comment-out the following print( "Spinbox_1_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.Spinbox_1_StringVar.get() ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "RadioGroup_1_StringVar_traceName" def RadioGroup_1_StringVar_Callback(self, varName, index, mode): """ RadioGroup: at Tab_4(1,1)""" pass # >>>>>>insert any user code below this comment for section "RadioGroup_1_StringVar_traceName" # replace, delete, or comment-out the following print( "RadioGroup_1_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.RadioGroup_1_StringVar.get() )
class _auto_detect(_Dialog): def body(self, master): dialogframe = Frame(master, width=741, height=560) self.dialogframe = dialogframe dialogframe.pack() self.make_Canvas_1( self.dialogframe ) # Canvas: at Main(2,2) self.make_Frame_1( self.dialogframe ) # Frame: at Main(2,1) self.make_Button_1( self.Frame_1 ) # Button: Generate Points : at Frame_1(8,1) self.make_Checkbutton_1( self.Frame_1 ) # Checkbutton: Replace or Add : at Frame_1(10,1) self.make_Checkbutton_2( self.Frame_1 ) # Checkbutton: Show Blur : at Frame_1(9,1) self.make_Entry_1( self.Frame_1 ) # Entry: 0.02 : at Frame_1(5,1) self.make_Label_1( self.Frame_1 ) # Label: Blur Radius : at Frame_1(0,1) self.make_Label_2( self.Frame_1 ) # Label: #Generated Points : at Frame_1(2,1) self.make_Label_3( self.Frame_1 ) # Label: Explore Fraction : at Frame_1(4,1) self.make_Label_4( self.Frame_1 ) # Label: Masking Line Width : at Frame_1(6,1) self.make_Label_5( self.Frame_1 ) # Label: Point Opacity : at Frame_1(11,1) self.make_Spinbox_1( self.Frame_1 ) # Spinbox: Blur Radius : at Frame_1(1,1) self.make_Spinbox_2( self.Frame_1 ) # Spinbox: 3 to 1000 : at Frame_1(3,1) self.make_Spinbox_3( self.Frame_1 ) # Spinbox: 1 to 9 : at Frame_1(7,1) self.make_Spinbox_4( self.Frame_1 ) # Spinbox: 1 to 255 : at Frame_1(12,1) self.make_Text_1( self.Frame_1 ) # Text: at Frame_1(13,1) self.dialogframe.rowconfigure(2, weight=1) self.dialogframe.rowconfigure(13, weight=1) self.dialogframe.columnconfigure(2, weight=1) # >>>>>>insert any user code below this comment for section "top_of_init" self.x, self.y, self.w, self.h = -1,-1,-1,-1 self.dw_canv = -1 self.dh_canv = -1 self.need_resize = False self.d_frac = 0.02 # explore fraction normal to 1st curve estimate self.blur_radius = 3 # GaussianBlur radius self.num_points = 12 # number of point intervals to generate self.masking_line_size = 9 # used in (Will be kept odd) self.opacity = 155 # for points on drawing self.calc_pointL = [] # list of calculated points # bind master to <Configure> in order to handle any resizing, etc. # postpone self.dialog_master.bind("<Configure>", self.Master_Configure) self.initComplete = 0 self.dialog_master = master self.dialog_master.bind('<Enter>', self.bindConfigure) # Mouse Wheel for Zooming in and out self.Canvas_1.bind("<MouseWheel>",self.MouseWheelHandler) # Windows Binding self.Canvas_1.bind("<Button-4>",self.MouseWheelHandler) # Linux Binding self.Canvas_1.bind("<Button-5>",self.MouseWheelHandler) # Linux Binding self.is_dragging = False self.last_right_click_pos = (0,0) # any action calling Canvas_Find_Closest will set self.last_hover_pos = (0,0) self.in_canvas = False self.Canvas_1.bind("<Button-3>", self.Canvas_Begin_End_Drag) self.Canvas_1.bind("<B3-Motion>", self.Canvas_Drag_Axes) self.Canvas_1.bind("<Motion>", self.Canvas_Hover) self.Canvas_1.bind("<Enter>", self.Canvas_Enter) self.Canvas_1.bind("<Leave>", self.Canvas_Leave) self.resizable(1,1) # Linux may not respect this self.Canvas_1.focus_set() self.PA = deepcopy( self.dialogOptions['PA'] ) self.PA_img = self.PA.img self.pointL = deepcopy( self.dialogOptions['pointL'] ) self.fill_canvas() def fill_canvas(self): try: self.Canvas_1.delete("all") except: pass self.build_PA_img() self.photo_image = self.PA.get_tk_photoimage(greyscale=False, text='') self.Canvas_1.create_image(0,0, anchor=NW, image=self.photo_image ) def build_PA_img(self): self.calc_pointL = [] # start with empty list of calculated points gray = self.PA_img.convert("L") w,h = self.PA_img.size rgb = Image.new('RGB', (w,h), (0,0,0)) show_gray = Image.new('L', (w,h), 255) gray_mask = Image.new('L', (w,h), 0) rgb_mask = Image.new('L', (w,h), 0) draw_rgb = ImageDraw.Draw( rgb ) draw_gray_mask = ImageDraw.Draw( gray_mask ) draw_rgb_mask = ImageDraw.Draw( rgb_mask ) pLL = [(P.x,P.y,P.fi,P.fj) for P in self.pointL] pLL.sort() # make sure increasing x fiL = [] fjL = [] fsL = [0.0] # approximate length along curve for i,pL in enumerate(pLL): #print(pL) x,y,fi,fj = pL fiL.append( fi ) fjL.append( fj ) if i>0: s = fsL[-1] + ((fi-fiL[-2])**2 + (fj-fjL[-2])**2)**0.5 fsL.append( s ) #print( 'fsL=',fsL ) s_total = fsL[-1] # build interplators along 1st estimate of curve fjterp = InterpProp( fiL, fjL, extrapOK=True ) fi_sterp = InterpProp( fsL, fiL, extrapOK=True ) # draw approximate-interpolated curve ijL = [] # list of (i,j) for draw.line for i in range(101): s = i*s_total / 100.0 fi = fi_sterp( s ) fj = fjterp( fi ) ijL.append( (int( w * fi ), int( h * fj )) ) #draw_rgb.line( ijL, width=3, fill='red' ) #draw_rgb_mask.line( ijL, width=3, fill=self.opacity ) # try to eliminate line imperfections (holes in wide lines.) for i in [-1,0,1]: for j in [-1,0,1]: ij_newL = [(i+ii,j+jj) for ii,jj in ijL] draw_gray_mask.line( ij_newL, width=self.masking_line_size, fill=255 ) # show data points for (x,y,fi,fj) in pLL: f_ipos = w * fi i = int( f_ipos ) f_jpos = h * fj j = int( f_jpos ) draw_rgb.rectangle(((i-4,j-4),(i+4,j+4)), fill ="blue", outline ="cyan") draw_rgb_mask.rectangle(((i-4,j-4),(i+4,j+4)), fill=self.opacity, outline =self.opacity) # show normal aspect = float(w) / float(h) #print('aspect=',aspect) show_gray.paste( gray, mask=gray_mask ) show_gray = show_gray.filter( ImageFilter.GaussianBlur(radius=self.blur_radius ) ) d = self.d_frac Npts = self.num_points for i in range(Npts + 1): s = i*s_total / float(Npts) fi = fi_sterp( s ) fj = fjterp( fi ) slope = -fjterp.deriv( fi ) # negative since fj=0 is at top #print(fi, fj, slope) try: normal = -1.0 / slope except: normal = 100.0 # any non-overflow big number should do. dfj = normal * d dfi = d / aspect mult = d / ( dfj**2 + dfi**2 )**0.5 dfj *= mult dfi *= mult fi_1 = fi - dfi fi_2 = fi + dfi fj_1 = fj + dfj fj_2 = fj - dfj i1 = int( fi_1 * w) j1 = int( fj_1 * h) i2 = int( fi_2 * w) j2 = int( fj_2 * h) draw_rgb.line( ((i1,j1),(i2,j2)), width=3, fill='magenta' ) draw_rgb_mask.line( ((i1,j1),(i2,j2)), width=3, fill=self.opacity ) #draw_rgb.rectangle(((i1-4,j1-4),(i1+4,j1+4)), fill ="blue", outline ="cyan") # get 1D color array for edge-finding. (FROM show_gray) def get_ave_color( fi, fj ): i1 = int( fi * w ) j1 = int( fj * h ) c11 = show_gray.getpixel( (i1,j1) ) return c11 oneDL = [] fi_oneDL = [] fj_oneDL = [] Nsteps = 100 for n in range(Nsteps+1): fi = fi_1 + n*dfi*2 / Nsteps fj = fj_1 - n*dfj*2 / Nsteps oneDL.append( get_ave_color( fi, fj ) ) fi_oneDL.append( fi ) fj_oneDL.append( fj ) gfilt_oneDL = gaussian_filter1d( oneDL, Nsteps/30.0 ) # take the darkest points to find approximate center of line max_v = gfilt_oneDL.max() min_v = gfilt_oneDL.min() r = max_v - min_v cutoff = min_v + (max_v - min_v)*0.1 minL = np.where(gfilt_oneDL <= cutoff )[0] #print( 'minL =', minL ) # clamp iave into range of 0 to len(fi_oneDL)-1 #iave = min( len(fi_oneDL)-1, max(0,np.argmin( gfilt_oneDL ))) iave = int( sum(minL) / len(minL) ) iave = min( len(fi_oneDL)-1, max(0,iave)) fi = fi_oneDL[ iave ] fj = fj_oneDL[ iave ] # use get_xy_at_fifj(self, fi, fj) in Digiplot code #x = self.PA.x_origin + (self.PA.xmax-self.PA.x_origin)*(fi-self.PA.fi_origin)/(self.PA.fimax-self.PA.fi_origin) #y = self.PA.y_origin + (self.PA.ymax-self.PA.y_origin)*(fj-self.PA.fj_origin)/(self.PA.fjmax-self.PA.fj_origin) x,y = self.PA.get_xy_at_fifj( fi, fj ) if iave<Nsteps/4 or iave>Nsteps*3/4: print('Rejected fi=%g, fj=%g, x=%g, y=%g'%(fi,fj,x,y)) else: f_ipos = w * fi i = int( f_ipos ) f_jpos = h * fj j = int( f_jpos ) draw_rgb.rectangle(((i-4,j-4),(i+4,j+4)), fill='green', outline ="green") draw_rgb_mask.rectangle(((i-4,j-4),(i+4,j+4)), fill=self.opacity, outline =self.opacity) self.calc_pointL.append( (x,y, fi,fj) ) # plot selected curve fiL = [] fjL = [] fsL = [0.0] # approximate length along curve for i,pL in enumerate(self.calc_pointL): #print(pL) x,y,fi,fj = pL fiL.append( fi ) fjL.append( fj ) if i>0: s = fsL[-1] + ((fi-fiL[-2])**2 + (fj-fjL[-2])**2)**0.5 fsL.append( s ) s_total = fsL[-1] # build interplators along curve fjterp = InterpProp( fiL, fjL, extrapOK=True ) fi_sterp = InterpProp( fsL, fiL, extrapOK=True ) # draw curve ijL = [] # list of (i,j) for draw.line for i in range(101): s = i*s_total / 100.0 fi = fi_sterp( s ) fj = fjterp( fi ) ijL.append( (int( w * fi ), int( h * fj )) ) draw_rgb.line( ijL, width=3, fill='red' ) draw_rgb_mask.line( ijL, width=3, fill=self.opacity ) # make rgb image for display to user if self.Checkbutton_2_StringVar.get() == 'yes': show_img = show_gray.convert("RGBA") else: show_img = gray.convert("RGBA") show_img.paste(rgb, mask=rgb_mask) self.PA.img = show_img def MouseWheelHandler(self, event): #print('MouseWheelHandler event.num =', event.num) if event.num == 5 or event.delta < 0: result = -1 #self.PA.zoom_in(zoom_factor=0.1) self.PA.zoom_into_ij(event.x, event.y, zoom_factor=0.1) else: result = 1 #self.PA.zoom_out(zoom_factor=0.1) self.PA.zoom_out_from_ij(event.x, event.y, zoom_factor=0.1) self.fill_canvas() def Canvas_Begin_End_Drag(self, event): self.is_dragging = not self.is_dragging ix = int(event.x) iy = int(event.y) self.last_right_click_pos = (ix, iy) def Canvas_Drag_Axes(self, event): di = self.last_right_click_pos[0] - event.x dj = self.last_right_click_pos[1] - event.y self.PA.adjust_offset(di, dj) self.last_right_click_pos = (event.x, event.y) self.fill_canvas() def Canvas_Enter(self, event): if self.dw_canv > 0 and self.need_resize: #print('Resizing Canvas',w-self.dw_canv, h-self.dh_canv) self.Canvas_1.config(width=self.w-self.dw_canv, height=self.h-self.dh_canv) self.PA.set_canvas_wh(self.w-self.dw_canv, self.h-self.dh_canv) #self.fill_canvas() self.need_resize = False self.in_canvas = True self.fill_canvas() def Canvas_Leave(self, event): self.in_canvas = False self.fill_canvas() def Canvas_Hover(self, event): self.last_hover_pos = (event.x, event.y) self.fill_canvas() def bindConfigure(self, event): if not self.initComplete: #print('Init Master_Configure') self.dialog_master.bind("<Configure>", self.Master_Configure) self.initComplete = 1 def Master_Configure(self, event): pass # replace, delete, or comment-out the following if event.widget != self.dialog_master: if self.w != -1: return #print('Master_Configure', event) x = int(self.winfo_x()) y = int(self.winfo_y()) w = int(self.winfo_width()) h = int(self.winfo_height()) if (self.x, self.y, self.w, self.h) == (-1,-1,-1,-1): self.x, self.y, self.w, self.h = x,y,w,h w_canv = int( self.Canvas_1.winfo_width() ) h_canv = int( self.Canvas_1.winfo_height() ) self.dw_canv = w - w_canv self.dh_canv = h - h_canv if self.w!=w or self.h!=h: #print( "Master reconfigured... make resize adjustments") self.w=w self.h=h self.need_resize = True #if self.dw_canv > 0: # #print('Resizing Canvas',w-self.dw_canv, h-self.dh_canv) # self.Canvas_1.config(width=w-self.dw_canv, height=h-self.dh_canv) # self.PA.set_canvas_wh(w-self.dw_canv, h-self.dh_canv) # self.fill_canvas() # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Canvas_1" def make_Canvas_1(self, frame): """ Canvas: at Main(2,2)""" self.Canvas_1 = Canvas( frame , width="600", height="500") self.Canvas_1.grid(row=2, column=2, sticky="nsew") # >>>>>>insert any user code below this comment for section "make_Canvas_1" self.Canvas_1.config(bg='#ffffcc') self.Canvas_1.bind("<ButtonRelease-1>", self.Canvas_1_Click) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Frame_1" def make_Frame_1(self, frame): """ Frame: at Main(2,1)""" self.Frame_1 = Frame( frame , width="60", height="50") self.Frame_1.grid(row=2, column=1, sticky="ns") # >>>>>>insert any user code below this comment for section "make_Frame_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Button_1" def make_Button_1(self, frame): """ Button: Generate Points : at Frame_1(8,1)""" self.Button_1 = Button( frame , text="Generate Points", width="15") self.Button_1.grid(row=8, column=1) # >>>>>>insert any user code below this comment for section "make_Button_1" self.Button_1.bind("<ButtonRelease-1>", self.Button_1_Click) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Checkbutton_1" def make_Checkbutton_1(self, frame): """ Checkbutton: Replace or Add : at Frame_1(10,1)""" self.Checkbutton_1 = Checkbutton( frame , text="Replace or Add", width="15", justify="left", anchor="w") self.Checkbutton_1.grid(row=10, column=1, sticky="w") self.Checkbutton_1_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Checkbutton_1" self.Checkbutton_1.configure(variable=self.Checkbutton_1_StringVar, onvalue="yes", offvalue="no") self.Checkbutton_1_StringVar.set("yes") self.Checkbutton_1_StringVar_traceName = self.Checkbutton_1_StringVar.trace_variable("w", self.Checkbutton_1_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Checkbutton_2" def make_Checkbutton_2(self, frame): """ Checkbutton: Show Blur : at Frame_1(9,1)""" self.Checkbutton_2 = Checkbutton( frame , text="Show Blur", width="15", justify="left", anchor="w") self.Checkbutton_2.grid(row=9, column=1, sticky="w") self.Checkbutton_2_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Checkbutton_2" self.Checkbutton_2.configure(variable=self.Checkbutton_2_StringVar, onvalue="yes", offvalue="no") self.Checkbutton_2_StringVar.set("no") self.Checkbutton_2_StringVar_traceName = self.Checkbutton_2_StringVar.trace_variable("w", self.Checkbutton_2_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Entry_1" def make_Entry_1(self, frame): """ Entry: 0.02 : at Frame_1(5,1)""" self.Entry_1 = Entry( frame , width="17") self.Entry_1.grid(row=5, column=1, sticky="e") self.Entry_1_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Entry_1" self.Entry_1_StringVar.set( '0.02' ) self.Entry_1.configure(textvariable=self.Entry_1_StringVar) self.Entry_1_StringVar_traceName = self.Entry_1_StringVar.trace_variable("w", self.Entry_1_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Label_1" def make_Label_1(self, frame): """ Label: Blur Radius : at Frame_1(0,1)""" self.Label_1 = Label( frame , text="Blur Radius", width="15", anchor="w", justify="left") self.Label_1.grid(row=0, column=1, sticky="w") # >>>>>>insert any user code below this comment for section "make_Label_1" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Label_2" def make_Label_2(self, frame): """ Label: #Generated Points : at Frame_1(2,1)""" self.Label_2 = Label( frame , text="#Point Intervals", width="15", anchor="w", justify="left") self.Label_2.grid(row=2, column=1, sticky="w") # >>>>>>insert any user code below this comment for section "make_Label_2" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Label_3" def make_Label_3(self, frame): """ Label: Explore Fraction : at Frame_1(4,1)""" self.Label_3 = Label( frame , text="Explore Fraction", width="15", anchor="w", justify="left") self.Label_3.grid(row=4, column=1, sticky="w") # >>>>>>insert any user code below this comment for section "make_Label_3" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Label_4" def make_Label_4(self, frame): """ Label: Masking Line Width : at Frame_1(6,1)""" self.Label_4 = Label( frame , text="Masking Line Width", width="15", anchor="w", justify="left") self.Label_4.grid(row=6, column=1, sticky="w") # >>>>>>insert any user code below this comment for section "make_Label_4" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Label_5" def make_Label_5(self, frame): """ Label: Point Opacity : at Frame_1(11,1)""" self.Label_5 = Label( frame , text="Point Opacity", width="15", anchor="w", justify="left") self.Label_5.grid(row=11, column=1, sticky="w") # >>>>>>insert any user code below this comment for section "make_Label_5" # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Spinbox_1" def make_Spinbox_1(self, frame): """ Spinbox: Blur Radius : at Frame_1(1,1)""" self.Spinbox_1 = Spinbox( frame , from_="1", to="10", text="Blur Radius", width="15") self.Spinbox_1.grid(row=1, column=1, sticky="e") self.Spinbox_1_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Spinbox_1" self.Spinbox_1.configure(textvariable=self.Spinbox_1_StringVar, from_="1", to="10") self.Spinbox_1_StringVar.set("3") self.Spinbox_1_StringVar_traceName = self.Spinbox_1_StringVar.trace_variable("w", self.Spinbox_1_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Spinbox_2" def make_Spinbox_2(self, frame): """ Spinbox: 3 to 1000 : at Frame_1(3,1)""" self.Spinbox_2 = Spinbox( frame , from_="3", to="1000", text="Spinbox_2", width="15") self.Spinbox_2.grid(row=3, column=1, sticky="e") self.Spinbox_2_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Spinbox_2" self.Spinbox_2.configure(textvariable=self.Spinbox_2_StringVar, from_="3", to="1000") self.Spinbox_2_StringVar.set("12") self.Spinbox_2_StringVar_traceName = self.Spinbox_2_StringVar.trace_variable("w", self.Spinbox_2_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Spinbox_3" def make_Spinbox_3(self, frame): """ Spinbox: 1 to 9 : at Frame_1(7,1)""" self.Spinbox_3 = Spinbox( frame , from_="1", to="9", text="Spinbox_3", width="15") self.Spinbox_3.grid(row=7, column=1, sticky="e") self.Spinbox_3_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Spinbox_3" self.Spinbox_3.configure(textvariable=self.Spinbox_3_StringVar, from_="1", to="25") self.Spinbox_3_StringVar.set("9") self.Spinbox_3_StringVar_traceName = self.Spinbox_3_StringVar.trace_variable("w", self.Spinbox_3_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Spinbox_4" def make_Spinbox_4(self, frame): """ Spinbox: 1 to 255 : at Frame_1(12,1)""" self.Spinbox_4 = Spinbox( frame , from_="1", to="255", text="Spinbox_4", width="15") self.Spinbox_4.grid(row=12, column=1, sticky="e") self.Spinbox_4_StringVar = StringVar() # >>>>>>insert any user code below this comment for section "make_Spinbox_4" self.Spinbox_4.configure(textvariable=self.Spinbox_4_StringVar, from_="10", to="255") self.Spinbox_4_StringVar.set("155") self.Spinbox_4_StringVar_traceName = self.Spinbox_4_StringVar.trace_variable("w", self.Spinbox_4_StringVar_Callback) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "make_Text_1" def make_Text_1(self, frame): """ Text: at Frame_1(13,1)""" self.Text_1 = Text( frame , width="15", height="15") self.Text_1.grid(row=13, column=1, sticky="ns") # >>>>>>insert any user code below this comment for section "make_Text_1" self.Text_1 = Text( frame , width="15") # redefine w/o height attribute. self.Text_1.grid(row=13, column=1, sticky="ns") self.Text_1.insert('1.0', text_warn) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Canvas_1_Click" def Canvas_1_Click(self, event): #bind method for component ID=Canvas_1 """ Canvas: at Main(2,2)""" pass # >>>>>>insert any user code below this comment for section "Canvas_1_Click" # replace, delete, or comment-out the following #print( "executed method Canvas_1_Click" ) #print( "clicked in canvas at x,y =",event.x,event.y ) w = int(self.Canvas_1.cget("width")) h = int(self.Canvas_1.cget("height")) #self.Canvas_1.create_rectangle((2, 2, w+1, h+1), outline="blue") #self.Canvas_1.create_line(0, 0, w+2, h+2, fill="red") #x = int(event.x) #y = int(event.y) #print( "event x,y=",x,y ) #self.Canvas_1.create_text(x,y, text="NE", fill="green", anchor=NE) #self.Canvas_1.create_text(x,y, text="SW", fill="magenta", anchor=SW) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Button_1_Click" def Button_1_Click(self, event): #bind method for component ID=Button_1 """ Button: Generate Points : at Frame_1(8,1)""" pass # >>>>>>insert any user code below this comment for section "Button_1_Click" # replace, delete, or comment-out the following #print( "executed method Button_1_Click" ) self.fill_canvas() # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Checkbutton_1_StringVar_traceName" def Checkbutton_1_StringVar_Callback(self, varName, index, mode): """ Checkbutton: Replace or Add : at Frame_1(10,1)""" pass # >>>>>>insert any user code below this comment for section "Checkbutton_1_StringVar_traceName" # replace, delete, or comment-out the following #print( "Checkbutton_1_StringVar_Callback varName, index, mode",varName, index, mode ) #print( " new StringVar value =",self.Checkbutton_1_StringVar.get() ) self.Text_1.delete('1.0', END) if self.Checkbutton_1_StringVar.get() == 'yes': self.Text_1.insert('1.0', text_warn) else: self.Text_1.insert('1.0', text_info) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Checkbutton_2_StringVar_traceName" def Checkbutton_2_StringVar_Callback(self, varName, index, mode): """ Checkbutton: Show Blur : at Frame_1(9,1)""" pass # >>>>>>insert any user code below this comment for section "Checkbutton_2_StringVar_traceName" # replace, delete, or comment-out the following #print( "Checkbutton_2_StringVar_Callback varName, index, mode",varName, index, mode ) #print( " new StringVar value =",self.Checkbutton_2_StringVar.get() ) self.fill_canvas() # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Entry_1_StringVar_traceName" def Entry_1_StringVar_Callback(self, varName, index, mode): """ Entry: 0.02 : at Frame_1(5,1)""" pass # >>>>>>insert any user code below this comment for section "Entry_1_StringVar_traceName" # replace, delete, or comment-out the following #print( "Entry_1_StringVar_Callback varName, index, mode",varName, index, mode ) #print( " new StringVar value =",self.Entry_1_StringVar.get() ) try: self.d_frac = float( self.Entry_1_StringVar.get() ) except: self.d_frac = 0.02 # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Spinbox_1_StringVar_traceName" def Spinbox_1_StringVar_Callback(self, varName, index, mode): """ Spinbox: Blur Radius : at Frame_1(1,1)""" pass # >>>>>>insert any user code below this comment for section "Spinbox_1_StringVar_traceName" # replace, delete, or comment-out the following #print( "Spinbox_1_StringVar_Callback varName, index, mode",varName, index, mode ) #print( " new StringVar value =",self.Spinbox_1_StringVar.get() ) try: self.blur_radius = int( self.Spinbox_1_StringVar.get() ) except: self.blur_radius = 3 self.fill_canvas() # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Spinbox_2_StringVar_traceName" def Spinbox_2_StringVar_Callback(self, varName, index, mode): """ Spinbox: 3 to 1000 : at Frame_1(3,1)""" pass # >>>>>>insert any user code below this comment for section "Spinbox_2_StringVar_traceName" # replace, delete, or comment-out the following #print( "Spinbox_2_StringVar_Callback varName, index, mode",varName, index, mode ) #print( " new StringVar value =",self.Spinbox_2_StringVar.get() ) try: self.num_points = int( self.Spinbox_2_StringVar.get() ) except: self.num_points = 20 self.fill_canvas() # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Spinbox_3_StringVar_traceName" def Spinbox_3_StringVar_Callback(self, varName, index, mode): """ Spinbox: 1 to 9 : at Frame_1(7,1)""" pass # >>>>>>insert any user code below this comment for section "Spinbox_3_StringVar_traceName" # replace, delete, or comment-out the following #print( "Spinbox_3_StringVar_Callback varName, index, mode",varName, index, mode ) #print( " new StringVar value =",self.Spinbox_3_StringVar.get() ) MAX_SIZE = 25 new_val = int( self.Spinbox_3_StringVar.get() ) if new_val %2 == 1: self.masking_line_size = new_val elif new_val > self.masking_line_size and new_val < MAX_SIZE: self.masking_line_size = new_val + 1 self.Spinbox_3_StringVar.set( new_val+1 ) elif new_val < self.masking_line_size and new_val > 0: self.masking_line_size = new_val - 1 self.Spinbox_3_StringVar.set( new_val-1 ) elif new_val >= MAX_SIZE: self.masking_line_size = MAX_SIZE self.Spinbox_3_StringVar.set( MAX_SIZE ) #print('self.masking_line_size =',self.masking_line_size) self.fill_canvas() # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "Spinbox_4_StringVar_traceName" def Spinbox_4_StringVar_Callback(self, varName, index, mode): """ Spinbox: 1 to 255 : at Frame_1(12,1)""" pass # >>>>>>insert any user code below this comment for section "Spinbox_4_StringVar_traceName" # replace, delete, or comment-out the following print( "Spinbox_4_StringVar_Callback varName, index, mode",varName, index, mode ) print( " new StringVar value =",self.Spinbox_4_StringVar.get() ) self.opacity = int( self.Spinbox_4_StringVar.get() ) # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "dialog_validate" def validate(self): self.result = {} # return a dictionary of results self.result["Checkbutton_1"] = self.Checkbutton_1_StringVar.get() self.result["Checkbutton_2"] = self.Checkbutton_2_StringVar.get() self.result["Entry_1"] = self.Entry_1_StringVar.get() self.result["Spinbox_1"] = self.Spinbox_1_StringVar.get() self.result["Spinbox_2"] = self.Spinbox_2_StringVar.get() self.result["Spinbox_3"] = self.Spinbox_3_StringVar.get() self.result["Spinbox_4"] = self.Spinbox_4_StringVar.get() # >>>>>>insert any user code below this comment for section "dialog_validate" # set values in "self.result" dictionary for return # for example... # self.result["age"] = self.Entry_2_StringVar.get() self.result["replace_pts"] = self.Checkbutton_1_StringVar.get() self.result["calc_pointL"] = self.calc_pointL return 1 # TkGridGUI generated code. DO NOT EDIT THE FOLLOWING. section "end" def apply(self): pass
def __top_frame(self): """ Create top frame content """ self._selected_modulation = StringVar(self._tk_obj) self._selected_channel = StringVar(self._tk_obj) self._selected_sync_mode = StringVar(self._tk_obj) self._cbx_manchester_value = IntVar(self._tk_obj) frame = Frame(self._tk_obj, borderwidth=1, relief=SUNKEN, bg='#fff') frame.grid(column=0, row=0, padx=15, pady=15, sticky=W + E) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) # headline lab_section = Label(frame, text="Default RF Settings") lab_section.grid(columnspan=6, row=0, padx=5, pady=5, sticky=W + E) lab_section.configure(font=self.__FONT_HEADLINE) # frequency lab_frequency = Label(frame, text='Frequency') lab_frequency.grid(column=0, row=1, padx=5, pady=5, sticky=E) lab_frequency.configure(font=self.__FONT_STYLE) self._ety_frequency = Entry(frame) self._ety_frequency.grid(column=1, row=1, padx=5, pady=5, sticky=W) self._ety_frequency.configure(font=self.__FONT_STYLE) value_frequency = self.rf_object.getFreq() self._ety_frequency.insert(0, int(value_frequency[0])) # modulation lab_modulation = Label(frame, text='Modulation') lab_modulation.grid(column=0, row=2, padx=5, pady=5, sticky=E) lab_modulation.configure(font=self.__FONT_STYLE) opm_modulation = OptionMenu(frame, self._selected_modulation, *self.__MODULATION_OPTIONS) opm_modulation.grid(column=1, row=2, padx=5, pady=5, sticky=W) opm_modulation.configure(font=self.__FONT_STYLE) value_modulation = self.rf_object.getMdmModulation() if value_modulation == 0: self._selected_modulation.set(self.__MODULATION_OPTIONS[1]) elif value_modulation == 16: self._selected_modulation.set(self.__MODULATION_OPTIONS[2]) elif value_modulation == 48: self._selected_modulation.set(self.__MODULATION_OPTIONS[3]) elif value_modulation == 112: self._selected_modulation.set(self.__MODULATION_OPTIONS[4]) else: self._selected_modulation.set(self.__MODULATION_OPTIONS[0]) # channel lab_channel = Label(frame, text='Channel') lab_channel.grid(column=0, row=3, padx=5, pady=5, sticky=E) lab_channel.configure(font=self.__FONT_STYLE) sbx_channel = Spinbox(frame, state='readonly') sbx_channel.grid(column=1, row=3, padx=5, pady=5, sticky=W) sbx_channel.configure(font=self.__FONT_STYLE) self._selected_channel.set(self.rf_object.getChannel()) sbx_channel.configure(from_=0, to=10, increment=1, textvariable=self._selected_channel) # baud rate lab_baud = Label(frame, text='Baud Rate') lab_baud.grid(column=2, row=1, padx=5, pady=5, sticky=E) lab_baud.configure(font=self.__FONT_STYLE) self._ety_baud = Entry(frame) self._ety_baud.grid(column=3, row=1, padx=5, pady=5, sticky=W) self._ety_baud.configure(font=self.__FONT_STYLE) self._ety_baud.insert(0, int(self.rf_object.getMdmDRate())) # deviation lab_deviation = Label(frame, text='Deviation') lab_deviation.grid(column=2, row=2, padx=5, pady=5, sticky=E) lab_deviation.configure(font=self.__FONT_STYLE) self._ety_deviation = Entry(frame) self._ety_deviation.grid(column=3, row=2, padx=5, pady=5, sticky=W) self._ety_deviation.configure(font=self.__FONT_STYLE) self._ety_deviation.insert(0, int(self.rf_object.getMdmDeviatn())) self._ety_deviation.configure(state='readonly') # channel bandwidth lab_channel_bandwidth = Label(frame, text='Channel BW') lab_channel_bandwidth.grid(column=2, row=3, padx=5, pady=5, sticky=E) lab_channel_bandwidth.configure(font=self.__FONT_STYLE) self._ety_channel_bandwidth = Entry(frame) self._ety_channel_bandwidth.grid(column=3, row=3, padx=5, pady=5, sticky=W) self._ety_channel_bandwidth.configure(font=self.__FONT_STYLE) self._ety_channel_bandwidth.insert(0, int(self.rf_object.getMdmChanBW())) self._ety_channel_bandwidth.configure(state='readonly') # sync mode lab_sync_mode = Label(frame, text='Sync Mode') lab_sync_mode.grid(column=4, row=1, padx=5, pady=5, sticky=E) lab_sync_mode.configure(font=self.__FONT_STYLE) sbx_sync_mode = Spinbox(frame, state='readonly') sbx_sync_mode.grid(column=5, row=1, padx=5, pady=5, sticky=W) sbx_sync_mode.configure(font=self.__FONT_STYLE) self._selected_sync_mode.set(self.rf_object.getMdmSyncMode()) sbx_sync_mode.configure(from_=0, to=7, increment=1, textvariable=self._selected_sync_mode) # sync word lab_sync_word = Label(frame, text='Sync Word') lab_sync_word.grid(column=4, row=2, padx=5, pady=5, sticky=E) lab_sync_word.configure(font=self.__FONT_STYLE) self._ety_sync_word = Entry(frame) self._ety_sync_word.grid(column=5, row=2, padx=5, pady=5, sticky=W) self._ety_sync_word.configure(font=self.__FONT_STYLE) self._ety_sync_word.insert(0, self.rf_object.getMdmSyncWord()) self._ety_sync_word.configure(state='readonly') # channel spacing lab_channel_spacing = Label(frame, text='Channel Spacing') lab_channel_spacing.grid(column=4, row=3, padx=5, pady=5, sticky=E) lab_channel_spacing.configure(font=self.__FONT_STYLE) self._ety_channel_spacing = Entry(frame) self._ety_channel_spacing.grid(column=5, row=3, padx=5, pady=5, sticky=W) self._ety_channel_spacing.configure(font=self.__FONT_STYLE) value_channel_spacing = self.rf_object.getMdmChanSpc() self._ety_channel_spacing.insert(0, int(value_channel_spacing)) self._ety_channel_spacing.configure(state='readonly') # enable manchester lab_manchester = Label(frame, text='Enable Manchester') lab_manchester.grid(column=0, row=4, padx=5, pady=5, sticky=E) lab_manchester.configure(font=self.__FONT_STYLE) cbx_manchester = Checkbutton(frame) cbx_manchester.grid(column=1, row=4, padx=5, pady=5, sticky=W) if self.rf_object.getEnableMdmManchester() == 1: self._cbx_manchester_value.set(1) else: self._cbx_manchester_value.set(0) cbx_manchester.configure(onvalue=1, offvalue=0, variable=self._cbx_manchester_value) # save settings self._btn_save_settings = Button(frame, text='Save all Settings', command=self.__action_store_settings) self._btn_save_settings.grid(column=5, row=4, padx=5, pady=5) self._btn_save_settings.configure(font=self.__FONT_STYLE) self._btn_save_settings.bind( "<Enter>", lambda event: event.widget.config(fg='indian red')) self._btn_save_settings.bind( "<Leave>", lambda event: event.widget.config(fg='black'))
class ApplicationUi(BaseUi): __FONT_HEADLINE = ('verdana', 13, 'bold') __FONT_STYLE = ('verdana', 11, 'normal') __MODULATION_OPTIONS = [ 'Please select', 'MOD_2FSK', 'MOD_GFSK', 'MOD_ASK_OOK', 'MOD_MSK' ] def __init__(self, window_title, window_resizable, bg_color, show_menu): """ Overwrite base tkinter object :type window_title: str :param window_title: set window title :type window_resizable: bool :param window_resizable: set windows resizeable true or false :type bg_color: str :param bg_color: color code ('#ddd') :type show_menu: bool :param show_menu: set menu visible true or false """ # initialize logging and set logging level self.__logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) # all needed variables self.__sample_list = [] self.rf_object = RfCat() self._selected_modulation = None self._selected_channel = None self._selected_sync_mode = None self._ety_frequency = None self._ety_baud = None self._ety_deviation = None self._ety_channel_bandwidth = None self._ety_sync_word = None self._ety_channel_spacing = None self._cbx_manchester_value = None self._btn_save_settings = None self._ety_message_to_send = None self._sbx_repeats = None self._btn_send = None self._txt_send_status = None self._cbx_max_power_value = None self._cbx_lowball_value = None self._stx_receive_status = None self._btn_copy = None self._btn_receive = None BaseUi.__init__(self, window_title, window_resizable, bg_color, show_menu) def __add_message_hex_to_list(self, value): """ Split message HEX values into list """ for element in value: self.__sample_list.append(element) def __set_btn_disabled(self): """ Set all button state to disabled """ self._btn_send.configure(state=DISABLED) self._btn_save_settings.configure(state=DISABLED) self._btn_receive.configure(state=DISABLED) self._btn_copy.configure(state=DISABLED) def __set_btn_normal(self): """ Set all button state to normal """ self._btn_send.configure(state=NORMAL) self._btn_save_settings.configure(state=NORMAL) self._btn_receive.configure(state=NORMAL) self._btn_copy.configure(state=NORMAL) def __action_clear_message(self): """ Delete values from tkinter box """ self._ety_message_to_send.delete(0, END) def __action_store_settings(self): """ Store values from tkinter items on rfcat dongle """ self.__set_btn_disabled() # frequency frequency = int(self._ety_frequency.get()) self.__logger.info('Frequency:%i', frequency) if frequency in range(300000000, 928000000): self.rf_object.setFreq(frequency) # modulation modulation = str(self._selected_modulation.get()) self.__logger.info('Modulation:%s', modulation) if modulation == 'MOD_2FSK': self.rf_object.setMdmModulation(MOD_2FSK) elif modulation == 'MOD_GFSK': self.rf_object.setMdmModulation(MOD_GFSK) elif modulation == 'MOD_ASK_OOK': self.rf_object.setMdmModulation(MOD_ASK_OOK) elif modulation == 'MOD_MSK': self.rf_object.setMdmModulation(MOD_MSK) else: self.rf_object.setMdmModulation(MOD_2FSK) # channel channel = int(self._selected_channel.get()) self.__logger.info('Channel:%i', channel) if channel in range(0, 10): self.rf_object.setChannel(channel) # baud rate baud_rate = int(self._ety_baud.get()) self.__logger.info('BaudRate:%i', baud_rate) if baud_rate in range(210, 250000): self.rf_object.setMdmDRate(baud_rate) # deviation deviation = int(self._ety_deviation.get()) self.__logger.info('Deviation:%i', deviation) # channel bandwidth channel_bandwidth = int(self._ety_channel_bandwidth.get()) self.__logger.info('ChannelBandwidth:%i', channel_bandwidth) # sync mode sync_mode = int(self._selected_sync_mode.get()) self.__logger.info('SyncMode:%i', sync_mode) if sync_mode in range(0, 8): self.rf_object.setMdmSyncMode(sync_mode) # sync word sync_word = self._ety_sync_word.get() self.__logger.info('SyncWord:%s', sync_word) # channel spacing channel_spacing = int(self._ety_channel_spacing.get()) self.__logger.info('ChannelSpacing:%i', channel_spacing) # manchester encoding manchester_encoding = int(self._cbx_manchester_value.get()) self.__logger.info('ManchesterEncoding:%i', manchester_encoding) self.__set_btn_normal() def __action_send_signal(self): """ Send rfcat dongle signal """ self.__set_btn_disabled() self._txt_send_status.configure(state='normal') self._txt_send_status.delete('0.0', END) rf_message = str(self._ety_message_to_send.get()).strip() if not rf_message: self.__logger.info('No message found') self._txt_send_status.insert(END, 'No message to send?') else: self.__logger.info('Message:%s', rf_message) self._txt_send_status.insert(END, 'Message: ' + rf_message) # text to binary rf_bin_message = ' '.join(format(ord(x), 'b') for x in rf_message) self._txt_send_status.insert(END, "\nBinary: " + rf_bin_message) # text to hex rf_hex_message = rf_message.encode().hex() self._txt_send_status.insert(END, "\nHEX: " + rf_hex_message) # add hex to list and count bytes self.__add_message_hex_to_list(re.findall('..', rf_hex_message)) byte_count = len(self.__sample_list) self._txt_send_status.insert(END, "\nBytes: " + str(byte_count)) rf_repeats = int(self._sbx_repeats.get()) self.__logger.info('Repeats:%i', rf_repeats) self._txt_send_status.insert(END, "\nRepeats: " + str(rf_repeats)) rf_datetime = datetime.now() self.__logger.info('Date/Time:%s', rf_datetime) self._txt_send_status.insert(END, "\nDate: " + str(rf_datetime)) # convert hex to bytes and start transmit send_message = bytes.fromhex(rf_hex_message) self.rf_object.RFxmit(data=send_message, repeat=int(rf_repeats)) self.__logger.info('Transmit of message done (%i)', int(rf_repeats)) self.rf_object.setModeIDLE() self.__logger.info('set USB dongle into idle state') self._txt_send_status.insert( END, "\nResult: transmit done, USB dongle set to idle") self.__sample_list = [] self._txt_send_status.configure(state='disabled') self.__set_btn_normal() def __action_receive_signal(self): """ Store settings and start receive signal """ self.__set_btn_disabled() self._stx_receive_status.delete(0.0, END) # @ToDo: store settings of lowball/max power # @ToDo: run signal receiving into ScrolledText incl press key to stop loop output = self.rf_object.discover() print(output) self.__set_btn_normal() def __action_copy_to_clipboard(self): """ Copy content of received signal field to clipboard """ self.__set_btn_disabled() field_value = self._stx_receive_status.get("1.0", 'end-1c') if not field_value: self.__logger.info('NoValueForClipboard') else: self._tk_obj.clipboard_clear() self._tk_obj.clipboard_append(field_value) self.__set_btn_normal() def build_frames(self): """ Build all tkinter frames and start mainloop """ self.__logger.info('BuildAllFrames') self.__top_frame() self.__middle_frame() self.__bottom_frame() self.run_app() def __top_frame(self): """ Create top frame content """ self._selected_modulation = StringVar(self._tk_obj) self._selected_channel = StringVar(self._tk_obj) self._selected_sync_mode = StringVar(self._tk_obj) self._cbx_manchester_value = IntVar(self._tk_obj) frame = Frame(self._tk_obj, borderwidth=1, relief=SUNKEN, bg='#fff') frame.grid(column=0, row=0, padx=15, pady=15, sticky=W + E) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) # headline lab_section = Label(frame, text="Default RF Settings") lab_section.grid(columnspan=6, row=0, padx=5, pady=5, sticky=W + E) lab_section.configure(font=self.__FONT_HEADLINE) # frequency lab_frequency = Label(frame, text='Frequency') lab_frequency.grid(column=0, row=1, padx=5, pady=5, sticky=E) lab_frequency.configure(font=self.__FONT_STYLE) self._ety_frequency = Entry(frame) self._ety_frequency.grid(column=1, row=1, padx=5, pady=5, sticky=W) self._ety_frequency.configure(font=self.__FONT_STYLE) value_frequency = self.rf_object.getFreq() self._ety_frequency.insert(0, int(value_frequency[0])) # modulation lab_modulation = Label(frame, text='Modulation') lab_modulation.grid(column=0, row=2, padx=5, pady=5, sticky=E) lab_modulation.configure(font=self.__FONT_STYLE) opm_modulation = OptionMenu(frame, self._selected_modulation, *self.__MODULATION_OPTIONS) opm_modulation.grid(column=1, row=2, padx=5, pady=5, sticky=W) opm_modulation.configure(font=self.__FONT_STYLE) value_modulation = self.rf_object.getMdmModulation() if value_modulation == 0: self._selected_modulation.set(self.__MODULATION_OPTIONS[1]) elif value_modulation == 16: self._selected_modulation.set(self.__MODULATION_OPTIONS[2]) elif value_modulation == 48: self._selected_modulation.set(self.__MODULATION_OPTIONS[3]) elif value_modulation == 112: self._selected_modulation.set(self.__MODULATION_OPTIONS[4]) else: self._selected_modulation.set(self.__MODULATION_OPTIONS[0]) # channel lab_channel = Label(frame, text='Channel') lab_channel.grid(column=0, row=3, padx=5, pady=5, sticky=E) lab_channel.configure(font=self.__FONT_STYLE) sbx_channel = Spinbox(frame, state='readonly') sbx_channel.grid(column=1, row=3, padx=5, pady=5, sticky=W) sbx_channel.configure(font=self.__FONT_STYLE) self._selected_channel.set(self.rf_object.getChannel()) sbx_channel.configure(from_=0, to=10, increment=1, textvariable=self._selected_channel) # baud rate lab_baud = Label(frame, text='Baud Rate') lab_baud.grid(column=2, row=1, padx=5, pady=5, sticky=E) lab_baud.configure(font=self.__FONT_STYLE) self._ety_baud = Entry(frame) self._ety_baud.grid(column=3, row=1, padx=5, pady=5, sticky=W) self._ety_baud.configure(font=self.__FONT_STYLE) self._ety_baud.insert(0, int(self.rf_object.getMdmDRate())) # deviation lab_deviation = Label(frame, text='Deviation') lab_deviation.grid(column=2, row=2, padx=5, pady=5, sticky=E) lab_deviation.configure(font=self.__FONT_STYLE) self._ety_deviation = Entry(frame) self._ety_deviation.grid(column=3, row=2, padx=5, pady=5, sticky=W) self._ety_deviation.configure(font=self.__FONT_STYLE) self._ety_deviation.insert(0, int(self.rf_object.getMdmDeviatn())) self._ety_deviation.configure(state='readonly') # channel bandwidth lab_channel_bandwidth = Label(frame, text='Channel BW') lab_channel_bandwidth.grid(column=2, row=3, padx=5, pady=5, sticky=E) lab_channel_bandwidth.configure(font=self.__FONT_STYLE) self._ety_channel_bandwidth = Entry(frame) self._ety_channel_bandwidth.grid(column=3, row=3, padx=5, pady=5, sticky=W) self._ety_channel_bandwidth.configure(font=self.__FONT_STYLE) self._ety_channel_bandwidth.insert(0, int(self.rf_object.getMdmChanBW())) self._ety_channel_bandwidth.configure(state='readonly') # sync mode lab_sync_mode = Label(frame, text='Sync Mode') lab_sync_mode.grid(column=4, row=1, padx=5, pady=5, sticky=E) lab_sync_mode.configure(font=self.__FONT_STYLE) sbx_sync_mode = Spinbox(frame, state='readonly') sbx_sync_mode.grid(column=5, row=1, padx=5, pady=5, sticky=W) sbx_sync_mode.configure(font=self.__FONT_STYLE) self._selected_sync_mode.set(self.rf_object.getMdmSyncMode()) sbx_sync_mode.configure(from_=0, to=7, increment=1, textvariable=self._selected_sync_mode) # sync word lab_sync_word = Label(frame, text='Sync Word') lab_sync_word.grid(column=4, row=2, padx=5, pady=5, sticky=E) lab_sync_word.configure(font=self.__FONT_STYLE) self._ety_sync_word = Entry(frame) self._ety_sync_word.grid(column=5, row=2, padx=5, pady=5, sticky=W) self._ety_sync_word.configure(font=self.__FONT_STYLE) self._ety_sync_word.insert(0, self.rf_object.getMdmSyncWord()) self._ety_sync_word.configure(state='readonly') # channel spacing lab_channel_spacing = Label(frame, text='Channel Spacing') lab_channel_spacing.grid(column=4, row=3, padx=5, pady=5, sticky=E) lab_channel_spacing.configure(font=self.__FONT_STYLE) self._ety_channel_spacing = Entry(frame) self._ety_channel_spacing.grid(column=5, row=3, padx=5, pady=5, sticky=W) self._ety_channel_spacing.configure(font=self.__FONT_STYLE) value_channel_spacing = self.rf_object.getMdmChanSpc() self._ety_channel_spacing.insert(0, int(value_channel_spacing)) self._ety_channel_spacing.configure(state='readonly') # enable manchester lab_manchester = Label(frame, text='Enable Manchester') lab_manchester.grid(column=0, row=4, padx=5, pady=5, sticky=E) lab_manchester.configure(font=self.__FONT_STYLE) cbx_manchester = Checkbutton(frame) cbx_manchester.grid(column=1, row=4, padx=5, pady=5, sticky=W) if self.rf_object.getEnableMdmManchester() == 1: self._cbx_manchester_value.set(1) else: self._cbx_manchester_value.set(0) cbx_manchester.configure(onvalue=1, offvalue=0, variable=self._cbx_manchester_value) # save settings self._btn_save_settings = Button(frame, text='Save all Settings', command=self.__action_store_settings) self._btn_save_settings.grid(column=5, row=4, padx=5, pady=5) self._btn_save_settings.configure(font=self.__FONT_STYLE) self._btn_save_settings.bind( "<Enter>", lambda event: event.widget.config(fg='indian red')) self._btn_save_settings.bind( "<Leave>", lambda event: event.widget.config(fg='black')) def __middle_frame(self): """ Create middle frame content """ frame = Frame(self._tk_obj, borderwidth=1, relief=SUNKEN, bg='#fff') frame.grid(column=0, row=1, padx=15, pady=15, sticky=W + E) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) # headline lab_section = Label(frame, text="Transmit RF Settings") lab_section.grid(columnspan=6, row=0, padx=5, pady=5, sticky=W + E) lab_section.configure(font=self.__FONT_HEADLINE) # message lab_message_to_send = Label(frame, text='Message') lab_message_to_send.grid(column=0, row=1, padx=5, pady=5, sticky=E) lab_message_to_send.configure(font=self.__FONT_STYLE) self._ety_message_to_send = Entry(frame, width=50) self._ety_message_to_send.grid(column=1, row=1, padx=5, pady=5, sticky=W) self._ety_message_to_send.configure(font=self.__FONT_STYLE) btn_clear = Button(frame, text='Clear message', command=self.__action_clear_message) btn_clear.grid(column=2, row=1, padx=5, pady=5) btn_clear.configure(font=self.__FONT_STYLE) # repeats lab_repeats = Label(frame, text='Repeats') lab_repeats.grid(column=3, row=1, padx=5, pady=5, sticky=E) lab_repeats.configure(font=self.__FONT_STYLE) self._sbx_repeats = Spinbox(frame, width=10) self._sbx_repeats.grid(column=4, row=1, padx=5, pady=5, sticky=W) self._sbx_repeats.configure(from_=0, to=50, increment=5, state='readonly') self._sbx_repeats.configure(font=self.__FONT_STYLE) # button send self._btn_send = Button(frame, text='Start transmit', command=self.__action_send_signal) self._btn_send.grid(column=5, row=1, padx=5, pady=5, sticky=E) self._btn_send.configure(font=self.__FONT_STYLE) self._btn_send.bind("<Enter>", lambda event: event.widget.config(fg='indian red')) self._btn_send.bind("<Leave>", lambda event: event.widget.config(fg='black')) self._txt_send_status = Text(frame, height=10) self._txt_send_status.grid(columnspan=6, row=2, padx=5, pady=5, sticky=W + E) self._txt_send_status.configure(state='disabled', borderwidth=1, relief=SOLID) def __bottom_frame(self): """ Create bottom frame content """ self._cbx_max_power_value = IntVar(self._tk_obj) self._cbx_lowball_value = IntVar(self._tk_obj) frame = Frame(self._tk_obj, borderwidth=1, relief=SUNKEN, bg='#fff') frame.grid(column=0, row=2, padx=15, pady=15, sticky=W + E) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) # headline txt_section = Label(frame, text="Receive RF Settings") txt_section.grid(columnspan=6, row=0, padx=5, pady=5, sticky=W + E) txt_section.configure(font=self.__FONT_HEADLINE) # lowball lab_lowball = Label(frame, text='Lowball') lab_lowball.grid(column=0, row=1, padx=5, pady=5, sticky=E) lab_lowball.configure(font=self.__FONT_STYLE) # @ToDo: implementation lowball cbx_lowball = Checkbutton(frame, state='disabled') cbx_lowball.grid(column=1, row=1, padx=5, pady=5, sticky=W) cbx_lowball.configure(onvalue=1, offvalue=0, variable=self._cbx_lowball_value) # max power lab_max_power = Label(frame, text='max Power') lab_max_power.grid(column=2, row=1, padx=5, pady=5, sticky=E) lab_max_power.configure(font=self.__FONT_STYLE) # @ToDo: implementation of max power cbx_max_power = Checkbutton(frame, state='disabled') cbx_max_power.grid(column=3, row=1, padx=5, pady=5, sticky=W) cbx_max_power.configure(onvalue=1, offvalue=0, variable=self._cbx_max_power_value) # receive signal self._btn_receive = Button(frame, text='Start receive', command=self.__action_receive_signal) self._btn_receive.grid(column=4, row=1, padx=5, pady=5) self._btn_receive.configure(font=self.__FONT_STYLE) self._btn_receive.bind( "<Enter>", lambda event: event.widget.config(fg='indian red')) self._btn_receive.bind("<Leave>", lambda event: event.widget.config(fg='black')) # copy to clipboard self._btn_copy = Button(frame, text='Copy to clipboard', command=self.__action_copy_to_clipboard) self._btn_copy.grid(column=5, row=1, padx=5, pady=5) self._btn_copy.configure(font=self.__FONT_STYLE) self._btn_copy.bind("<Enter>", lambda event: event.widget.config(fg='indian red')) self._btn_copy.bind("<Leave>", lambda event: event.widget.config(fg='black')) # status self._stx_receive_status = ScrolledText(frame) self._stx_receive_status.grid(columnspan=6, row=2, padx=5, pady=5, sticky=W + E) self._stx_receive_status.configure(height=12, font=self.__FONT_STYLE, borderwidth=1, relief=SOLID)