class test_gui(tk.Tk): def __init__(self, args, picker_type): tk.Tk.__init__(self) self.picker_type = picker_type self.title("test") self.geometry(f"{WIDTH}x{HEIGHT}") f = Frame(self) f.pack(expand=1, fill="both") self.l = Label(f, anchor="center") self.l.pack(side="top", expand=1, fill="both") if args.file: text = "Pick a file!" elif args.dir: text = "Pick a folder!" else: #Not used text = "Pick something!" Button( f, text=text, command=lambda: threader.add_thread(self.get_input ) #Lambda function to ).pack(expand=0, side="bottom") def get_input(self): dialog = self.picker_type(self) #Make the dialog window selection = dialog.get_input() # self.l.configure(text=selection)
def save(event=None): name = name_entry.get().strip() if not mailbox: # new mailbox i = self.b_add.grid_info()['row'] self.b_add.grid_configure(row=i + 1) c = Checkbutton(self.frame) c.state(('selected',)) c.grid(row=i, column=0, pady=4, padx=(4, 0)) l = Label(self.frame, text=name) l.grid(row=i, column=1, padx=4, pady=4) b_edit = Button(self.frame, image=self.im_edit, width=1, command=lambda m=name: self.mailbox_info(m)) b_edit.grid(row=i, column=2, padx=4, pady=4) b_del = Button(self.frame, image=self.im_del, width=1, command=lambda m=name: self.del_mailbox(m)) b_del.grid(row=i, column=3, padx=4, pady=4) self.mailboxes[name] = [c, l, b_edit, b_del] elif name != mailbox: # change name of mailbox os.remove(os.path.join(LOCAL_PATH, mailbox)) c, l, b_edit, b_del = self.mailboxes[mailbox] del(self.mailboxes[mailbox]) l.configure(text=name) b_edit.configure(command=lambda m=name: self.mailbox_info(m)) b_del.configure(command=lambda m=name: self.del_mailbox(m)) self.mailboxes[name] = [c, l, b_edit, b_del] encrypt(name, self.pwd, server_entry.get().strip(), login_entry.get().strip(), password_entry.get().strip(), folder_entry.get().strip()) top.destroy()
class PredictionWidget(Frame): """Shows a prediction to the user.""" def __init__(self, master): """Make boxes, register callbacks etc.""" Frame.__init__(self, master) self.active_category = StringVar() self.bind("<Configure>", self.onResize) self.date = None self.predictor = Predictor() self.category_buttons = self.createCategoryButtons() self.text = Label(self, justify=CENTER, font="Arial 14") def createCategoryButtons(self): """Create the buttons used to choose category. Return them.""" result = [] icons = self.readIcons() categories = self.predictor.categories() for i in categories: if i in icons: icon = icons[i] else: icon = icons["= default ="] category_button = Radiobutton(self, image=icon, variable=self.active_category, value=i, indicatoron=False, width=icon_size, height=icon_size, command=self.update) category_button.image_data = icon result.append(category_button) self.active_category.set(categories[0]) return result def readIcons(self): """Read the gui icons from disk. Return them.""" result = {} categories = open(nextToThisFile("icons.txt")).read().split("\n\n") for i in categories: category_name, file_data = i.split("\n", maxsplit=1) image = PhotoImage(data=file_data) result[category_name] = image return result def onResize(self, event): """Rearrange the children when the geometry of self changes.""" if event.widget == self: center = (event.width / 2, event.height / 2) radius = min(center) - icon_size / 2 self.text.place(anchor=CENTER, x=center[0], y=center[1]) for i, j in enumerate(self.category_buttons): turn = 2 * math.pi angle = turn * (1 / 4 - i / len(self.category_buttons)) j.place(anchor=CENTER, x=center[0] + math.cos(angle) * radius, y=center[1] - math.sin(angle) * radius) def update(self, date=None): """Change contents based on circumstances. Set date if given.""" if date: self.date = date if self.date: predictions = self.predictor.predict(self.date) prediction = predictions[self.active_category.get()] prediction = textwrap.fill(prediction, width=20) else: prediction = "" self.text.configure(text=prediction)
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent, name="frame") self.parent = parent self.initUI() def initUI(self): self.parent.title("Animation") self.pack(fill=BOTH, expand=True) self.i = 0 self.img_names = ("one.png", "two.png", "three.png", "four.png", "five.png", "six.png", "seven.png", "eight.png", "nine.png") img = Image.open(self.img_names[self.i]) num = ImageTk.PhotoImage(img) self.label = Label(self, image=num) self.label.pack(pady=30) # reference must be stored self.label.image = num self.after(DELAY, self.doCycle) def doCycle(self): self.i += 1 if (self.i >= 9): return img = ImageTk.PhotoImage(Image.open(self.img_names[self.i])) self.label.configure(image=img) self.label.image = img self.after(DELAY, self.doCycle)
def initItems(self): """Initialize all widgets here""" # An entry to enter feet value. self.feet_entry = Entry(self, width=7) self.feet_entry.grid(column=2, row=1, sticky=(W, E)) # A label to display translated meters. self.meters_lbl = Label(self, textvariable=self.meters_value) self.meters_value.set(0) self.meters_lbl.grid(column=2, row=2, sticky=(W, E)) # Different labels for text only. Label(self, text='feet').grid(column=3, row=1, sticky=W) Label(self, text='is equivalent to').grid(column=1, row=2, sticky=E) Label(self, text='meters').grid(column=3, row=2, sticky=W) # Button to calculate things. calc_btn = Button(self, text='Calculate', command=lambda: calculate(self)) calc_btn.grid(column=3, row=3, sticky=W) # This widget is just for fun. # Also it shows how to get an event callback when Entry widget is modified def callback(str): print(str.get()) entry_str = StringVar() entry_str.trace('w', lambda name, index, mode, str=entry_str: callback(str)) self.entry_widg = Entry(self, width=10, textvariable=entry_str) self.entry_widg.grid(column=1, row=4, sticky=(W, E)) # A really simple way to change label text: test_lbl = Label(self) test_lbl.grid(column=3, row=4, sticky=E) test_lbl['text'] = 'hello!' # Handling label's events ev_lbl = Label(self, text='Do something with me...', width=30) ev_lbl.grid(column=1, row=5, columnspan=2, rowspan=2) ev_lbl.bind('<Enter>', lambda e: ev_lbl.configure(text='Moved mouse inside')) ev_lbl.bind('<Leave>', lambda e: ev_lbl.configure(text='Moved mouse outside')) ev_lbl.bind( '<1>', lambda e: ev_lbl.configure(text='Clicked left mouse button!')) ev_lbl.bind( '<Double-1>', lambda e: ev_lbl.configure( text='Double clicked left mouse button!')) # Configure pads for all grid cells for child in self.winfo_children(): child.grid_configure(padx=5, pady=5) # As default, entry is focused self.feet_entry.focus()
class MainUI(Frame): def __init__(self, fresco_xyz: FrescoXYZ, z_camera: ZCamera, fresco_camera: FrescoCamera): super().__init__() self.fresco_xyz = fresco_xyz self.z_camera = z_camera self.fresco_camera = fresco_camera self.image_label = None self.init_ui() def init_ui(self): self.master.title("Fresco Labs") self.pack(fill=BOTH, expand=1) steps_manual_controller = StepsManualController( self, fresco_xyz=self.fresco_xyz) steps_manual_controller.place(x=0, y=0) macro_steps_controller = MacroStepsManualController( self, fresco_xyz=self.fresco_xyz) macro_steps_controller.place(x=0, y=200) initialization_controller = Initialization(self, fresco_xyz=self.fresco_xyz) initialization_controller.place(x=0, y=360) auto_focus_controller = AutoFocus(self, fresco_xyz=self.fresco_xyz, z_camera=self.z_camera) auto_focus_controller.place(x=0, y=540) functions_controller = Functions(self, fresco_xyz=self.fresco_xyz, z_camera=self.z_camera) functions_controller.place(x=0, y=640) image_array = self.fresco_camera.get_current_image() camera_image = ImageTk.PhotoImage(image=Image.fromarray(image_array)) self.image_label = Label(self, image=camera_image) self.image_label.image = camera_image self.image_label.place(x=300, y=50) self.after(2000, self.update_image) def update_image(self): image_array = self.fresco_camera.get_current_image() camera_image = ImageTk.PhotoImage(image=Image.fromarray(image_array)) self.image_label.configure(image=camera_image) self.image_label.image = camera_image self.after(10, self.update_image)
def average_normals( self ): """ Applies Gouraud normalization to the module """ # Set up updater top = Toplevel() pb = Progressbar(top,orient ="horizontal",length = 200, mode ="determinate") pb['maximum'] = len(self.__elements__) pb['value'] = 10 pb.grid(row=0,column=0) tx = Label(top) tx.grid(row=1,column=0) top.update_idletasks() top.lift() t0 = time.time() # run the loop, if we're visible and phong shading if not self.invisible == 'gouroud': try: buf = np.array([0,0,0,1]) for i,polygon in enumerate(self.__elements__): if not ispoly(polygon): continue polygon._onorms = np.array([polygon.normals.astype(float)+buf for i in range(len(polygon.coordinates))]) # Update the user as to what's going on if i % 50 == 0 and i > 0: pb['value'] = i tmp = i/len(self.__elements__) estimation = int(tmp*(time.time()-t0) * (1-tmp)/tmp) tx.configure(text=str(int(100*i/len(self.__elements__)))+"%"+' Estimated time: '+str(estimation)+'s' ) top.update_idletasks() for c,coordinate in enumerate(polygon.coordinates): for j,opolygon in enumerate(self.__elements__): if i == j or not ispoly(opolygon): continue for k,ocoordinate in enumerate(opolygon.coordinates): if all(coordinate == ocoordinate): # same vertex, finally polygon._onorms[c] += (opolygon.normals+buf) polygon._onorms /= polygon._onorms[:,3,None] for polygon in self.__elements__: if ispoly(polygon): polygon.normals = polygon._onorms del polygon._onorms except IndexError as ie: pass top.destroy() if self.invisible == 'gouroud': self.invisible = False return self # for chaining
class Tooltip(Toplevel): def __init__(self, parent, **kwargs): Toplevel.__init__(self, parent) if 'title' in kwargs: self.title(kwargs['title']) self.transient(parent) self.attributes('-type', 'tooltip') self.attributes('-alpha', kwargs.get('alpha', 0.8)) self.overrideredirect(True) self.configure(padx=kwargs.get('padx', 4)) self.configure(pady=kwargs.get('pady', 4)) self.style = Style(self) bg = kwargs.get('background', 'black') self.configure(background=bg) self.style.configure('tooltip.TLabel', foreground=kwargs.get('foreground', 'gray90'), background=bg, font='TkDefaultFont 9 bold') self.im = kwargs.get('image', None) self.label = Label(self, text=kwargs.get('text', ''), image=self.im, style='tooltip.TLabel', compound=kwargs.get('compound', 'left')) self.label.pack() def configure(self, **kwargs): if 'text' in kwargs: self.label.configure(text=kwargs.pop('text')) if 'image' in kwargs: self.label.configure(image=kwargs.pop('image')) if 'background' in kwargs: self.style.configure('tooltip.TLabel', background=kwargs['background']) if 'foreground' in kwargs: fg = kwargs.pop('foreground') self.style.configure('tooltip.TLabel', foreground=fg) if 'alpha' in kwargs: self.attributes('-alpha', kwargs.pop('alpha')) Toplevel.configure(self, **kwargs)
def initUI(self): self.master.title("Fawkes") self.master.configure(bg='white') self.pack(fill=BOTH, expand=1) # fawkes image canvas = Canvas(self, width=110, height=150) orig = Image.open("fawkes_mask.jpg") resized = orig.resize((110,150), Image.ANTIALIAS) img = ImageTk.PhotoImage(resized) canvas.create_image(0,0, image=img, anchor=NW) canvas.image = img canvas.pack() # open button btn_Open = Button(self, text='Choose image(s) to cloak', width=25, command=self.select_path) btn_Open.pack() # run button btn_Run = Button(self, text='Cloak images', width=25, command=lambda: thread_it(self.my_fawkes.run_protection, self.img_paths)) btn_Run.pack() # # save button # btn_Save = Button(self, # text='Save cloaked image(s)', # width=25, # command=self.save_images) # btn_Save.pack() # Progress info Label_Show = Label(self, textvariable=self.var, font=('Arial', 13), width=50) Label_Show.configure(anchor="center") Label_Show.pack()
def display_evts(self): def wrap(event): l = event.widget if l.master.winfo_ismapped(): l.configure(wraplength=l.winfo_width()) week = self.master.get_next_week_events() date_today = datetime.now().date() today = date_today.strftime('%A') children = list(self.display.children.values()) for ch in children: ch.destroy() for day, evts in week.items(): if day == today: text = _('Today') else: text = day.capitalize() Label(self.display, text=text, style='day.Events.TLabel').grid(sticky='w', pady=(4, 0), padx=4) for ev, desc in evts: if desc.strip(): tf = ToggledFrame(self.display, text=ev.strip(), style='Events.TFrame') l = Label(tf.interior, text=desc.strip(), style='Events.TLabel') l.pack(padx=4, fill='both', expand=True) l.configure(wraplength=l.winfo_width()) l.bind('<Configure>', wrap) tf.grid(sticky='we', pady=2, padx=(8, 4)) else: l = Label(self.display, text=ev.strip(), style='Events.TLabel') l.bind('<Configure>', wrap) l.grid(sticky='ew', pady=2, padx=(21, 10))
def about_popup(): top = Toplevel() top.title("About Me") top.geometry = "500x400" top.resizable(False, False) top.iconbitmap(pyxe_favicon) about_labelframe = LabelFrame(top, labelanchor="nw", text="Developer Profile:", width=600, height=200, font=('', 10)) about_labelframe.pack(fill="both", expand=True, padx=3, pady=3) profile_photo = Image.open( resource_path( r"pyxe_resources\data\DutytoDevelop_Profile_Pic.png")) resized = profile_photo.resize((150, 150)) profile_photo_resize = ImageTk.PhotoImage(resized) canvas = Canvas(about_labelframe, height=150, width=150) canvas.create_image(75, 75, image=profile_photo_resize) canvas.image = profile_photo_resize canvas.grid(row=1, column=1, padx=3, pady=(3, 0), sticky="nsew") about_label = Label( about_labelframe, text="Name: Nicholas H.\nGitHub: DutytoDevelop", font=('', 10, 'bold')) about_label.configure(anchor="center", justify='center') about_label.grid(row=2, column=1, padx=3, pady=(0, 3), sticky="nsew") return
class StatusBar(Frame): def __init__(self, master, progressMax=100, **kwargs): Frame.__init__(self, master, **kwargs) self.label = Label(self, text="Ready...") self.label.pack(anchor=Tkc.W) self.progressVar = IntVar() self.progress = Progressbar(self, mode='determinate', maximum=abs(progressMax), length="150", variable=self.progressVar) def showText(self, message): self.label.configure(text=message) self.progress.stop() self.progress.pack_forget() self.label.pack(anchor=Tkc.W) def showProgress(self): self.progress.configure(mode='determinate') self.label.pack_forget() self.progress.pack(anchor=Tkc.W) self.update_idletasks() def setProgress(self, value): self.progressVar.set(value) self.update_idletasks() def setProgressMax(self, value): self.progress.configure(maximum=abs(value)) def showActivity(self): self.progress.configure(mode='indeterminate') self.progress.start() self.showProgress()
class ShanksApp(): """Tkinter GUI application with interactive calcualtion of dicrepete logarithm.""" is_start = True i = 0 a = 0 b = 0 p = 0 x1 = 0 x2 = 0 output_ind = 0 max_ind = -1 line0 = 'm =' line1 = 'Step number i ' line2 = '----------------------------------' line3 = 'Big step = a^(i*m) ' line4 = 'Small step = b*a^i ' def create_table(self) -> str: """Create string with output layout (algorithm steps).""" return self.line0 + '\n' + self.line1 + '\n' + self.line2 + '\n' + self.line3 + '\n' + self.line4 def create_output(self) -> None: """Initialization of textual output after correctly specified a, b, p. Mainly string operations. Assign values to class instance attributes.""" self.x1, self.x2, giant_list, baby_list = self.run_shanks_algo( self.a, self.b, self.p) m = ceil(sqrt(self.p)) self.max_ind = m + len(baby_list) self.output_list = [] self.line0 = f"PROBLEM: {self.a}^x = {self.b} mod {self.p}, find x.\nSOLUTION: Number of big steps is {m}." self.line1 = "Step number i " for i in range(m): self.line1 += f"| {i} " self.line2 = '-----------------------' + '-' * 4 * m self.line3 = f'Big step = {self.a}^(i*{m}) ' self.line3 = self.line3[:27] self.line4 = f'Small step = {self.b}*{self.a}^(-i) ' self.line4 = self.line4[:27] self.output_list.append(self.create_table()) for i in range(m): temp = f"| {giant_list[i % len(giant_list)]} " self.line3 += temp[:5] self.output_list.append(self.create_table()) for i in range(len(baby_list)): temp = f"| {baby_list[i]} " self.line4 += temp[:5] self.output_list.append(self.create_table()) self.line0 = f"PROBLEM: {self.a}^x = {self.b} mod {self.p}, find x.\nSOLUTION: Number of big steps is {m}." self.line1 = "Step number i " for i in range(m): self.line1 += f"| {i} " self.line2 = '-----------------------' + '-' * 4 * m self.line3 = f'Big step = {self.a}^(i*{m}) ' self.line3 = self.line3[:27] self.line4 = f'Small step = {self.b}*{self.a}^(-i) ' self.line4 = self.line4[:25] def exp(self, a: int, b: int, p: int) -> int: """Recursive exponentiation a^b modulo p.""" if b == 0: return 1 res = self.exp(a, int(b / 2), p) res = (res * res) % p if b % 2 == 1: res = (res * a) % p return res def is_prime(self, n: int) -> bool: """Checks if n is prime.""" return n > 1 and all(n % i for i in islice(count(2), int(sqrt(n) - 1))) def is_generator(self, a: int, p: int) -> bool: """Checks if A generate whole cyclic multiplication group of order P.""" gen_set = set() curr = 1 gen_set.add(curr) for i in range(p - 2): curr = (curr * a) % p if curr in gen_set: return False gen_set.add(curr) return True def validate_input(self) -> None: """Validate input values for a, b, p and prompt corresponding errors if some constraints are not satisfiied. 1. Converts a, b, p to integers, prompt error if not successful 2. Checks a, b, p to be positive 3. Checks p to be prime and not exceed p_limit. 4. Checks if a generates full cyclic group of order p under multiplication """ p_limit = 10000000 try: self.p = int(self.entry_p.get()) self.a = int(self.entry_a.get()) self.b = int(self.entry_b.get()) except Exception: self.lbl0.config(text=f"Error! Input should be numeric!", foreground="red") return if self.is_prime(self.p) and self.p < p_limit and 0 < self.a and self.a < self.p and 0 < self.b and \ self.b < self.p: self.create_output() if self.is_generator(self.a, self.p): self.lbl0.config(foreground="black") self.update_grid_start_algo() else: self.lbl0.config( text=f"Error! a={self.a} should generate the whole group!", foreground="red") else: bool_list = [ self.is_prime(self.p), self.p < p_limit, 0 < self.a, self.a < self.p, 0 < self.b, self.b < self.p ] str_list = [ 'p should be prime', f'p < {p_limit}', '0 < a', 'a < p', '0 < b', 'b < p' ] err = 'Error! Following constraints should be satisfied: ' flag = -1 # controls state of error text variable for bool_val, err_str in zip(bool_list, str_list): if not bool_val: # several possibilities of updating err if flag in [0, 2]: err += '; ' err += err_str if flag in [-1, 1]: flag += 1 if flag == 0 and len(err) > 66: err += '\n' flag = 1 self.lbl0.configure(text=err, foreground="red") def run_shanks_algo(self, a: int, b: int, p: int) -> Tuple[int, int, List, List]: """Main method for running shanks algorithm. Args: a: logarithm base b: result of power operation on a p: order of cyclic group Returns: self.x1: calculated value of giant step self.x2: calculated value of beby step giant_list: list with values of giant steps baby_list: list with values of baby steps """ m = int(ceil(sqrt(p))) giant_dict = {} step = self.exp(a, m, p) baby_list = [] giant_list = [1] # giant steps calculation last_val = 1 for i in range(m): last_val = (last_val * step) % p giant_list.append(last_val) if last_val not in giant_dict: giant_dict[last_val] = i + 1 # baby steps calculation, terminates when we match value in giant_dict last_val = b for i in range(m): baby_list.append(last_val) if last_val in giant_dict: self.x1 = giant_dict[last_val] self.x2 = i break last_val = (last_val * a) % p return self.x1, self.x2, giant_list, baby_list def update_grid_start(self) -> None: """Called on start or when Restart button was pressed. Destroys old layout elements and create new in the latter case.""" if not self.is_start: self.frame0.destroy() self.frame1.destroy() self.frame2.destroy() self.frame3.destroy() try: self.frame4.destroy() self.frame5.destroy() self.frame6.destroy() except: pass self.is_start = False self.frame.pack(fill=BOTH, expand=True) self.frame0 = Frame(self.frame) self.frame0.pack(fill=X) self.lbl0 = Label(self.frame0, text="Solving for x: a^x = b mod p. Enter a, b, p:", width=60) self.lbl0.pack(side=LEFT, padx=20, pady=5) self.frame1 = Frame(self.frame) self.frame1.pack(fill=X) self.lbl1 = Label(self.frame1, text="Logarithm base a", width=18) self.lbl1.pack(side=LEFT, padx=20, pady=5) self.entry_a = Entry(self.frame1) self.entry_a.pack(fill=X, padx=5, expand=True) self.frame2 = Frame(self.frame) self.frame2.pack(fill=X) self.lbl2 = Label(self.frame2, text="Logarithm argument b", width=18) self.lbl2.pack(side=LEFT, padx=20, pady=5) self.entry_b = Entry(self.frame2) self.entry_b.pack(fill=X, padx=5, expand=False) self.frame3 = Frame(self.frame) self.frame3.pack(fill=X) self.lbl3 = Label(self.frame3, text="Prime number p", width=18) self.lbl3.pack(side=LEFT, padx=20, pady=5) self.entry_p = Entry(self.frame3) self.entry_p.pack(fill=X, padx=5, expand=True) self.frame4 = Frame(self.frame) self.frame4.pack(fill=X) self.input_button = Button(self.frame4, text="Set", command=lambda: self.validate_input()) self.input_button.pack(side=LEFT, padx=20, pady=0) self.input_button = Button(self.frame4, text="Restart", command=lambda: self.update_grid_start()) self.input_button.pack(side=LEFT, padx=0, pady=0) self.input_button = Button(self.frame4, text="Exit", command=lambda: self.update_grid_exit()) self.input_button.pack(side=LEFT, padx=0, pady=0) def update_grid_start_algo(self) -> None: """Called when "Set button" clicked while all parameters of algorithm specified correctly a, b, p. Clears old layout elements, set textual output and new buttons. """ self.output_ind = 0 self.lbl0.configure(text=self.create_table()) self.frame1.destroy() self.frame2.destroy() self.frame3.destroy() self.frame4.destroy() self.frame3 = Frame(self.frame) self.frame3.pack(fill=X) self.input_button = Button( self.frame3, text="<< Previous step", command=lambda: self.update_grid_previous_step()) self.input_button.pack(side=LEFT, padx=20, pady=0) self.input_button = Button( self.frame3, text="Next step >>", command=lambda: self.update_grid_next_step()) self.input_button.pack(side=LEFT, padx=0, pady=0) self.frame4 = Frame(self.frame) self.frame4.pack(fill=X) self.input_button = Button(self.frame4, text="Restart", command=lambda: self.update_grid_start()) self.input_button.pack(side=LEFT, padx=20, pady=0) self.input_button = Button(self.frame4, text="Exit", command=lambda: self.update_grid_exit()) self.input_button.pack(side=LEFT, padx=60, pady=0) def update_grid_next_step(self) -> None: """Called when "Next Step" button pressed during the algorithm run.""" if self.output_ind == self.max_ind: upd_txt = f"Congratulations, we are done! m = {ceil(sqrt(self.p))}, answer: " upd_txt += f"x = {ceil(sqrt(self.p))} * {self.x1} - {self.x2} = {ceil(sqrt(self.p)) * self.x1 - self.x2}\n" self.lbl0.configure(text=upd_txt + self.output_list[self.max_ind]) else: self.output_ind += 1 self.lbl0.configure(text=self.output_list[self.output_ind]) def update_grid_previous_step(self) -> None: """Called when "Previous Step" button is pressed. Updates state of layout and layout itself.""" if self.output_ind != 0: self.output_ind -= 1 self.lbl0.configure(text=self.output_list[self.output_ind]) def update_grid_exit(self) -> None: """Called if "Exit" button is pressed. Closes tkinter's window. """ self.window.destroy() def run_app(self) -> None: """Entry point to tkinter app.""" self.window = Tk() self.window.title("Baby-step giant-step algorithm") self.window.geometry("500x180") self.frame = Frame() self.update_grid_start() self.frame.mainloop()
class TtkScale(Scale): def __init__(self, parent, length=0, from_=0, to=255, orient='vertical', variable=0, digits=None, tickinterval=None, command=None, style=None, showvalue=True, resolution=1): self.from_ = from_ self.to = to self.variable = variable self.length = length self.command = command self.parent = parent super().__init__(parent, length=length, from_=from_, to=to, orient=orient, variable=variable, command=command, style=style) self.digits = digits self.tickinterval = tickinterval self.showvalue = showvalue self.resolution = resolution # set sliderlength st = Style(self) self.bw_val = bw_val = st.lookup('Vertical.Scale.trough', 'borderwidth') self.sliderlength = sliderlength = 32 if showvalue: self.configure(command=self.display_value) def_font = font.nametofont('TkDefaultFont') # if from_ more than to swap values if from_ < to: pass else: from_, to = to, from_ data = np.arange(from_, (to + 1 if tickinterval >= 1 else to + tickinterval), tickinterval) self.data = data = np.round(data, 1) range_vals = tuple(data) len_rvs = len(range_vals) lspace = def_font.metrics('linespace') len_rvs = len(range_vals) data_size = len_rvs * lspace space_size = len_rvs * 3 sizes = data_size + space_size min_len = (sizes if sizes % 50 == 0 else sizes + 50 - sizes % 50) self.len_val = len_val = min_len if length < min_len else length self.configure(length=len_val) self.rel_min = rel_min = (sliderlength / 2 + bw_val) / len_val self.rel_max = rel_max = 1 - (sliderlength / 2 - bw_val) / len_val if range_vals[-1] == to: pass else: max_rv = range_vals[-1] self.mult_y = mult_y = ((max_rv - from_) * rel_max / (to - from_)) self.bind("<Button-1>", self.resolve) self.build(from_, to, rel_min, rel_max, range_vals, len_rvs) def build(self, from_, to, rel_min, rel_max, range_vals, len_rvs): for i, rv in enumerate(range_vals): item = Label(self.parent, text=rv) item.place( in_=self, bordermode='outside', rely=(rel_min + i / (len_rvs - 1) * ((rel_max if range_vals[-1] == to else self.mult_y) - rel_min)), relx=1, anchor='w') if self.showvalue: self.disp_lab = Label(self.parent, text=self.get()) rel_y = self.convert_to_rely(float( self.get())) #, textvariable = self.act_val) self.disp_lab.place(in_=self, bordermode='outside', rely=rel_y, relx=0, anchor='e') def convert_to_rely(self, curr_val): return ((curr_val - self.from_) * (self.rel_max - self.rel_min) / (self.to - self.from_) + self.rel_min) def convert_to_acty(self, curr_val): y_max = self.rel_max * self.len_val y_min = self.rel_min * self.len_val return ((curr_val - self.from_) * (y_max - y_min) / (self.to - self.from_) + y_min) def display_value(self, value): # position (in pixel) of the center of the slider rel_y = self.convert_to_rely(float(value)) self.disp_lab.config(text=value) # text="" self.disp_lab.place_configure(rely=rel_y) digits = self.digits self.disp_lab.configure(text=f'{float(value):.{dig_val}f}') # if your python is not 3.6 or above use the following 2 lines # instead of the line above #my_precision = '{:.{}f}'.format #self.disp_lab.configure(text=my_precision(float(value), digits)) def resolve(self, evt): resolution = self.resolution if resolution < 1 or self.tickinterval < 1: pass else: value = self.get() curr_y = self.convert_to_acty(value) if evt.y < curr_y - self.sliderlength / 2: self.set(value - resolution + 1) elif evt.y > curr_y + self.sliderlength / 2: self.set(value + resolution - 1)
class Tooltip(Toplevel): """ Tooltip class """ def __init__(self, parent, **kwargs): """ Create a tooltip with given parent. KEYWORD OPTIONS title, alpha, padx, pady, font, background, foreground, image, text """ Toplevel.__init__(self, parent) if 'title' in kwargs: self.title(kwargs['title']) self.transient(parent) self.attributes('-type', 'tooltip') self.attributes('-alpha', kwargs.get('alpha', 0.75)) self.overrideredirect(True) self.configure(padx=kwargs.get('padx', 4)) self.configure(pady=kwargs.get('pady', 4)) self.font = Font(self, kwargs.get('font', '')) self.style = Style(self) if 'background' in kwargs: bg = kwargs['background'] self.configure(background=bg) self.style.configure('tooltip.TLabel', background=bg) if 'foreground' in kwargs: self.style.configure('tooltip.TLabel', foreground=kwargs['foreground']) self.im = kwargs.get('image', None) self.label = Label(self, text=kwargs.get('text', ''), image=self.im, style='tooltip.TLabel', font=self.font, wraplength='6c', compound=kwargs.get('compound', 'left')) self.label.pack() def configure(self, **kwargs): if 'text' in kwargs: self.label.configure(text=kwargs.pop('text')) if 'image' in kwargs: self.label.configure(image=kwargs.pop('image')) if 'background' in kwargs: self.style.configure('tooltip.TLabel', background=kwargs['background']) if 'foreground' in kwargs: fg = kwargs.pop('foreground') self.style.configure('tooltip.TLabel', foreground=fg) if 'alpha' in kwargs: self.attributes('-alpha', kwargs.pop('alpha')) if 'font' in kwargs: font = Font(self, kwargs.pop('font')) self.font.configure(**font.actual()) Toplevel.configure(self, **kwargs) def config(self, **kw): self.configurere(**kw) def cget(self, key): if key in ['text', 'image']: return self.label.cget(key) elif key == 'font': return self.font elif key == 'alpha': return self.attributes('-alpha') elif key in ['foreground', 'background']: return self.style.lookup('tooltip.TLabel', key) else: return Toplevel.cget(self, key)
class ExpenseTab: # Use for option selection for currency currency_code_list = [ 'AUD', 'CAD', 'CHF', 'CNY', 'DKK', 'EUR', 'GBP', 'INR', 'JPY', 'LBP', 'NOK', 'NZD', 'MAD', 'USD', 'SEK', 'TND' ] convert_to_EUR = [ 0.62, 0.65, 0.93, 0.13, 0.13, 1, 1.11, 0.011, 0.008, 0.00056, 0.094, 0.58, 0.092, 0.85, 0.098, 0.31 ] def __init__(self, tab_control, expense_controller, user_controller, username): """Initializes the expense tab and creates all elements of the visual interface""" # Input for the expense interface self.expense_controller = expense_controller self.user_controller = user_controller self.username = username self.category_list = self.user_controller.get_categories(self.username) self.chosen_currency = StringVar() self.chosen_category = StringVar() self.description = StringVar() self.price = StringVar() self.price_in_euro = StringVar() self.date = StringVar() self.currency_EUR_dict = { self.currency_code_list[i]: self.convert_to_EUR[i] for i in range(len(self.currency_code_list)) } try: # try to load latest currency conversion codes through an API response = requests.get('https://api.ratesapi.io/api/latest') for c in self.currency_code_list: try: # try to load conversion rate for specific currency self.currency_EUR_dict[c] = 1 / response.json()['rates'][c] except KeyError: # if not available (e.g. LBP) the hard-coded conversion rate is used pass except requests.exceptions.RequestException as e: # if no internet connection is available or the server is down, hard-coded conversion rates are used print(e) self.id_expenseItem = 0 total = self.expense_controller.total_expenses(self.username) self.sum_expenses = StringVar(value=f"Sum of all expenses: {total}€") self.budget_message = StringVar() self.expense_tab = ttk.Frame(tab_control) tab_control.add(self.expense_tab, text='Expenses') Label(self.expense_tab, text="New expense:", font='Helvetica 16 bold').grid(row=0, column=0, padx=15, pady=15, sticky='w') # DESCRIPTION Label(self.expense_tab, text="Description:").grid(row=1, column=0, padx=(15, 0), pady=2, sticky='w') Entry(self.expense_tab, textvariable=self.description).grid(row=1, column=1, pady=2, sticky="ew") # CATEGORY Label(self.expense_tab, text="Category:").grid(row=1, column=2, pady=2) self.category_select = OptionMenu(self.expense_tab, self.chosen_category, self.category_list[0], *self.category_list) self.category_select.grid(row=1, column=3, padx=(0, 15), pady=2, sticky="ew") # PRICE Label(self.expense_tab, text="Price:").grid(row=2, column=0, padx=(15, 0), pady=2, sticky='w') Entry(self.expense_tab, textvariable=self.price).grid(row=2, column=1, pady=2, sticky="ew") # CURRENCY OPTION Label(self.expense_tab, text="Currency:").grid(row=2, column=2, pady=2) OptionMenu(self.expense_tab, self.chosen_currency, self.currency_code_list[5], *self.currency_code_list)\ .grid(row=2, column=3, padx=(0, 15), pady=2, sticky="ew") # DATE Label(self.expense_tab, text="Date:").grid(row=3, column=0, padx=(15, 0), pady=2, sticky='w') DateEntry(self.expense_tab, background='darkblue', foreground='white', borderwidth=2, textvariable=self.date, date_pattern='dd/MM/yyyy').grid(row=3, column=1, pady=2, sticky="ew") # INSERT BUTTON Button(self.expense_tab, text="Insert", command=self.insert_expense_data).grid(row=4, column=1, pady=2, sticky="ew") Label(self.expense_tab, text="Your expenses:", font='Helvetica 16 bold').grid(row=5, column=0, padx=15, pady=15, sticky='w') # TOTAL EXPENSE Label(self.expense_tab, textvariable=self.sum_expenses).grid(row=6, column=0, padx=(15, 0), sticky='w') # BUDGET DIFFERENCE self.budgetLabel = Label(self.expense_tab, textvariable=self.budget_message) self.budgetLabel.grid(row=7, column=0, columnspan=2, padx=(15, 0), sticky='w') # set budget difference value budget_message = self.calculate_budget_level() self.budget_message.set(budget_message) # TREEVIEW WITH SCROLLBAR y_scroll = Scrollbar(self.expense_tab, orient='vertical') y_scroll.grid(row=8, column=5, padx=(0, 15), pady=(40, 15), sticky='nsw') self.treeExpense = ttk.Treeview(self.expense_tab, columns=('Date', 'Category', 'Description', 'Price', 'Currency', 'Price in EUR'), yscrollcommand=y_scroll.set, height=20) y_scroll['command'] = self.treeExpense.yview self.treeExpense.grid(row=8, column=0, columnspan=5, padx=(15, 0), pady=15) # Set the treeview columns self.treeExpense.heading('#0', text='Item Id') self.treeExpense.column("#0", minwidth=0, width=0) self.treeExpense.heading('#1', text='Date') self.treeExpense.column("#1", minwidth=0, width=120) self.treeExpense.heading('#2', text='Category') self.treeExpense.column("#2", minwidth=0, width=280) self.treeExpense.heading('#3', text='Description') self.treeExpense.column("#3", minwidth=0, width=280) self.treeExpense.heading('#4', text='Price') self.treeExpense.column("#4", minwidth=0, width=100) self.treeExpense.heading('#5', text='Currency') self.treeExpense.column("#5", minwidth=0, width=100) self.treeExpense.heading('#6', text='Price in EUR') self.treeExpense.column("#6", minwidth=0, width=100) # Restore display in table from the expense database self.update_treeview_from_existing_database() # DELETE BUTTON # Configure delete button style to be red style = Style() style.configure('W.TButton', foreground='red') Button(self.expense_tab, text="Delete", style='W.TButton', command=self.delete_expense_data).grid(row=9, column=4, padx=15, sticky="e") # SORT THE PRICE: CALL FUNCTION col1 = "Price" col2 = "Price in EUR" col3 = "Date" self.treeExpense.heading( col1, text=col1, command=lambda: self.treeview_sort_price(col1, False)) self.treeExpense.heading( col2, text=col2, command=lambda: self.treeview_sort_price(col2, False)) # SORT THE DATE: CALL FUNCTION self.treeExpense.heading( col3, text=col3, command=lambda s=col3: self.treeview_sort_date(col3, False)) def update_treeview_from_existing_database(self): """If the database of expenses already exist for this username, display it back into the treeview""" database = self.expense_controller.get_expenses_for_user(self.username) for id_item in database: self.treeExpense.insert( '', 0, id_item, values=(database[id_item]["date"], database[id_item]["category"], database[id_item]["description"], database[id_item]["price"], database[id_item]["currency"], database[id_item]["price_in_euro"])) self.id_expenseItem = id_item def insert_expense_data(self): """ Add a new expense item both to the treeview and to the database. Then update the sum of all expenses and the budget difference. This function is called when clicking the 'Insert' button """ currency = self.chosen_currency.get() category = self.chosen_category.get() description = self.description.get() price = self.price.get() expense_date = self.date.get() # replace comma with point in order to make it possible to cast to float price = price.replace(',', '.') # Check if it is numeric if not is_float_number(price): messagebox.showerror("INPUT ERROR", "The price must be a (floating) number") else: self.id_expenseItem = self.id_expenseItem + 1 price = float(price) price_in_euro = self.expense_controller.convert_in_euro( price, currency, self.currency_EUR_dict) # display into the Expense gui table # https://www.askpython.com/python-modules/tkinter/tkinter-treeview-widget self.treeExpense.insert('', 0, self.id_expenseItem, values=(expense_date, category, description, price, currency, price_in_euro)) # update the expense database through expense controller self.expense_controller.create_expense(self.username, self.id_expenseItem, expense_date, category, description, price, currency, price_in_euro) total = self.expense_controller.total_expenses(self.username) self.sum_expenses.set(f"Sum of all expenses: {total}€") budget_message = self.calculate_budget_level() self.budget_message.set(budget_message) def delete_expense_data(self): """ Remove the selected item from the treeview and the database, then update the sum of all expenses and the budget difference. This function is called when clicking the 'Delete' button """ try: id_expense_selected = int(self.treeExpense.focus()) self.treeExpense.delete(id_expense_selected) # remove the selected expense id in the database as well self.expense_controller.delete_expense(self.username, id_expense_selected) except ValueError: messagebox.showerror("Delete Error", "Select an item to be deleted") total = self.expense_controller.total_expenses(self.username) self.sum_expenses.set(f"Sum of all expenses: {total}€") budget_message = self.calculate_budget_level() self.budget_message.set(budget_message) def refresh_categories(self, category_list): """Refresh the category drop-down menu. This is called after configuring categories in the preferences""" self.category_list = category_list self.category_select = OptionMenu(self.expense_tab, self.chosen_category, self.category_list[0], *self.category_list) self.category_select.grid(row=1, column=3, pady=5, sticky="ew") def treeview_sort_price(self, col, reverse: bool): """Sort the table by price when clicking on the price column""" data_list = [(float(self.treeExpense.set(k, col)), k) for k in self.treeExpense.get_children("")] data_list.sort(reverse=reverse) # rearrange items in sorted positions for index, (val, k) in enumerate(data_list): self.treeExpense.move(k, "", index) # reverse sort next time self.treeExpense.heading( column=col, text=col, command=lambda _col=col: self.treeview_sort_price( _col, not reverse), ) def treeview_sort_date(self, date_col, reverse): """Sort the table by date when clicking on the date column""" l = [(self.treeExpense.set(k, date_col), k) for k in self.treeExpense.get_children('')] sortedArray = sorted( l, key=lambda x_lab: datetime.strptime(x_lab[0], '%d/%m/%Y'), reverse=not reverse) for index, (val, k) in enumerate(sortedArray): self.treeExpense.move(k, '', index) self.treeExpense.heading( column=date_col, text=date_col, command=lambda _date_col=date_col: self.treeview_sort_date( _date_col, not reverse), ) def calculate_budget_level(self): """ Calculates whether the custom budget (in preferences) is already exceeded or not and generate a message to display. """ budget = self.user_controller.get_budget(self.username) if budget[0]: today = date.today() if budget[1] == 'per day': start_date = today elif budget[1] == 'per week': start_date = today - timedelta(days=today.weekday()) elif budget[1] == 'per month': start_date = today.replace(day=1) elif budget[1] == 'per year': start_date = today.replace(month=1).replace(day=1) expenses = self.expense_controller.get_expenses_for_user( self.username) delete = [] for k, v in expenses.items(): if datetime.date(datetime.strptime(v['date'], '%d/%m/%Y')) < start_date: delete.append(k) # we cannot delete items from dictionary while iterating the dict, therefore we store indices to delete in # list and delete the corresponding elements later for k in delete: del expenses[k] total = sum([e['price_in_euro'] for e in expenses.values()]) difference = round((float(budget[0]) - total), 2) if difference > 0: message = f'You have {difference}€ left from your budget which is {budget[0]}€ {budget[1]}.' self.budgetLabel.configure(foreground='green') elif difference == 0: message = f'Attention! You have nothing left from your budget which is {budget[0]}€ {budget[1]}.' self.budgetLabel.configure(foreground='orange') else: message = f'Attention! You exceeded your budget ({budget[0]}€ {budget[1]}) by {-1*difference}€!' self.budgetLabel.configure(foreground='red') return message return "You haven't set a budget yet. You can do so in the preferences."
class viewStock(Frame): '''The Frame that is kind of a logged in view and contains buttons to move to sell, buy or log out. At the same time it it also shows what stocks one has along with their profit and more''' def __init__(self, parent, main, **kw): Frame.__init__(self, parent, **kw) self.view_f_text = Text(width=30) self.main = main self.view_scroll = Scrollbar(orient = VERTICAL, command=self.view_f_text.yview) self.view_f_text.config(yscrollcommand = self.view_scroll.set) self.label_head = Label(text='Stocks available', font = MED_FONT) self.back_b = Button(text='Login and Buy', command = self.back ) self.buy_b = Button(text='BUY', command = self.buy) self.sell_b = Button(text='SELL', command = self.sell) def buy(self): '''the call back if we click on buy and takes us to the buy window''' self.main.frames[RETAIL_PAGE].page = 'b' self.main.show_frame(RETAIL_PAGE, VIEW_STOCK) def sell(self): '''the call back if we click on sell and it takes us to the sell window''' self.main.frames[RETAIL_PAGE].page = 's' self.main.show_frame(RETAIL_PAGE, VIEW_STOCK) def back(self): '''this is kind of the ''' self.main.show_frame(LOGIN_PAGE, VIEW_STOCK) self.main.login = False self.main.admin = False def showItems(self, main): if main.login: self.back_b.config(text='Log Out') self.label_head.config(text='Logged in as %s'%self.main.present_user) self.buy_b.grid(column=0, row=2, columnspan=2) self.sell_b.grid(column=0, row=3, columnspan=2) else: self.back_b.config(text='Login and Buy') self.label_head.configure(text='View Stock') self.label_head.grid(column=0, row=0, columnspan=2) self.view_f_text.grid(column=0, row=1, sticky='nsew') self.view_scroll.grid(column=2, row=1) self.back_b.grid(column=0, row=4, columnspan=2) self.view_stock() def hideItems(self, main): self.label_head.grid_forget() self.view_f_text.grid_forget() self.view_scroll.grid_forget() self.back_b.grid_forget() if main.login: self.buy_b.grid_forget() self.sell_b.grid_forget() def view_stock(self): self.view_f_text.config(state='normal') self.view_f_text.delete('1.0', 'end') if self.main.login and not self.main.admin: l2 = self.main.accounts[self.main.present_user] txt_1 = 'Balance: ' + l2['balance'] + '\n' + 'Profit: ' + l2['profit'] + '\n'*2 + '*'*20 + '\n' self.view_f_text.insert('end',txt_1) key = self.main.shares_dict.keys() if not self.main.login: for name in key: li = self.main.shares_dict[name] txt_b1 = 'Name: ' self.view_f_text.insert('end',txt_b1) self.view_f_text.insert('end',name+'\n') txt_b2 = 'Cost Price: ' self.view_f_text.insert('end',txt_b2) self.view_f_text.insert('end',li['cost']+'\n') available_num = int(li['tot_amount']) - int(li['tot_sold']) txt_b3 = 'Available amount: ' self.view_f_text.insert('end',txt_b3) self.view_f_text.insert('end',str(available_num)+'\n') txt_b4 = '*'*20 self.view_f_text.insert('end','\n'+txt_b4+'\n\n') self.view_scroll.grid(column=1, row=0, rowspan=2, sticky='nswe') if self.main.login: for name in key: li = self.main.shares_dict[name] txt_b1 = 'Name: ' self.view_f_text.insert('end',txt_b1) self.view_f_text.insert('end',name+'\n') txt_b2 = 'Cost Price: ' self.view_f_text.insert('end',txt_b2) self.view_f_text.insert('end',li['cost']+'\n') available_num = int(li['tot_amount']) - int(li['tot_sold']) txt_b3 = 'Available amount: ' self.view_f_text.insert('end',txt_b3) self.view_f_text.insert('end',str(available_num)+'\n') lis = self.main.p_user_dict for i in lis: if i['name'] == name: lis = i break txt1 = 'Stocks owned: '+lis['tot_owned']+'\n' if not lis['tot_owned'] == '0' else '' self.view_f_text.insert('end', txt1) txt2 = 'Money spent: '+ lis['money_spent']+'\n' if not lis['tot_owned'] == '0' else '' self.view_f_text.insert('end', txt2) txt_b4 = '*'*20 self.view_f_text.insert('end','\n'+txt_b4+'\n\n') self.view_f_text.config(state='disabled') else: self.view_f_text.config(state='disabled')
def label_inc(): global i i = i + 1 label.configure(text='Counting UP: {}'.format(i)) root.update_idletasks() def label_dec(): global i i = i - 1 label.configure(text='Counting Down: {}'.format(i)) root.update_idletasks() def close_window(): root.destroy() if __name__ == '__main__': i = 0 root = Tk() root.geometry("250x80") root.title("Up & Down Counter") label = Label(root) label.place(x=5, y=10) label.configure(text='Count: 0') Button(root, text=' Count up ', command=label_inc).place(x=5, y=40) Button(root, text='Count down', command=label_dec).place(x=85, y=40) Button(root, text='Exit', command=close_window).place(x=170, y=40) mainloop()
class Sudoku(Tk): def __init__(self, file=None): Tk.__init__(self, className="Sudoku-Tk") self.title("Sudoku-Tk") self.resizable(0, 0) self.protocol("WM_DELETE_WINDOW", self.quitter) cst.set_icon(self) self.columnconfigure(3, weight=1) # --- style bg = '#dddddd' activebg = '#efefef' pressedbg = '#c1c1c1' lightcolor = '#ededed' darkcolor = '#cfcdc8' bordercolor = '#888888' focusbordercolor = '#5E5E5E' disabledfg = '#999999' disabledbg = bg button_style_config = {'bordercolor': bordercolor, 'background': bg, 'lightcolor': lightcolor, 'darkcolor': darkcolor} button_style_map = {'background': [('active', activebg), ('disabled', disabledbg), ('pressed', pressedbg)], 'lightcolor': [('pressed', darkcolor)], 'darkcolor': [('pressed', lightcolor)], 'bordercolor': [('focus', focusbordercolor)], 'foreground': [('disabled', disabledfg)]} style = Style(self) style.theme_use(cst.STYLE) style.configure('TFrame', background=bg) style.configure('TLabel', background=bg) style.configure('TScrollbar', gripcount=0, troughcolor=pressedbg, **button_style_config) style.map('TScrollbar', **button_style_map) style.configure('TButton', **button_style_config) style.map('TButton', **button_style_map) style.configure('TCheckutton', **button_style_config) style.map('TCheckutton', **button_style_map) self.option_add('*Toplevel.background', bg) self.option_add('*Menu.background', bg) self.option_add('*Menu.activeBackground', activebg) self.option_add('*Menu.activeForeground', "black") self.configure(bg=bg) style.configure("bg.TFrame", background="grey") style.configure("case.TFrame", background="white") style.configure("case.TLabel", background="white", foreground="black") style.configure("case_init.TFrame", background="lightgrey") style.configure("case_init.TLabel", background="lightgrey", foreground="black") style.configure("erreur.TFrame", background="white") style.configure("erreur.TLabel", background="white", foreground="red") style.configure("solution.TFrame", background="white") style.configure("solution.TLabel", background="white", foreground="blue") style.configure("pause.TLabel", foreground="grey", background='white') # --- images self.im_erreur = open_image(cst.ERREUR) self.im_pause = open_image(cst.PAUSE) self.im_restart = open_image(cst.RESTART) self.im_play = open_image(cst.PLAY) self.im_info = open_image(cst.INFO) self.im_undo = open_image(cst.UNDO) self.im_redo = open_image(cst.REDO) self.im_question = open_image(cst.QUESTION) # --- timer self.chrono = [0, 0] self.tps = Label(self, text=" %02i:%02i" % tuple(self.chrono), font="Arial 16") self.debut = False # la partie a-t-elle commencée ? self.chrono_on = False # le chrono est-il en marche ? # --- buttons self.b_pause = Button(self, state="disabled", image=self.im_pause, command=self.play_pause) self.b_restart = Button(self, state="disabled", image=self.im_restart, command=self.recommence) self.b_undo = Button(self, image=self.im_undo, command=self.undo) self.b_redo = Button(self, image=self.im_redo, command=self.redo) # --- tooltips self.tooltip_wrapper = TooltipWrapper(self) self.tooltip_wrapper.add_tooltip(self.b_pause, _("Pause game")) self.tooltip_wrapper.add_tooltip(self.b_restart, _("Restart game")) self.tooltip_wrapper.add_tooltip(self.b_undo, _("Undo")) self.tooltip_wrapper.add_tooltip(self.b_redo, _("Redo")) # --- numbers frame_nb = Frame(self, style='bg.TFrame', width=36) self.progression = [] for i in range(1, 10): self.progression.append(Progression(frame_nb, i)) self.progression[-1].pack(padx=1, pady=1) # --- level indication frame = Frame(self) frame.grid(row=0, columnspan=5, padx=(30, 10), pady=10) Label(frame, text=_("Level") + ' - ', font="Arial 16").pack(side='left') self.label_level = Label(frame, font="Arial 16", text=_("Unknown")) self.label_level.pack(side='left') self.level = "unknown" # puzzle level # --- frame contenant la grille de sudoku self.frame_puzzle = Frame(self, style="bg.TFrame") self.frame_pause = Frame(self, style="case.TFrame") self.frame_pause.grid_propagate(False) self.frame_pause.columnconfigure(0, weight=1) self.frame_pause.rowconfigure(0, weight=1) Label(self.frame_pause, text='PAUSE', style='pause.TLabel', font='Arial 30 bold').grid() # --- placement frame_nb.grid(row=1, column=6, sticky='en', pady=0, padx=(0, 30)) self.frame_puzzle.grid(row=1, columnspan=5, padx=(30, 15)) self.tps.grid(row=2, column=0, sticky="e", padx=(30, 10), pady=30) self.b_pause.grid(row=2, column=1, sticky="w", padx=2, pady=30) self.b_restart.grid(row=2, column=2, sticky="w", padx=2, pady=30) self.b_undo.grid(row=2, column=3, sticky="e", pady=30, padx=2) self.b_redo.grid(row=2, column=4, sticky="w", pady=30, padx=(2, 10)) # --- menu menu = Menu(self, tearoff=0) menu_nouveau = Menu(menu, tearoff=0) menu_levels = Menu(menu_nouveau, tearoff=0) menu_levels.add_command(label=_("Easy"), command=self.new_easy) menu_levels.add_command(label=_("Medium"), command=self.new_medium) menu_levels.add_command(label=_("Difficult"), command=self.new_difficult) menu_nouveau.add_cascade(label=_("Level"), menu=menu_levels) menu_nouveau.add_command(label=_("Generate a puzzle"), command=self.genere_grille, accelerator="Ctrl+G") menu_nouveau.add_command(label=_("Empty grid"), command=self.grille_vide, accelerator="Ctrl+N") menu_ouvrir = Menu(menu, tearoff=0) menu_ouvrir.add_command(label=_("Game"), command=self.import_partie, accelerator="Ctrl+O") menu_ouvrir.add_command(label=_("Puzzle"), command=self.import_grille, accelerator="Ctrl+Shift+O") menu_game = Menu(menu, tearoff=0) menu_game.add_command(label=_("Restart"), command=self.recommence) menu_game.add_command(label=_("Solve"), command=self.resolution) menu_game.add_command(label=_("Save"), command=self.sauvegarde, accelerator="Ctrl+S") menu_game.add_command(label=_("Export"), command=self.export_impression, accelerator="Ctrl+E") menu_game.add_command(label=_("Evaluate level"), command=self.evaluate_level) menu_language = Menu(menu, tearoff=0) self.langue = StringVar(self) self.langue.set(cst.LANGUE[:2]) menu_language.add_radiobutton(label="Français", variable=self.langue, value="fr", command=self.translate) menu_language.add_radiobutton(label="English", variable=self.langue, value="en", command=self.translate) menu_help = Menu(menu, tearoff=0) menu_help.add_command(label=_("Help"), command=self.aide, accelerator='F1') menu_help.add_command(label=_("About"), command=self.about) menu.add_cascade(label=_("New"), menu=menu_nouveau) menu.add_cascade(label=_("Open"), menu=menu_ouvrir) menu.add_cascade(label=_("Game"), menu=menu_game) menu.add_cascade(label=_("Language"), menu=menu_language) menu.add_command(label=_("Statistics"), command=self.show_stat) menu.add_cascade(label=_("Help"), menu=menu_help) self.configure(menu=menu) # --- clavier popup self.clavier = None # --- cases self.nb_cases_remplies = 0 self.blocs = np.zeros((9, 9), dtype=object) for i in range(9): for j in range(9): self.blocs[i, j] = Case(self.frame_puzzle, i, j, self.update_nbs, width=50, height=50) px, py = 1, 1 if i % 3 == 2 and i != 8: py = (1, 3) if j % 3 == 2 and j != 8: px = (1, 3) self.blocs[i, j].grid(row=i, column=j, padx=px, pady=py) self.blocs[i, j].grid_propagate(0) # --- undo/redo stacks self._undo_stack = [] self._redo_stack = [] # --- raccourcis clavier et actions de la souris self.bind("<Button>", self.edit_case) self.bind("<Control-z>", lambda e: self.undo()) self.bind("<Control-y>", lambda e: self.redo()) self.bind("<Control-s>", lambda e: self.sauvegarde()) self.bind("<Control-e>", lambda e: self.export_impression()) self.bind("<Control-o>", lambda e: self.import_partie()) self.bind("<Control-Shift-O>", lambda e: self.import_grille()) self.bind("<Control-n>", lambda e: self.grille_vide()) self.bind("<Control-g>", lambda e: self.genere_grille()) self.bind("<FocusOut>", self.focus_out) self.bind("<F1>", self.aide) # --- open game if file: try: self.load_sudoku(file) except FileNotFoundError: one_button_box(self, _("Error"), _("The file %(file)r does not exist.") % file, image=self.im_erreur) except (KeyError, EOFError, UnpicklingError): try: self.load_grille(file) except Exception: one_button_box(self, _("Error"), _("This file is not a valid sudoku file."), image=self.im_erreur) elif exists(cst.PATH_SAVE): self.load_sudoku(cst.PATH_SAVE) remove(cst.PATH_SAVE) @property def level(self): return self._level @level.setter def level(self, level): self._level = level self.label_level.configure(text=_(level.capitalize())) def update_nbs(self, nb, delta): self.progression[nb - 1].nb += delta def reset_nbs(self): for p in self.progression: p.nb = 0 def evaluate_level(self): grille = Grille() for i in range(9): for j in range(9): val = self.blocs[i, j].get_val() if val: grille.ajoute_init(i, j, val) self.level = difficulte_grille(grille) def show_stat(self): """ show best times """ def reset(): """ reset best times """ for level in ["easy", "medium", "difficult"]: CONFIG.set("Statistics", level, "") top.destroy() if self.chrono_on: self.play_pause() top = Toplevel(self) top.transient(self) top.columnconfigure(1, weight=1) top.resizable(0, 0) top.title(_("Statistics")) top.grab_set() Label(top, text=_("Best times"), font="Sans 12 bold").grid(row=0, columnspan=2, padx=30, pady=10) for i, level in enumerate(["easy", "medium", "difficult"]): Label(top, text=_(level.capitalize()), font="Sans 10 bold").grid(row=i + 1, column=0, padx=(20, 4), pady=4, sticky="e") tps = CONFIG.get("Statistics", level) if tps: tps = int(tps) m = tps // 60 s = tps % 60 Label(top, text=" %i min %i s" % (m, s), font="Sans 10").grid(row=i + 1, column=1, sticky="w", pady=4, padx=(4, 20)) Button(top, text=_("Close"), command=top.destroy).grid(row=4, column=0, padx=(10, 4), pady=10) Button(top, text=_("Clear"), command=reset).grid(row=4, column=1, padx=(4, 10), pady=10) def new_easy(self): nb = np.random.randint(1, 101) fichier = join(cst.PUZZLES_LOCATION, "easy", "puzzle_easy_%i.txt" % nb) self.import_grille(fichier) self.level = "easy" def new_medium(self): nb = np.random.randint(1, 101) fichier = join(cst.PUZZLES_LOCATION, "medium", "puzzle_medium_%i.txt" % nb) self.import_grille(fichier) self.level = "medium" def new_difficult(self): nb = np.random.randint(1, 101) fichier = join(cst.PUZZLES_LOCATION, "difficult", "puzzle_difficult_%i.txt" % nb) self.import_grille(fichier) self.level = "difficult" def translate(self): """ changement de la langue de l'interface """ one_button_box(self, _("Information"), _("The language setting will take effect after restarting the application"), image=self.im_info) CONFIG.set("General", "language", self.langue.get()) def focus_out(self, event): """ met en pause si la fenêtre n'est plus au premier plan """ try: if not self.focus_get() and self.chrono_on: self.play_pause() except KeyError: # erreur déclenchée par la présence d'une tkMessagebox if self.chrono_on: self.play_pause() def stacks_reinit(self): """efface l'historique des actions""" self._undo_stack.clear() self._redo_stack.clear() self.b_undo.configure(state="disabled") self.b_redo.configure(state="disabled") def stacks_modif(self, action): """Record action and clear redo stack.""" self._undo_stack.append(action) self.b_undo.configure(state="normal") self.b_redo.configure(state="disabled") self._redo_stack.clear() def about(self): if self.chrono_on: self.play_pause() About(self) def aide(self, event=None): if self.chrono_on: self.play_pause() Aide(self) def quitter(self): rep = _("Yes") if self.debut: rep = two_button_box(self, _("Confirmation"), _("Do you want to interrupt the current puzzle?"), _("Yes"), _("No"), image=self.im_question) if rep == _("Yes"): if self.debut: self.save(cst.PATH_SAVE) self.destroy() def undo(self): if self._undo_stack and self.chrono_on: self.b_redo.configure(state="normal") i, j, val_prec, pos_prec, modifs, val, pos = self._undo_stack.pop(-1) self._redo_stack.append((i, j, val_prec, pos_prec, modifs, val, pos)) if not self._undo_stack: self.b_undo.configure(state="disabled") if self.blocs[i, j].get_val(): self.modifie_nb_cases_remplies(-1) self.update_nbs(self.blocs[i, j].get_val(), -1) self.blocs[i, j].efface_case() if val_prec: self.modifie_nb_cases_remplies(self.blocs[i, j].edit_chiffre(val_prec)) if not self.test_case(i, j, val): self.update_grille(i, j, val) else: for nb in pos_prec: v = int(nb) self.modifie_nb_cases_remplies(self.blocs[i, j].edit_possibilite(v)) self.test_possibilite(i, j, v) for k, l in modifs: self.blocs[k, l].edit_possibilite(val) def redo(self): if self._redo_stack and self.chrono_on: self.b_undo.configure(state="normal") i, j, val_prec, pos_prec, modifs, val, pos = self._redo_stack.pop(-1) self._undo_stack.append((i, j, val_prec, pos_prec, modifs, val, pos)) if not self._redo_stack: self.b_redo.configure(state="disabled") val_prec = self.blocs[i, j].get_val() if val_prec: self.modifie_nb_cases_remplies(-1) self.update_nbs(val_prec, -1) self.blocs[i, j].efface_case() if val: self.modifie_nb_cases_remplies(self.blocs[i, j].edit_chiffre(val)) if not self.test_case(i, j, val_prec): self.update_grille(i, j, val_prec) else: for nb in pos: v = int(nb) self.modifie_nb_cases_remplies(self.blocs[i, j].edit_possibilite(v)) self.test_possibilite(i, j, v) def restart(self, m=0, s=0): """ réinitialise le chrono et les boutons """ self.chrono = [m, s] self.chrono_on = False self.debut = False self.tps.configure(text=" %02i:%02i" % tuple(self.chrono)) self.b_undo.configure(state="disabled") self.b_pause.configure(state="disabled", image=self.im_pause) self.b_redo.configure(state="disabled") self.b_restart.configure(state="disabled") self.stacks_reinit() self.frame_pause.place_forget() def play_pause(self): """ Démarre le chrono s'il était arrêté, le met en pause sinon """ if self.debut: if self.chrono_on: self.chrono_on = False self.b_pause.configure(image=self.im_play) self.b_redo.configure(state="disabled") self.b_undo.configure(state="disabled") self.tooltip_wrapper.set_tooltip_text(self.b_pause, _("Resume game")) self.frame_pause.place(in_=self.frame_puzzle, x=0, y=0, anchor='nw', relwidth=1, relheight=1) elif self.nb_cases_remplies != 81: self.chrono_on = True self.b_pause.configure(image=self.im_pause) self.tps.after(1000, self.affiche_chrono) if self._undo_stack: self.b_undo.configure(state="normal") if self._redo_stack: self.b_redo.configure(state="normal") self.tooltip_wrapper.set_tooltip_text(self.b_pause, _("Pause game")) self.frame_pause.place_forget() def affiche_chrono(self): """ Met à jour l'affichage du temps """ if self.chrono_on: self.chrono[1] += 1 if self.chrono[1] == 60: self.chrono[0] += 1 self.chrono[1] = 0 self.tps.configure(text=" %02i:%02i" % tuple(self.chrono)) self.tps.after(1000, self.affiche_chrono) def modifie_nb_cases_remplies(self, nb): self.nb_cases_remplies += nb def edit_case(self, event): if event.num in [1, 3]: if not self.debut and self.nb_cases_remplies != 81: self.debut = True self.b_pause.configure(state="normal") self.b_restart.configure(state="normal") self.play_pause() if str(event.widget) != "." and self.chrono_on: if self.clavier: self.clavier.quitter() ref = self.blocs[0, 0].winfo_parent() case = event.widget.grid_info().get("in", None) if str(case) == ref: case = event.widget try: if case.is_modifiable(): if event.num == 1: self.clavier = Clavier(self, case, "val") elif event.num == 3: self.clavier = Clavier(self, case, "possibilite") self.clavier.display("+%i+%i" % (case.winfo_rootx() - 25, case.winfo_rooty() + 50)) except AttributeError: if self.clavier: self.clavier.quitter() elif self.clavier: self.clavier.quitter() def test_case(self, i, j, val_prec=0): """ Teste si la valeur de la case est en contradiction avec celles des autres cases de la ligne / colonne / bloc et renvoie True s'il y a une erreur.""" val = self.blocs[i, j].get_val() a, b = i // 3, j // 3 error = False if val: if ((self.blocs[i, :] == val).sum() > 1 or (self.blocs[:, j] == val).sum() > 1 or (self.blocs[3 * a: 3 * (a + 1), 3 * b: 3 * (b + 1)] == val).sum() > 1): # erreur ! self.blocs[i, j].affiche_erreur() error = True if val_prec: # a number was removed, remove obsolete errors line = self.blocs[i, :] == val_prec column = self.blocs[:, j] == val_prec bloc = self.blocs[3 * a: 3 * (a + 1), 3 * b: 3 * (b + 1)] == val_prec if line.sum() == 1: self.blocs[i, line.argmax()].no_error() self.test_case(i, line.argmax()) if column.sum() == 1: self.blocs[column.argmax(), j].no_error() self.test_case(column.argmax(), j) if bloc.sum() == 1: x, y = divmod(bloc.argmax(), 3) self.blocs[3 * a + x, 3 * b + y].no_error() self.test_case(3 * a + x, 3 * b + y) return error def test_possibilite(self, i, j, val): """ Teste si la possibilité val de la case est en contradiction avec les valeurs des autres cases de la ligne / colonne / bloc """ a, b = i // 3, j // 3 if ((self.blocs[i, :] == val).sum() > 0 or (self.blocs[:, j] == val).sum() > 0 or (self.blocs[3 * a: 3 * (a + 1), 3 * b: 3 * (b + 1)] == val).sum() > 0): # erreur ! self.blocs[i, j].affiche_erreur_possibilite(val) def test_remplie(self): """ Test si la grille est remplie """ if self.nb_cases_remplies == 81: grille = Grille() for i in range(9): for j in range(9): val = self.blocs[i, j].get_val() if val: grille.ajoute_init(i, j, val) sol = grille.solve() if type(sol) == np.ndarray: self.play_pause() self.frame_pause.place_forget() one_button_box(self, _("Information"), _("You solved the puzzle in %(min)i minutes and %(sec)i secondes.") % {"min": self.chrono[0], "sec": self.chrono[1]}, image=self.im_info) if self.level != "unknown": best = CONFIG.get("Statistics", self.level) current = self.chrono[0] * 60 + self.chrono[1] if best: best = int(best) if current < best: CONFIG.set("Statistics", self.level, str(current)) else: CONFIG.set("Statistics", self.level, str(current)) self.b_pause.configure(state="disabled") self.debut = False else: i, j = sol[1] if self.blocs[i, j].get_val(): self.blocs[i, j].affiche_erreur() one_button_box(self, _("Information"), _("There is a mistake."), image=self.im_info) def update_grille(self, i, j, val_prec=0): """ Enlève les possibilités devenues impossibles suite à l'ajout d'une valeur dans la case (i, j) """ val = self.blocs[i, j].get_val() modif = [] a, b = i // 3, j // 3 if val_prec: x, y = divmod(val_prec - 1, 3) for k, (line, column, bloc) in enumerate(zip(self.blocs[i, :], self.blocs[:, j], self.blocs[3 * a: 3 * (a + 1), 3 * b: 3 * (b + 1)].flatten())): # works because if line is bloc then pos1 is pos3 and both are edited at once pos1 = line.get_possibilites() pos2 = column.get_possibilites() pos3 = bloc.get_possibilites() if val in pos1: self.blocs[i, k].edit_possibilite(val) modif.append((i, k)) if val in pos2: self.blocs[k, j].edit_possibilite(val) modif.append((k, j)) if val in pos3: m, n = divmod(k, 3) self.blocs[3 * a + m, 3 * b + n].edit_possibilite(val) modif.append((3 * a + m, 3 * b + n)) if val_prec: if val_prec in pos1: self.blocs[i, k].pas_erreur(x, y) self.test_possibilite(i, k, val_prec) if val_prec in pos2: self.blocs[k, j].pas_erreur(x, y) self.test_possibilite(k, j, val_prec) if val_prec in pos3: m, n = divmod(k, 3) m, n = 3 * a + m, 3 * b + n if m != i and n != j: self.blocs[m, n].pas_erreur(x, y) self.test_possibilite(m, n, val_prec) return modif def set_clavier(self, c): self.clavier = c def grille_vide(self): rep = _("Yes") if self.debut: rep = two_button_box(self, _("Confirmation"), _("Do you want to abandon the current puzzle?"), _("Yes"), _("No"), self.im_question) if rep == _("Yes"): self.nb_cases_remplies = 0 self.restart() self.level = "unknown" self.reset_nbs() for i in range(9): for j in range(9): self.blocs[i, j].set_modifiable(True) self.blocs[i, j].efface_case() def genere_grille(self): """ Génère une nouvelle grille """ if self.chrono_on: self.play_pause() rep = _("Yes") if self.debut: rep = two_button_box(self, _("Confirmation"), _("Do you want to abandon the current puzzle?"), _("Yes"), _("No"), self.im_question) if rep == _("Yes"): self.configure(cursor="watch") self.update() rep2 = _("Retry") while rep2 == _("Retry"): grille = genere_grille() diff = difficulte_grille(grille) nb = grille.nb_cases_remplies() self.configure(cursor="") rep2 = two_button_box(self, _("Information"), _("The generated puzzle contains %(nb)i numbers and its level is %(difficulty)s.") % ({"nb": nb, "difficulty": _(diff.capitalize())}), _("Play"), _("Retry"), image=self.im_info) if rep2 == _("Play"): self.level = diff self.affiche_grille(grille.get_sudoku()) def recommence(self): if self.chrono_on: self.play_pause() rep = _("Yes") if self.debut: rep = two_button_box(self, _("Confirmation"), _("Do you really want to start again?"), _("Yes"), _("No"), self.im_question) if rep == _("Yes"): self.reset_nbs() for i in range(9): for j in range(9): if self.blocs[i, j].is_modifiable(): if self.blocs[i, j].get_val(): self.nb_cases_remplies -= 1 self.blocs[i, j].efface_case() else: self.update_nbs(self.blocs[i, j].get_val(), 1) self.restart() elif self.debut: self.play_pause() def save(self, path): grille = np.zeros((9, 9), dtype=int) modif = np.zeros((9, 9), dtype=bool) possibilites = [] for i in range(9): possibilites.append([]) for j in range(9): grille[i, j] = self.blocs[i, j].get_val() modif[i, j] = self.blocs[i, j].is_modifiable() possibilites[i].append(self.blocs[i, j].get_possibilites()) with open(path, "wb") as fich: p = Pickler(fich) p.dump(grille) p.dump(modif) p.dump(possibilites) p.dump(self.chrono) p.dump(self.level) def sauvegarde(self): if self.chrono_on: self.play_pause() fichier = asksaveasfilename(initialdir=cst.INITIALDIR, defaultextension='.sudoku', filetypes=[('Sudoku', '*.sudoku')]) if fichier: self.save(fichier) def affiche_grille(self, grille): """ Affiche la grille """ self.nb_cases_remplies = 0 self.restart() self.reset_nbs() for i in range(9): for j in range(9): nb = grille[i, j] self.blocs[i, j].efface_case() if nb: self.blocs[i, j].set_modifiable(False) self.nb_cases_remplies += 1 self.blocs[i, j].edit_chiffre(nb) else: self.blocs[i, j].set_modifiable(True) def load_sudoku(self, file): with open(file, "rb") as fich: dp = Unpickler(fich) grille = dp.load() modif = dp.load() possibilites = dp.load() chrono = dp.load() self.level = dp.load() self.nb_cases_remplies = 0 self.reset_nbs() self.restart(*chrono) for i in range(9): for j in range(9): self.blocs[i, j].efface_case() if grille[i, j]: self.nb_cases_remplies += 1 self.blocs[i, j].edit_chiffre(grille[i, j]) else: for pos in possibilites[i][j]: self.blocs[i, j].edit_possibilite(pos) self.blocs[i, j].set_modifiable(modif[i, j]) def import_partie(self): """ importe une partie stockée dans un fichier .sudoku """ if self.chrono_on: self.play_pause() rep = _("Yes") if self.debut: rep = two_button_box(self, _("Confirmation"), _("Do you want to abandon the current puzzle?"), _("Yes"), _("No"), self.im_question) if rep == _("Yes"): fichier = askopenfilename(initialdir=cst.INITIALDIR, defaultextension='.sudoku', filetypes=[('Sudoku', '*.sudoku')]) if fichier: try: self.load_sudoku(fichier) except FileNotFoundError: one_button_box(self, _("Error"), _("The file %(file)r does not exist.") % fichier, image=self.im_erreur) except (KeyError, EOFError, UnpicklingError): one_button_box(self, _("Error"), _("This file is not a valid sudoku file."), image=self.im_erreur) elif self.debut: self.play_pause() def resolution_init(self): """ Résolution de la grille initiale (sans tenir compte des valeurs rentrées par l'utilisateur. """ grille = Grille() for i in range(9): for j in range(9): if not self.blocs[i, j].is_modifiable(): val = self.blocs[i, j].get_val() grille.ajoute_init(i, j, val) self.configure(cursor="watch") self.update() sol = grille.solve() self.configure(cursor="") if type(sol) == np.ndarray: for i in range(9): for j in range(9): val = self.blocs[i, j].get_val() if not val: self.blocs[i, j].edit_chiffre(sol[i, j]) self.blocs[i, j].affiche_solution() elif self.blocs[i, j].is_modifiable(): if val != sol[i, j]: self.blocs[i, j].edit_chiffre(sol[i, j]) self.blocs[i, j].affiche_erreur() self.restart() self.nb_cases_remplies = 81 elif sol[1]: i, j = sol[1] if self.blocs[i, j].get_val(): self.blocs[i, j].affiche_erreur() one_button_box(self, _("Error"), _("The grid is wrong. It cannot be solved."), image=self.im_erreur) else: one_button_box(self, _("Error"), _("Resolution failed."), image=self.im_erreur) def resolution(self): if self.chrono_on: self.play_pause() rep = two_button_box(self, _("Confirmation"), _("Do you really want to get the solution?"), _("Yes"), _("No"), image=self.im_question) if rep == _("Yes"): self.frame_pause.place_forget() grille = Grille() for i in range(9): for j in range(9): val = self.blocs[i, j].get_val() if val: grille.ajoute_init(i, j, val) self.configure(cursor="watch") self.update() sol = grille.solve() self.configure(cursor="") if type(sol) == np.ndarray: for i in range(9): for j in range(9): val = self.blocs[i, j].get_val() if not val: self.blocs[i, j].edit_chiffre(sol[i, j]) self.blocs[i, j].affiche_solution() self.restart() self.b_restart.configure(state="normal") self.nb_cases_remplies = 81 elif sol[1]: i, j = sol[1] if self.blocs[i, j].get_val(): self.blocs[i, j].affiche_erreur() i, j = 0, 0 while i < 9 and self.blocs[i, j].is_modifiable(): j += 1 if j == 9: i += 1 j = 0 if i < 9: # il y a au moins une case de type "initial" rep = two_button_box(self, _("Error"), _("The grid is wrong. It cannot be solved. Do you want the solution of the initial grid?"), _("Yes"), _("No"), image=self.im_erreur) if rep == _("Yes"): self.resolution_init() else: one_button_box(self, _("Error"), _("The grid is wrong. It cannot be solved."), image=self.im_erreur) else: one_button_box(self, _("Error"), _("Resolution failed."), image=self.im_erreur) def load_grille(self, file): gr = np.loadtxt(file, dtype=int) if gr.shape == (9, 9): self.affiche_grille(gr) self.level = "unknown" else: one_button_box(self, _("Error"), _("This is not a 9x9 sudoku grid."), image=self.im_erreur) def import_grille(self, fichier=None): """ importe une grille stockée dans un fichier txt sous forme de chiffres séparés par des espaces (0 = case vide) """ if self.chrono_on: self.play_pause() rep = _("Yes") if self.debut: rep = two_button_box(self, _("Confirmation"), _("Do you want to abandon the current puzzle?"), _("Yes"), _("No"), self.im_question) if rep == _("Yes"): if not fichier: fichier = askopenfilename(initialdir=cst.INITIALDIR, defaultextension='.txt', filetypes=[('Text', '*.txt'), ('Tous les fichiers', "*")]) if fichier: try: self.load_grille(fichier) except (ValueError, UnicodeDecodeError): one_button_box(self, _("Error"), _("The file does not have the right format. It should be a .txt file with cell values separated by one space. 0 means empty cell."), image=self.im_erreur) except FileNotFoundError: one_button_box(self, _("Error"), _("The file %(file)r does not exist.") % fichier, image=self.im_erreur) elif self.debut: self.play_pause() def export_impression(self): """ exporte la grille en image (pour pouvoir l'imprimer) """ if self.chrono_on: self.play_pause() fichier = asksaveasfilename(title=_("Export"), initialdir=cst.INITIALDIR, defaultextension='.png', filetypes=[('PNG', '*.png'), ('JPEG', 'jpg')]) if fichier: grille = np.zeros((9, 9), dtype=int) for i in range(9): for j in range(9): grille[i, j] = self.blocs[i, j].get_val() font = ImageFont.truetype("arial.ttf", 64) im = Image.new("RGB", (748, 748), "white") draw = ImageDraw.Draw(im) i = 0 l = 1 while i < 10: if i % 3 == 0: w = 4 else: w = 2 draw.line((l, 1, l, 748), width=w, fill="black") draw.line((1, l, 748, l), width=w, fill="black") l += 80 + w i += 1 for i in range(9): for j in range(9): if grille[i, j]: draw.text((26 + j * 82 + 2 * (j // 3), 10 + i * 82 + 2 * (i // 3)), " %i" % grille[i, j], fill="black", font=font) del draw im.save(fichier)
class Sticky(Toplevel): """ Sticky note class """ def __init__(self, master, key, **kwargs): """ Create a new sticky note. master: main app key: key identifying this note in master.note_data kwargs: dictionnary of the other arguments (title, txt, category, color, tags, geometry, locked, checkboxes, images, rolled) """ Toplevel.__init__(self, master) # --- window properties self.id = key self.is_locked = not (kwargs.get("locked", False)) self.images = [] self.links = {} self.latex = {} self.nb_links = 0 self.title('mynotes%s' % key) self.attributes("-type", "splash") self.attributes("-alpha", CONFIG.getint("General", "opacity") / 100) self.focus_force() # window geometry self.update_idletasks() self.geometry(kwargs.get("geometry", '220x235')) self.save_geometry = kwargs.get("geometry", '220x235') self.update() self.rowconfigure(1, weight=1) self.minsize(10, 10) self.protocol("WM_DELETE_WINDOW", self.hide) # --- style self.style = Style(self) self.style.configure(self.id + ".TCheckbutton", selectbackground="red") self.style.map('TEntry', selectbackground=[('!focus', '#c3c3c3')]) selectbg = self.style.lookup('TEntry', 'selectbackground', ('focus', )) self.style.configure("sel.TCheckbutton", background=selectbg) self.style.map("sel.TCheckbutton", background=[("active", selectbg)]) # --- note elements # title font_title = "%s %s" % (CONFIG.get("Font", "title_family").replace( " ", "\ "), CONFIG.get("Font", "title_size")) style = CONFIG.get("Font", "title_style").split(",") if style: font_title += " " font_title += " ".join(style) self.title_var = StringVar(master=self, value=kwargs.get("title", _("Title"))) self.title_label = Label(self, textvariable=self.title_var, anchor="center", style=self.id + ".TLabel", font=font_title) self.title_entry = Entry(self, textvariable=self.title_var, exportselection=False, justify="center", font=font_title) # buttons/icons self.roll = Label(self, image="img_roll", style=self.id + ".TLabel") self.close = Label(self, image="img_close", style=self.id + ".TLabel") self.im_lock = PhotoImage(master=self, file=IM_LOCK) self.cadenas = Label(self, style=self.id + ".TLabel") # corner grip self.corner = Sizegrip(self, style=self.id + ".TSizegrip") # texte font_text = "%s %s" % (CONFIG.get("Font", "text_family").replace( " ", "\ "), CONFIG.get("Font", "text_size")) self.txt = Text(self, wrap='word', undo=True, selectforeground='white', inactiveselectbackground=selectbg, selectbackground=selectbg, tabs=(10, 'right', 21, 'left'), relief="flat", borderwidth=0, highlightthickness=0, font=font_text) # tags self.txt.tag_configure("bold", font="%s bold" % font_text) self.txt.tag_configure("italic", font="%s italic" % font_text) self.txt.tag_configure("bold-italic", font="%s bold italic" % font_text) self.txt.tag_configure("underline", underline=True, selectforeground="white") self.txt.tag_configure("overstrike", overstrike=True, selectforeground="white") self.txt.tag_configure("center", justify="center") self.txt.tag_configure("left", justify="left") self.txt.tag_configure("right", justify="right") self.txt.tag_configure("link", foreground="blue", underline=True, selectforeground="white") self.txt.tag_configure("list", lmargin1=0, lmargin2=21, tabs=(10, 'right', 21, 'left')) self.txt.tag_configure("todolist", lmargin1=0, lmargin2=21, tabs=(10, 'right', 21, 'left')) margin = 2 * Font(self, font=font_text).measure("m") self.txt.tag_configure("enum", lmargin1=0, lmargin2=margin + 5, tabs=(margin, 'right', margin + 5, 'left')) for coul in TEXT_COLORS.values(): self.txt.tag_configure(coul, foreground=coul, selectforeground="white") self.txt.tag_configure(coul + "-underline", foreground=coul, selectforeground="white", underline=True) self.txt.tag_configure(coul + "-overstrike", foreground=coul, overstrike=True, selectforeground="white") # --- menus # --- * menu on title self.menu = Menu(self, tearoff=False) # note color menu_note_color = Menu(self.menu, tearoff=False) colors = list(COLORS.keys()) colors.sort() for coul in colors: menu_note_color.add_command( label=coul, command=lambda key=coul: self.change_color(key)) # category self.category = StringVar( self, kwargs.get("category", CONFIG.get("General", "default_category"))) self.menu_categories = Menu(self.menu, tearoff=False) categories = CONFIG.options("Categories") categories.sort() for cat in categories: self.menu_categories.add_radiobutton(label=cat.capitalize(), value=cat, variable=self.category, command=self.change_category) # position: normal, always above, always below self.position = StringVar( self, kwargs.get("position", CONFIG.get("General", "position"))) menu_position = Menu(self.menu, tearoff=False) menu_position.add_radiobutton(label=_("Always above"), value="above", variable=self.position, command=self.set_position_above) menu_position.add_radiobutton(label=_("Always below"), value="below", variable=self.position, command=self.set_position_below) menu_position.add_radiobutton(label=_("Normal"), value="normal", variable=self.position, command=self.set_position_normal) # mode: note, list, todo list menu_mode = Menu(self.menu, tearoff=False) self.mode = StringVar(self, kwargs.get("mode", "note")) menu_mode.add_radiobutton(label=_("Note"), value="note", variable=self.mode, command=self.set_mode_note) menu_mode.add_radiobutton(label=_("List"), value="list", variable=self.mode, command=self.set_mode_list) menu_mode.add_radiobutton(label=_("ToDo List"), value="todolist", variable=self.mode, command=self.set_mode_todolist) menu_mode.add_radiobutton(label=_("Enumeration"), value="enum", variable=self.mode, command=self.set_mode_enum) self.menu.add_command(label=_("Delete"), command=self.delete) self.menu.add_cascade(label=_("Category"), menu=self.menu_categories) self.menu.add_cascade(label=_("Color"), menu=menu_note_color) self.menu.add_command(label=_("Lock"), command=self.lock) self.menu.add_cascade(label=_("Position"), menu=menu_position) self.menu.add_cascade(label=_("Mode"), menu=menu_mode) # --- * menu on main text self.menu_txt = Menu(self.txt, tearoff=False) # style menu_style = Menu(self.menu_txt, tearoff=False) menu_style.add_command(label=_("Bold"), command=lambda: self.toggle_text_style("bold")) menu_style.add_command( label=_("Italic"), command=lambda: self.toggle_text_style("italic")) menu_style.add_command(label=_("Underline"), command=self.toggle_underline) menu_style.add_command(label=_("Overstrike"), command=self.toggle_overstrike) # text alignment menu_align = Menu(self.menu_txt, tearoff=False) menu_align.add_command(label=_("Left"), command=lambda: self.set_align("left")) menu_align.add_command(label=_("Right"), command=lambda: self.set_align("right")) menu_align.add_command(label=_("Center"), command=lambda: self.set_align("center")) # text color menu_colors = Menu(self.menu_txt, tearoff=False) colors = list(TEXT_COLORS.keys()) colors.sort() for coul in colors: menu_colors.add_command(label=coul, command=lambda key=coul: self. change_sel_color(TEXT_COLORS[key])) # insert menu_insert = Menu(self.menu_txt, tearoff=False) menu_insert.add_command(label=_("Symbols"), command=self.add_symbols) menu_insert.add_command(label=_("Checkbox"), command=self.add_checkbox) menu_insert.add_command(label=_("Image"), command=self.add_image) menu_insert.add_command(label=_("Date"), command=self.add_date) menu_insert.add_command(label=_("Link"), command=self.add_link) if LATEX: menu_insert.add_command(label="LaTex", command=self.add_latex) self.menu_txt.add_cascade(label=_("Style"), menu=menu_style) self.menu_txt.add_cascade(label=_("Alignment"), menu=menu_align) self.menu_txt.add_cascade(label=_("Color"), menu=menu_colors) self.menu_txt.add_cascade(label=_("Insert"), menu=menu_insert) # --- restore note content/appearence self.color = kwargs.get("color", CONFIG.get("Categories", self.category.get())) self.txt.insert('1.0', kwargs.get("txt", "")) self.txt.edit_reset() # clear undo stack # restore inserted objects (images and checkboxes) # we need to restore objects with increasing index to avoid placment errors indexes = list(kwargs.get("inserted_objects", {}).keys()) indexes.sort(key=sorting) for index in indexes: kind, val = kwargs["inserted_objects"][index] if kind == "checkbox": ch = Checkbutton(self.txt, takefocus=False, style=self.id + ".TCheckbutton") if val: ch.state(("selected", )) self.txt.window_create(index, window=ch) elif kind == "image": if os.path.exists(val): self.images.append(PhotoImage(master=self.txt, file=val)) self.txt.image_create(index, image=self.images[-1], name=val) # restore tags for tag, indices in kwargs.get("tags", {}).items(): if indices: self.txt.tag_add(tag, *indices) for link in kwargs.get("links", {}).values(): self.nb_links += 1 self.links[self.nb_links] = link self.txt.tag_bind("link#%i" % self.nb_links, "<Button-1>", lambda e, l=link: open_url(l)) for img, latex in kwargs.get("latex", {}).items(): self.latex[img] = latex if LATEX: self.txt.tag_bind(img, '<Double-Button-1>', lambda e, im=img: self.add_latex(im)) mode = self.mode.get() if mode != "note": self.txt.tag_add(mode, "1.0", "end") self.txt.focus_set() self.lock() if kwargs.get("rolled", False): self.rollnote() if self.position.get() == "above": self.set_position_above() elif self.position.get() == "below": self.set_position_below() # --- placement # titlebar if CONFIG.get("General", "buttons_position") == "right": # right = lock icon - title - roll - close self.columnconfigure(1, weight=1) self.roll.grid(row=0, column=2, sticky="e") self.close.grid(row=0, column=3, sticky="e", padx=(0, 2)) self.cadenas.grid(row=0, column=0, sticky="w") self.title_label.grid(row=0, column=1, sticky="ew", pady=(1, 0)) else: # left = close - roll - title - lock icon self.columnconfigure(2, weight=1) self.roll.grid(row=0, column=1, sticky="w") self.close.grid(row=0, column=0, sticky="w", padx=(2, 0)) self.cadenas.grid(row=0, column=3, sticky="e") self.title_label.grid(row=0, column=2, sticky="ew", pady=(1, 0)) # body self.txt.grid(row=1, columnspan=4, column=0, sticky="ewsn", pady=(1, 4), padx=4) self.corner.lift(self.txt) self.corner.place(relx=1.0, rely=1.0, anchor="se") # --- bindings self.bind("<FocusOut>", self.save_note) self.bind('<Configure>', self.bouge) self.bind('<Button-1>', self.change_focus, True) self.close.bind("<Button-1>", self.hide) self.close.bind("<Enter>", self.enter_close) self.close.bind("<Leave>", self.leave_close) self.roll.bind("<Button-1>", self.rollnote) self.roll.bind("<Enter>", self.enter_roll) self.roll.bind("<Leave >", self.leave_roll) self.title_label.bind("<Double-Button-1>", self.edit_title) self.title_label.bind("<ButtonPress-1>", self.start_move) self.title_label.bind("<ButtonRelease-1>", self.stop_move) self.title_label.bind("<B1-Motion>", self.move) self.title_label.bind('<Button-3>', self.show_menu) self.title_entry.bind("<Return>", lambda e: self.title_entry.place_forget()) self.title_entry.bind("<FocusOut>", lambda e: self.title_entry.place_forget()) self.title_entry.bind("<Escape>", lambda e: self.title_entry.place_forget()) self.txt.tag_bind("link", "<Enter>", lambda event: self.txt.configure(cursor="hand1")) self.txt.tag_bind("link", "<Leave>", lambda event: self.txt.configure(cursor="")) self.txt.bind("<FocusOut>", self.save_note) self.txt.bind('<Button-3>', self.show_menu_txt) # add binding to the existing class binding so that the selected text # is erased on pasting self.txt.bind("<Control-v>", self.paste) self.corner.bind('<ButtonRelease-1>', self.resize) # --- keyboard shortcuts self.txt.bind('<Control-b>', lambda e: self.toggle_text_style('bold')) self.txt.bind('<Control-i>', lambda e: self.toggle_text_style('italic')) self.txt.bind('<Control-u>', lambda e: self.toggle_underline()) self.txt.bind('<Control-r>', lambda e: self.set_align('right')) self.txt.bind('<Control-l>', lambda e: self.set_align('left')) def __setattr__(self, name, value): object.__setattr__(self, name, value) if name == "color": self.style.configure(self.id + ".TSizegrip", background=self.color) self.style.configure(self.id + ".TLabel", background=self.color) self.style.configure("close" + self.id + ".TLabel", background=self.color) self.style.configure("roll" + self.id + ".TLabel", background=self.color) self.style.map(self.id + ".TLabel", background=[("active", self.color)]) self.style.configure(self.id + ".TCheckbutton", background=self.color) self.style.map(self.id + ".TCheckbutton", background=[("active", self.color), ("disabled", self.color)]) self.style.map("close" + self.id + ".TLabel", background=[("active", self.color)]) self.style.map("roll" + self.id + ".TLabel", background=[("active", self.color)]) self.configure(bg=self.color) self.txt.configure(bg=self.color) def paste(self, event): """ delete selected text before pasting """ if self.txt.tag_ranges("sel"): self.txt.delete("sel.first", "sel.last") def delete(self, confirmation=True): """ Delete this note """ if confirmation: rep = askokcancel(_("Confirmation"), _("Delete the note?")) else: rep = True if rep: del (self.master.note_data[self.id]) del (self.master.notes[self.id]) self.master.save() self.destroy() def lock(self): """ Put note in read-only mode to avoid unwanted text insertion """ if self.is_locked: selectbg = self.style.lookup('TEntry', 'selectbackground', ('focus', )) self.txt.configure(state="normal", selectforeground='white', selectbackground=selectbg, inactiveselectbackground=selectbg) self.style.configure("sel.TCheckbutton", background=selectbg) self.style.map("sel.TCheckbutton", background=[("active", selectbg)]) self.is_locked = False for checkbox in self.txt.window_names(): ch = self.txt.children[checkbox.split(".")[-1]] ch.configure(state="normal") self.cadenas.configure(image="") self.menu.entryconfigure(3, label=_("Lock")) self.title_label.bind("<Double-Button-1>", self.edit_title) self.txt.bind('<Button-3>', self.show_menu_txt) else: self.txt.configure(state="disabled", selectforeground='black', inactiveselectbackground='#c3c3c3', selectbackground='#c3c3c3') self.style.configure("sel.TCheckbutton", background='#c3c3c3') self.style.map("sel.TCheckbutton", background=[("active", '#c3c3c3')]) self.cadenas.configure(image=self.im_lock) for checkbox in self.txt.window_names(): ch = self.txt.children[checkbox.split(".")[-1]] ch.configure(state="disabled") self.is_locked = True self.menu.entryconfigure(3, label=_("Unlock")) self.title_label.unbind("<Double-Button-1>") self.txt.unbind('<Button-3>') self.save_note() def save_info(self): """ Return the dictionnary containing all the note data """ data = {} data["txt"] = self.txt.get("1.0", "end")[:-1] data["tags"] = {} for tag in self.txt.tag_names(): if tag not in ["sel", "todolist", "list", "enum"]: data["tags"][tag] = [ index.string for index in self.txt.tag_ranges(tag) ] data["title"] = self.title_var.get() data["geometry"] = self.save_geometry data["category"] = self.category.get() data["color"] = self.color data["locked"] = self.is_locked data["mode"] = self.mode.get() data["inserted_objects"] = {} data["rolled"] = not self.txt.winfo_ismapped() data["position"] = self.position.get() data["links"] = {} for i, link in self.links.items(): if self.txt.tag_ranges("link#%i" % i): data["links"][i] = link data["latex"] = {} for img, latex in self.latex.items(): if self.txt.tag_ranges(img): data["latex"][img] = latex for image in self.txt.image_names(): data["inserted_objects"][self.txt.index(image)] = ( "image", image.split('#')[0]) for checkbox in self.txt.window_names(): ch = self.txt.children[checkbox.split(".")[-1]] data["inserted_objects"][self.txt.index(checkbox)] = ( "checkbox", "selected" in ch.state()) return data def change_color(self, key): self.color = COLORS[key] self.save_note() def change_category(self, category=None): if category: self.category.set(category) self.color = CONFIG.get("Categories", self.category.get()) self.save_note() def set_position_above(self): e = ewmh.EWMH() for w in e.getClientList(): if w.get_wm_name() == 'mynotes%s' % self.id: e.setWmState(w, 1, '_NET_WM_STATE_ABOVE') e.setWmState(w, 0, '_NET_WM_STATE_BELOW') e.display.flush() self.save_note() def set_position_below(self): e = ewmh.EWMH() for w in e.getClientList(): if w.get_wm_name() == 'mynotes%s' % self.id: e.setWmState(w, 0, '_NET_WM_STATE_ABOVE') e.setWmState(w, 1, '_NET_WM_STATE_BELOW') e.display.flush() self.save_note() def set_position_normal(self): e = ewmh.EWMH() for w in e.getClientList(): if w.get_wm_name() == 'mynotes%s' % self.id: e.setWmState(w, 0, '_NET_WM_STATE_BELOW') e.setWmState(w, 0, '_NET_WM_STATE_ABOVE') e.display.flush() self.save_note() def set_mode_note(self): self.txt.tag_remove("list", "1.0", "end") self.txt.tag_remove("todolist", "1.0", "end") self.txt.tag_remove("enum", "1.0", "end") self.save_note() def set_mode_list(self): end = int(self.txt.index("end").split(".")[0]) lines = self.txt.get("1.0", "end").splitlines() for i, l in zip(range(1, end), lines): # remove checkboxes try: ch = self.txt.window_cget("%i.0" % i, "window") self.txt.children[ch.split('.')[-1]].destroy() self.txt.delete("%i.0" % i) except TclError: # there is no checkbox # remove enumeration res = re.match('^\t[0-9]+\.\t', l) if res: self.txt.delete("%i.0" % i, "%i.%i" % (i, res.end())) if self.txt.get("%i.0" % i, "%i.3" % i) != "\t•\t": self.txt.insert("%i.0" % i, "\t•\t") self.txt.tag_add("list", "1.0", "end") self.txt.tag_remove("todolist", "1.0", "end") self.txt.tag_remove("enum", "1.0", "end") self.save_note() def set_mode_enum(self): self.txt.configure(autoseparators=False) self.txt.edit_separator() end = int(self.txt.index("end").split(".")[0]) lines = self.txt.get("1.0", "end").splitlines() for i, l in zip(range(1, end), lines): # remove checkboxes try: ch = self.txt.window_cget("%i.0" % i, "window") self.txt.children[ch.split('.')[-1]].destroy() self.txt.delete("%i.0" % i) except TclError: # there is no checkbox # remove bullets if self.txt.get("%i.0" % i, "%i.3" % i) == "\t•\t": self.txt.delete("%i.0" % i, "%i.3" % i) if not re.match('^\t[0-9]+\.', l): self.txt.insert("%i.0" % i, "\t0.\t") self.txt.tag_add("enum", "1.0", "end") self.txt.tag_remove("todolist", "1.0", "end") self.txt.tag_remove("list", "1.0", "end") self.update_enum() self.txt.configure(autoseparators=True) self.txt.edit_separator() self.save_note() def set_mode_todolist(self): end = int(self.txt.index("end").split(".")[0]) lines = self.txt.get("1.0", "end").splitlines() for i, l in zip(range(1, end), lines): res = re.match('^\t[0-9]+\.\t', l) if res: self.txt.delete("%i.0" % i, "%i.%i" % (i, res.end())) elif self.txt.get("%i.0" % i, "%i.3" % i) == "\t•\t": self.txt.delete("%i.0" % i, "%i.3" % i) try: ch = self.txt.window_cget("%i.0" % i, "window") except TclError: ch = Checkbutton(self.txt, takefocus=False, style=self.id + ".TCheckbutton") self.txt.window_create("%i.0" % i, window=ch) self.txt.tag_remove("enum", "1.0", "end") self.txt.tag_remove("list", "1.0", "end") self.txt.tag_add("todolist", "1.0", "end") self.save_note() # --- bindings def enter_roll(self, event): """ mouse is over the roll icon """ self.roll.configure(image="img_rollactive") def leave_roll(self, event): """ mouse leaves the roll icon """ self.roll.configure(image="img_roll") def enter_close(self, event): """ mouse is over the close icon """ self.close.configure(image="img_closeactive") def leave_close(self, event): """ mouse leaves the close icon """ self.close.configure(image="img_close") def change_focus(self, event): if not self.is_locked: event.widget.focus_force() def show_menu(self, event): self.menu.tk_popup(event.x_root, event.y_root) def show_menu_txt(self, event): self.menu_txt.tk_popup(event.x_root, event.y_root) def resize(self, event): self.save_geometry = self.geometry() def bouge(self, event): geo = self.geometry().split("+")[1:] self.save_geometry = self.save_geometry.split("+")[0] \ + "+%s+%s" % tuple(geo) def edit_title(self, event): self.title_entry.place(x=self.title_label.winfo_x() + 5, y=self.title_label.winfo_y(), anchor="nw", width=self.title_label.winfo_width() - 10) def start_move(self, event): self.x = event.x self.y = event.y self.configure(cursor='fleur') def stop_move(self, event): self.x = None self.y = None self.configure(cursor='') def move(self, event): if self.x is not None and self.y is not None: deltax = event.x - self.x deltay = event.y - self.y x = self.winfo_x() + deltax y = self.winfo_y() + deltay self.geometry("+%s+%s" % (x, y)) def save_note(self, event=None): data = self.save_info() data["visible"] = True self.master.note_data[self.id] = data self.master.save() def rollnote(self, event=None): if self.txt.winfo_ismapped(): self.txt.grid_forget() self.corner.place_forget() self.geometry("%sx22" % self.winfo_width()) else: self.txt.grid(row=1, columnspan=4, column=0, sticky="ewsn", pady=(1, 4), padx=4) self.corner.place(relx=1.0, rely=1.0, anchor="se") self.geometry(self.save_geometry) self.save_note() def hide(self, event=None): """ Hide note (can be displayed again via app menu) """ cat = self.category.get() self.master.add_note_to_menu(self.id, self.title_var.get().strip(), cat) data = self.save_info() data["visible"] = False self.master.note_data[self.id] = data del (self.master.notes[self.id]) self.master.save() self.destroy() # --- Settings update def update_title_font(self): font = "%s %s" % (CONFIG.get("Font", "title_family").replace( " ", "\ "), CONFIG.get("Font", "title_size")) style = CONFIG.get("Font", "title_style").split(",") if style: font += " " font += " ".join(style) self.title_label.configure(font=font) def update_text_font(self): font = "%s %s" % (CONFIG.get("Font", "text_family").replace( " ", "\ "), CONFIG.get("Font", "text_size")) self.txt.configure(font=font) self.txt.tag_configure("bold", font="%s bold" % font) self.txt.tag_configure("italic", font="%s italic" % font) self.txt.tag_configure("bold-italic", font="%s bold italic" % font) margin = 2 * Font(self, font=font).measure("m") self.txt.tag_configure("enum", lmargin1=0, lmargin2=margin + 5, tabs=(margin, 'right', margin + 5, 'left')) def update_menu_cat(self, categories): """ Update the category submenu """ self.menu_categories.delete(0, "end") for cat in categories: self.menu_categories.add_radiobutton(label=cat.capitalize(), value=cat, variable=self.category, command=self.change_category) def update_titlebar(self): if CONFIG.get("General", "buttons_position") == "right": # right = lock icon - title - roll - close self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=0) self.roll.grid_configure(row=0, column=2, sticky="e") self.close.grid_configure(row=0, column=3, sticky="e", padx=(0, 2)) self.cadenas.grid_configure(row=0, column=0, sticky="w") self.title_label.grid_configure(row=0, column=1, sticky="ew", pady=(1, 0)) else: # left = close - roll - title - lock icon self.columnconfigure(2, weight=1) self.columnconfigure(1, weight=0) self.roll.grid_configure(row=0, column=1, sticky="w") self.close.grid_configure(row=0, column=0, sticky="w", padx=(2, 0)) self.cadenas.grid_configure(row=0, column=3, sticky="e") self.title_label.grid_configure(row=0, column=2, sticky="ew", pady=(1, 0)) # --- Text edition def add_link(self): def ok(eveny=None): lien = link.get() txt = text.get() if lien: if not txt: txt = lien self.nb_links += 1 if self.txt.tag_ranges("sel"): index = self.txt.index("sel.first") self.txt.delete('sel.first', 'sel.last') else: index = "current" tags = self.txt.tag_names(index) + ("link", "link#%i" % self.nb_links) self.txt.insert("current", txt, tags) if not lien[:4] == "http": lien = "http://" + lien self.links[self.nb_links] = lien self.txt.tag_bind("link#%i" % self.nb_links, "<Button-1>", lambda e: open_url(lien)) top.destroy() top = Toplevel(self) top.transient(self) top.update_idletasks() top.geometry("+%i+%i" % top.winfo_pointerxy()) top.grab_set() top.resizable(True, False) top.title(_("Link")) top.columnconfigure(1, weight=1) text = Entry(top) link = Entry(top) if self.txt.tag_ranges('sel'): txt = self.txt.get('sel.first', 'sel.last') else: txt = '' text.insert(0, txt) text.icursor("end") Label(top, text=_("Text")).grid(row=0, column=0, sticky="e", padx=4, pady=4) Label(top, text=_("Link")).grid(row=1, column=0, sticky="e", padx=4, pady=4) text.grid(row=0, column=1, sticky="ew", padx=4, pady=4) link.grid(row=1, column=1, sticky="ew", padx=4, pady=4) Button(top, text="Ok", command=ok).grid(row=2, columnspan=2, padx=4, pady=4) text.focus_set() text.bind("<Return>", ok) link.bind("<Return>", ok) def add_checkbox(self): ch = Checkbutton(self.txt, takefocus=False, style=self.id + ".TCheckbutton") self.txt.window_create("current", window=ch) def add_date(self): self.txt.insert("current", strftime("%x")) def add_latex(self, img_name=None): def ok(event): latex = r'%s' % text.get() if latex: if img_name is None: l = [ int(os.path.splitext(f)[0]) for f in os.listdir(PATH_LATEX) ] l.sort() if l: i = l[-1] + 1 else: i = 0 img = "%i.png" % i self.txt.tag_bind(img, '<Double-Button-1>', lambda e: self.add_latex(img)) self.latex[img] = latex else: img = img_name im = os.path.join(PATH_LATEX, img) try: math_to_image(latex, im, fontsize=CONFIG.getint("Font", "text_size") - 2) self.images.append(PhotoImage(file=im, master=self)) if self.txt.tag_ranges("sel"): index = self.txt.index("sel.first") self.txt.delete('sel.first', 'sel.last') else: index = self.txt.index("current") self.txt.image_create(index, image=self.images[-1], name=im) self.txt.tag_add(img, index) top.destroy() except Exception as e: showerror(_("Error"), str(e)) top = Toplevel(self) top.transient(self) top.update_idletasks() top.geometry("+%i+%i" % top.winfo_pointerxy()) top.grab_set() top.resizable(True, False) top.title("LaTex") text = Entry(top, justify='center') if img_name is not None: text.insert(0, self.latex[img_name]) else: if self.txt.tag_ranges('sel'): text.insert(0, self.txt.get('sel.first', 'sel.last')) else: text.insert(0, '$$') text.icursor(1) text.pack(fill='x', expand=True) text.bind('<Return>', ok) text.focus_set() def add_image(self): fichier = askopenfilename(defaultextension=".png", filetypes=[("PNG", "*.png")], initialdir="", initialfile="", title=_('Select PNG image')) if os.path.exists(fichier): self.images.append(PhotoImage(master=self.txt, file=fichier)) self.txt.image_create("current", image=self.images[-1], name=fichier) elif fichier: showerror("Erreur", "L'image %s n'existe pas" % fichier) def add_symbols(self): symbols = pick_symbol( self, CONFIG.get("Font", "text_family").replace(" ", "\ "), CONFIG.get("General", "symbols")) self.txt.insert("current", symbols) def toggle_text_style(self, style): '''Toggle the style of the selected text''' if self.txt.tag_ranges("sel"): current_tags = self.txt.tag_names("sel.first") if style in current_tags: # first char is in style so 'unstyle' the range self.txt.tag_remove(style, "sel.first", "sel.last") elif style == "bold" and "bold-italic" in current_tags: self.txt.tag_remove("bold-italic", "sel.first", "sel.last") self.txt.tag_add("italic", "sel.first", "sel.last") elif style == "italic" and "bold-italic" in current_tags: self.txt.tag_remove("bold-italic", "sel.first", "sel.last") self.txt.tag_add("bold", "sel.first", "sel.last") elif style == "bold" and "italic" in current_tags: self.txt.tag_remove("italic", "sel.first", "sel.last") self.txt.tag_add("bold-italic", "sel.first", "sel.last") elif style == "italic" and "bold" in current_tags: self.txt.tag_remove("bold", "sel.first", "sel.last") self.txt.tag_add("bold-italic", "sel.first", "sel.last") else: # first char is normal, so apply style to the whole selection self.txt.tag_add(style, "sel.first", "sel.last") def toggle_underline(self): if self.txt.tag_ranges("sel"): current_tags = self.txt.tag_names("sel.first") if "underline" in current_tags: # first char is in style so 'unstyle' the range self.txt.tag_remove("underline", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): self.txt.tag_remove(coul + "-underline", "sel.first", "sel.last") else: self.txt.tag_add("underline", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): r = text_ranges(self.txt, coul, "sel.first", "sel.last") if r: for deb, fin in zip(r[::2], r[1::2]): self.txt.tag_add(coul + "-underline", "sel.first", "sel.last") def toggle_overstrike(self): if self.txt.tag_ranges("sel"): current_tags = self.txt.tag_names("sel.first") if "overstrike" in current_tags: # first char is in style so 'unstyle' the range self.txt.tag_remove("overstrike", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): self.txt.tag_remove(coul + "-overstrike", "sel.first", "sel.last") else: self.txt.tag_add("overstrike", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): r = text_ranges(self.txt, coul, "sel.first", "sel.last") if r: for deb, fin in zip(r[::2], r[1::2]): self.txt.tag_add(coul + "-overstrike", "sel.first", "sel.last") def change_sel_color(self, color): """ change the color of the selection """ if self.txt.tag_ranges("sel"): for coul in TEXT_COLORS.values(): self.txt.tag_remove(coul, "sel.first", "sel.last") self.txt.tag_remove(coul + "-overstrike", "sel.first", "sel.last") self.txt.tag_remove(coul + "-underline", "sel.first", "sel.last") if not color == "black": self.txt.tag_add(color, "sel.first", "sel.last") underline = text_ranges(self.txt, "underline", "sel.first", "sel.last") overstrike = text_ranges(self.txt, "overstrike", "sel.first", "sel.last") for deb, fin in zip(underline[::2], underline[1::2]): self.txt.tag_add(color + "-underline", deb, fin) for deb, fin in zip(overstrike[::2], overstrike[1::2]): self.txt.tag_add(color + "-overstrike", deb, fin) def set_align(self, alignment): """ Align the text according to alignment (left, right, center) """ if self.txt.tag_ranges("sel"): line = self.txt.index("sel.first").split(".")[0] line2 = self.txt.index("sel.last").split(".")[0] deb, fin = line + ".0", line2 + ".end" if not "\t" in self.txt.get(deb, fin): # tabulations don't support right/center alignment # remove old alignment tag self.txt.tag_remove("left", deb, fin) self.txt.tag_remove("right", deb, fin) self.txt.tag_remove("center", deb, fin) # set new alignment tag self.txt.tag_add(alignment, deb, fin) def update_enum(self): """ update enumeration numbers """ lines = self.txt.get("1.0", "end").splitlines() indexes = [] for i, l in enumerate(lines): res = re.match('^\t[0-9]+\.\t', l) res2 = re.match('^\t[0-9]+\.', l) if res: indexes.append((i, res.end())) elif res2: indexes.append((i, res2.end())) for j, (i, end) in enumerate(indexes): self.txt.delete("%i.0" % (i + 1), "%i.%i" % (i + 1, end)) self.txt.insert("%i.0" % (i + 1), "\t%i.\t" % (j + 1)) self.txt.tag_add("enum", "1.0", "end")
class LoginFrame: def __init__(self, url): self.url = url self.root = Tk() self.root.title("验证码") while True: try: image_bytes = urlopen(self.url).read() break except socket.timeout: print('获取验证码超时:%s\r\n重新获取.' % (self.url)) continue except urllib.error.URLError as e: if isinstance(e.reason, socket.timeout): print('获取验证码超时:%s\r\n重新获取.' % (self.url)) continue # internal data file data_stream = io.BytesIO(image_bytes) # open as a PIL image object self.pil_image = Image.open(data_stream) # convert PIL image object to Tkinter PhotoImage object self.tk_image = ImageTk.PhotoImage(self.pil_image) self.label = Label(self.root, image=self.tk_image, background='brown') self.label.pack(padx=5, pady=5) self.button = Button(self.root, text="刷新验证码", command=self.refreshImg) self.button.pack(padx=5, pady=5) randCodeLable = Label(self.root, text="验证码:") randCodeLable.pack(padx=5, pady=5) self.randCode = Entry(self.root) self.randCode.pack(padx=5, pady=5) self.loginButton = Button(self.root, text="登录", default=tkinter.ACTIVE) self.loginButton.pack(padx=5, pady=5) def refreshImg(self): url = self.url while True: try: image_bytes = urlopen(url).read() data_stream = io.BytesIO(image_bytes) self.pil_image = Image.open(data_stream) self.tk_image = ImageTk.PhotoImage(self.pil_image) self.label.configure(image=self.tk_image) break except socket.timeout: print('获取验证码超时:%s\r\n重新获取.' % (self.url)) continue except urllib.error.URLError as e: if isinstance(e.reason, socket.timeout): print('获取验证码超时:%s\r\n重新获取.' % (self.url)) continue # 显示URL地址指定图片 def show(self): w, h = self.pil_image.size # 窗体居中 width = w + 100 height = h + 160 ws = self.root.winfo_screenwidth() hs = self.root.winfo_screenheight() x = int((ws / 2) - (width / 2)) y = int((hs / 2) - (height / 2)) self.root.geometry('{}x{}+{}+{}'.format(width, height, x, y)) # 禁止窗体改变大小 self.root.resizable(False, False) self.root.mainloop() def quit(self): self.root.destroy()
class ErrorSurfaceFrame(LabelFrame): def __init__(self,parent): LabelFrame.__init__(self, parent, borderwidth=0) entryWidth = 7 xPad1 = 30 xPad2 = 5 self.errorXLowerLimitL = Label(self) self.errorXLowerLimitE = CustomEntry(self,width=entryWidth,justify="right") self.errorXLowerLimitL.grid(row=0,column=0,padx=(10,xPad2),pady=5,sticky="W") self.errorXLowerLimitE.grid(row=0,column=1,padx=(xPad2,xPad1),pady=5) self.errorXUpperLimitL = Label(self) self.errorXUpperLimitE = CustomEntry(self,width=entryWidth,justify="right") self.errorXUpperLimitL.grid(row=1,column=0,padx=(10,xPad2),pady=5,sticky="W") self.errorXUpperLimitE.grid(row=1,column=1,padx=(xPad2,xPad1),pady=5) self.errorYLowerLimitL = Label(self) self.errorYLowerLimitE = CustomEntry(self,width=entryWidth,justify="right") self.errorYLowerLimitL.grid(row=0,column=2,padx=(xPad1,xPad2),pady=5,sticky="W") self.errorYLowerLimitE.grid(row=0,column=3,padx=(xPad2,xPad1),pady=5) self.errorYUpperLimitL = Label(self) self.errorYUpperLimitE = CustomEntry(self,width=entryWidth,justify="right") self.errorYUpperLimitL.grid(row=1,column=2,padx=(xPad1,xPad2),pady=5,sticky="W") self.errorYUpperLimitE.grid(row=1,column=3,padx=(xPad2,xPad1),pady=5) self.errorResolutionL = Label(self,text="Resolution: ") self.errorResolutionE = CustomEntry(self,width=entryWidth,justify="right") self.errorResolutionE.insert(0,ERROR_SURFACE_DEFAULT_RESOLUTION) self.errorResolutionL.grid(row=0,column=4,padx=(xPad1,xPad2),pady=5,sticky="W") self.errorResolutionE.grid(row=0,column=5,padx=(xPad2,xPad1),pady=5,sticky="E") self.errorSurfaceB = Button(self,text=" Calculate error surface ") self.errorSurfaceB.grid(row=1,column=4,columnspan=2,padx=(xPad1,xPad1),sticky="EW") self.errorSurfaceB.configure(state=tkinter.ACTIVE) def update(self,xSymbol,ySymbol,xLL,xUL,yLL,yUL): self.xSymbol = xSymbol self.ySymbol = ySymbol self.errorXLowerLimitL.configure(text="Lower limit ("+self.xSymbol+"): ") self.errorXLowerLimitE.insertNew(xLL) self.errorXUpperLimitL.configure(text="Upper limit ("+self.xSymbol+"): ") self.errorXUpperLimitE.insertNew(xUL) self.errorYLowerLimitL.configure(text="Lower limit ("+self.ySymbol+"): ") self.errorYLowerLimitE.insertNew(yLL) self.errorYUpperLimitL.configure(text="Upper limit ("+self.ySymbol+"): ") self.errorYUpperLimitE.insertNew(yUL) def getSurfaceParameters(self): xLowerLimit = helper_functions.validateValue(self.errorXLowerLimitE.get(), self.xSymbol + " lower limit must be a positive number", "float", lowerBound=0) xUpperLimit = helper_functions.validateValue(self.errorXUpperLimitE.get(), self.xSymbol + " upper limit must be greater than the lower limit", "float", strictLowerBound=xLowerLimit) yLowerLimit = helper_functions.validateValue(self.errorYLowerLimitE.get(), self.ySymbol + " lower limit must be a positive number", "float", lowerBound=0) yUpperLimit = helper_functions.validateValue(self.errorYUpperLimitE.get(), self.ySymbol + " upper limit must be greater than the lower limit", "float", strictLowerBound=yLowerLimit) resolution = helper_functions.validateValue(self.errorResolutionE.get(), "Resolution must be " + str(ERROR_SURFACE_MIN_RESOLUTION) + " \u2264 x \u2264 " + str(ERROR_SURFACE_MAX_RESOLUTION), "int", lowerBound=ERROR_SURFACE_MIN_RESOLUTION, upperBound=ERROR_SURFACE_MAX_RESOLUTION) return [xLowerLimit,xUpperLimit,yLowerLimit,yUpperLimit,resolution] def clear(self): self.errorXLowerLimitE.insertNew("") self.errorXUpperLimitE.insertNew("") self.errorYLowerLimitE.insertNew("") self.errorYUpperLimitE.insertNew("")
class GUI(Frame): def __init__(self, jointNumber): super().__init__() self.jointNumber = jointNumber self.initGUI() def quit(self): self.master.quit() self.master.destroy() def initGUI(self): self.master.title('VRGlove') self.master.geometry('1280x720') self.pack(fill=BOTH, expand=True) # Color list: https://xkcd.com/color/rgb/ self.colorList = ['xkcd:purple', 'xkcd:green', \ 'xkcd:blue', 'xkcd:pink', 'xkcd:brown', 'xkcd:red', \ 'xkcd:light blue', 'xkcd:teal', 'xkcd:orange', 'xkcd:light green', \ 'xkcd:magenta', 'xkcd:yellow', 'xkcd:cyan', 'xkcd:grey', \ 'xkcd:lime green', 'xkcd:light purple', 'xkcd:violet', 'xkcd:dark green', \ 'xkcd:turquoise', 'xkcd:lavender', 'xkcd:dark blue', 'xkcd:tan'] ################################################## # frameCalibrate = Frame(self) # frameCalibrate.pack(side=RIGHT, fill=Y) # labelPredict = Label(frameCalibrate, text='CALIBRATE', width=32) # labelPredict.pack(side=TOP, padx=5, pady=5) s = Style() s.configure('My.TFrame', background='green') ################################################## framePredict = Frame(self,style='My.TFrame') framePredict.pack(side=RIGHT, fill=Y) labelPredict = Label(framePredict, text='SETTING') labelPredict.pack(side=TOP, padx=5, pady=5) # self.textPredictResult = Label(framePredict, text='N/A', font=("Arial", 50), foreground='red') # self.textPredictResult.pack(side=TOP, padx=5, pady=50) labelTrainer = Label(framePredict, text='TRAINER',style='My.TFrame') labelTrainer.pack(side=TOP, padx=5, pady=100) labelTrainingCharacter = Label(framePredict, text='Training character', ) labelTrainingCharacter.pack(side=TOP, padx=5, pady=5) entryTrainingCharacter = Entry(framePredict, width=5, justify=CENTER) entryTrainingCharacter.pack(side=TOP, padx=5, pady=5) entryTrainingCharacter.insert(END, '2') labelSampleCount = Label(framePredict, text='Sample count') labelSampleCount.pack(side=TOP, padx=5, pady=5) self.textSampleCount = Label(framePredict, text=0) self.textSampleCount.pack(side=TOP, padx=5, pady=5) def sample(): global threadCollectData global threadPredict if not threadCollectData.collectSampleEnable: threadPredict.predictEnable=False threadCollectData.sampleCount = 0 threadCollectData.collectSampleEnable = True threadCollectData.trainingCharacter = entryTrainingCharacter.get() print('\nStarted sampling!') print('Sampling character: ' + threadCollectData.trainingCharacter + '\n') buttonSample.configure(text='Stop sampling') else: threadPredict.predictEnable=True threadCollectData.collectSampleEnable = False print('\nStopped sampling!\n') buttonSample.configure(text='Start sampling') buttonSample = Button(framePredict, text='Start sampling', command=sample, width=15) buttonSample.pack(side=TOP, padx=5, pady=5) def trainModel(): global threadPredict threadPredict.predictEnable = False global threadCollectData if threadQuatProcess.collectSampleEnable: sample() global threadTrainingModel threadTrainingModel.train() statusText = 'Training done!\nTime elapsed: ' + str(threadTrainingModel.timeElapsed) + ' ms\n' statusText += 'Testing done!\nTraining accuracy: ' + str(threadTrainingModel.trainScore) + '%\n' statusText += 'Saving done!\nFilename: ' + threadTrainingModel.modelFile labelTrainingStatus.configure(text=statusText) threadPredict.predictEnable = True buttonTrain = Button(framePredict, text='Train model', command=trainModel, width=15) buttonTrain.pack(side=TOP, padx=5, pady=5) labelTrainingStatus = Label(framePredict, text='Ready') labelTrainingStatus.pack(side=TOP, padx=5, pady=5) def PredictCmd(): global threadPredict if threadPredict.predictEnable and not threadPredict.MultiplePredictEnable: start=timer() jointAngle=jointAngleRight+jointAngleLeft threadPredict.Count=threadPredict.Count+1 temp = np.array(jointAngle).reshape(1, -1) yPredict = threadPredict.loadedModel.predict(temp) img=mpimg.imread(ImageIndex[int(yPredict)]) imgplot=plt.imshow(img) plt.show() end=timer() predictTime=end-start predictTime=round(predictTime,3) #self.textPredictResult.configure(text=predictTime) else: messagebox.showwarning("Infor", "Another process is running") def MultiplePredictCmd(): global threadPredict if threadPredict.predictEnable: if not threadPredict.MultiplePredictEnable: threadPredict.MultiplePredictEnable = True buttonMultiplePredict.configure(text='Stop') threadPredict.start() else: threadPredict.MultiplePredictEnable = False buttonMultiplePredict.configure(text='Multiple Predict') #threadPredict = ThreadPredict('finalizedModel.sav') threadPredict = ThreadPredict('twoHandModel.h5') ################################################## frameGraph = Frame(self,style='My.TFrame') frameGraph.pack(side=RIGHT, fill=BOTH, expand=True) labelGraph = Label(frameGraph, text='JOINT ANGLES') labelGraph.pack(side=TOP, padx=5, pady=5) buttonPredict = Button(frameGraph, text='Single Predict', command=PredictCmd, width=15) buttonPredict.pack(side=BOTTOM, padx=5, pady=5) buttonMultiplePredict= Button(frameGraph, text='Multiple Predict', command=MultiplePredictCmd, width=15) buttonMultiplePredict.pack(side=BOTTOM, padx=5, pady=5) self.fig = plt.Figure(dpi = 100) ax = self.fig.add_subplot(111) ax.set(xlim = (0, 100), ylim = (-100, 100)) canvas = FigureCanvasTkAgg(self.fig, frameGraph) canvas.get_tk_widget().pack(fill=BOTH, padx=5, expand=True) self.x = np.arange(0, 101, 1) self.y = [] self.line = [] for i in range(jointNumber): self.y.append([]) for j in range(101): self.y[i].append(0) self.line.append(ax.plot(self.x, self.y[i], color=self.colorList[i], lw=1)[0]) ######################################################### frameMultiplePredict = Frame(self,style='My.TFrame') frameMultiplePredict.pack(side=RIGHT, fill=BOTH) LabelMultiplePredict = Label(frameMultiplePredict, text='MULTIPLE PREDICT') LabelMultiplePredict.pack(side=TOP, padx=5, pady=5) self.predictResult = Text(frameMultiplePredict, width=50, font=("Arial",15), foreground='black') self.predictResult.pack(fill=BOTH, padx=5, expand=True) TimeLabel= Label(frameMultiplePredict, text='Time Respone', font=("Arial", 15), foreground='red') TimeLabel.pack(side=TOP, padx=5, pady=5) def UpCmd(): global threadPredict global timeConstant if timeConstant<10: timeConstant=timeConstant+0.5 threadPredict.timeConstant=timeConstant self.Time.configure(text=timeConstant) buttonUp=Button(frameMultiplePredict, command=UpCmd, text ='+', width=2) buttonUp.pack(side=TOP, padx=5, pady=5) self.Time= Label(frameMultiplePredict, text='0.5') self.Time.pack(side=TOP, padx=5, pady=5) def DownCmd(): global threadPredict global timeConstant if timeConstant>0.5: timeConstant=timeConstant-0.5 threadPredict.timeConstant=timeConstant self.Time.configure(text=timeConstant) buttonDown=Button(frameMultiplePredict, command=DownCmd, text ='-', width=2) buttonDown.pack(side=TOP, padx=5, pady=5) # buttonPredict = Button(frameGraph, Text='Predict') # buttonPredict.pack(side=TOP ,padx=5, pady=5) # serialPort = StringVar(frameGraph) # serialPort.set('/dev/rfcomm0') # serialPortList = ['/dev/rfcomm0', '/dev/ttyACM0', '/dev/ttyACM1'] # serialPortOption = OptionMenu(frameGraph, serialPort, serialPortList[0], *serialPortList) # serialPortOption.pack(side=LEFT, padx=10, pady=10) # def connect(): # global threadQuatProcess # threadQuatProcess.receiveQuatEnable = False # threadQuatProcess.changeSerialPort(serialPort.get()) # threadQuatProcess.receiveQuatEnable = True # print('\nConnected to ' + threadQuatProcess.serialPort + '!\n') # buttonConnect = Button(frameGraph, text='Connect', command=connect) # buttonConnect.pack(side=TOP, padx=5, pady=5) def updateGraph(self, i): for i in range(jointNumber): global jointAngleRight self.y[i].pop(0) self.y[i].append(jointAngleRight[i]*180.0/3.1416) # self.y[i].append(randint(-90, 90)) self.line[i].set_ydata(self.y[i]) return self.line[i], def updateParameters(self): global threadPredict global threadCollectData #self.textPredictResult.configure(text=threadPredict.predictResult) self.textSampleCount.configure(text=threadCollectData.sampleCount) self.master.after(100, self.updateParameters) def run(self): self.ani = animation.FuncAnimation(self.fig, self.updateGraph, interval=100) self.master.after(100, self.updateParameters) self.master.mainloop()
class Progression(Frame): """Class to display the progress in filling the puzzle.""" def __init__(self, master, number, **kwargs): kwargs.setdefault('width', 34) kwargs.setdefault('height', 34) kwargs.setdefault('style', 'case.TFrame') Frame.__init__(self, master, **kwargs) self.grid_propagate(False) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.number = number self._nb = 0 self.label_number = Label(self, style='case.TLabel', text=str(number), font='Arial 16') self.label_nb = Label(self, style='case.TLabel', text='0', font='Arial 9') self.label_number.grid(row=0, column=0, sticky='e', padx=0) self.label_nb.grid(row=0, column=1, sticky='n') @property def nb(self): return self._nb @nb.setter def nb(self, value): self._nb = value self.label_nb.configure(text=str(self._nb)) if self._nb < 9: self.configure(style='case.TFrame') self.label_number.configure(style='case.TLabel') self.label_nb.configure(style='case.TLabel') elif self._nb == 9: self.configure(style='case_init.TFrame') self.label_number.configure(style='case_init.TLabel') self.label_nb.configure(style='case_init.TLabel') else: self.configure(style='erreur.TFrame') self.label_number.configure(style='erreur.TLabel') self.label_nb.configure(style='erreur.TLabel')
class Search(Module): def __init__(self, app): self.app = app self.window = None self.context_size = 3 self.results = [] self.regex = StringVar(self.app) # if anything ever changes the contents of any intervals # it should call SearchModule.loadIntervals() self.intervals = [] self.loadIntervals() def handleClose(self, event=None): self.window.destroy() self.window = None def createWindow(self): self.window = Toplevel(self.app) self.window.title('Search') self.window.protocol("WM_DELETE_WINDOW", self.handleClose) self.input = Entry(self.window, textvariable=self.regex) self.input.grid(row=0, column=0) self.input.bind('<Return>', self.search) self.input.bind('<Escape>', lambda ev: self.window.focus()) self.searchButton = Button(self.window, text='Search', command=self.search, takefocus=0) self.searchButton.grid(row=0, column=1) self.resultCount = Label(self.window, text='0 results') self.resultCount.grid(row=0, column=2) cols = ('File', 'Tier', 'Time', 'Text') self.scroll = Scrollbar(self.window, orient='vertical') self.resultList = Treeview(self.window, columns=cols, show="headings", yscrollcommand=self.scroll.set, selectmode='browse') self.scroll.config(command=self.resultList.yview) for col in cols: self.resultList.heading(col, text=col) self.resultList.grid(row=2, column=0, columnspan=3, sticky='news') self.resultList.bind('<Double-1>', self.onClick) Grid.rowconfigure(self.window, 2, weight=1) Grid.columnconfigure(self.window, 0, weight=1) self.scroll.grid(row=2, column=3, sticky='ns') def openSearch(self): if self.window == None: self.createWindow() self.window.lift() self.input.focus() def loadIntervals(self): filecount = len(self.app.Data.getTopLevel('files')) self.intervals = [] for f in range(filecount): filename = self.app.Data.getFileLevel('name', f) tg = self.app.Data.checkFileLevel('.TextGrid', f, shoulderror=False) if tg: grid = self.app.TextGrid.fromFile(tg) for tier in grid: if TextGrid.isIntervalTier(tier): for el in tier: if el.mark: self.intervals.append( (el, tier.name, filename)) def search(self, event=None): if self.regex.get() == '': self.results = [] else: pat = re.compile(self.regex.get(), re.IGNORECASE | re.MULTILINE | re.DOTALL) self.results = [] for i in self.intervals: s = pat.search(i[0].mark) if s: disp = i[0].mark a = max(0, s.start() - self.context_size) b = min(s.end() + self.context_size, len(disp)) self.results.append(i + (('...' if a > 0 else '') + disp[a:b] + ('...' if b < len(disp) else ''), )) self.resultCount.configure(text='%s results' % len(self.results)) for kid in self.resultList.get_children(): self.resultList.delete(kid) for row, res in enumerate(self.results): ls = (res[2], res[1], '%s-%s' % (res[0].minTime, res[0].maxTime), res[3]) self.resultList.insert('', 'end', iid=str(row), values=ls) def onClick(self, event=None): self.jumpTo(int(self.resultList.selection()[0])) def jumpTo(self, index): self.app.filesJumpTo(self.results[index][2]) self.app.TextGrid.selectedTier.set(self.results[index][1]) self.app.TextGrid.start = self.results[index][0].minTime self.app.TextGrid.end = self.results[index][0].maxTime for i, f in enumerate(self.app.TextGrid.frameTier): if f.time >= self.results[index][0].minTime: self.app.frameSV.set(str(i)) self.app.framesJumpTo() break self.app.TextGrid.fillCanvases() def reset(self, *args, **kwargs): raise NotImplementedError('cannot call SearchModule::reset') def update(self, *args, **kwargs): raise NotImplementedError('cannot call SearchModule::update') def grid(self, *args, **kwargs): raise NotImplementedError('cannot call SearchModule::grid') def grid_remove(self, *args, **kwargs): raise NotImplementedError('cannot call SearchModule::grid_remove')
class fiveOhOne: def __init__(self, master): self.master = master self.frame = Frame(self.master) self.configure_gui1() def configure_gui1(self): self.master.title("501") self.master.geometry("800x600") # function binding return key to entry box self.master.bind('<Return>', lambda e: self.score_Entered()) #create menu def callback(): print("called the callback!") # create a menu menu = Menu(root) root.config(menu=menu) filemenu = Menu(menu) menu.add_cascade(label="File", menu=filemenu) filemenu.add_command(label="New", command=callback) filemenu.add_command(label="Open...", command=callback) filemenu.add_separator() filemenu.add_command(label="Exit", command=callback) helpmenu = Menu(menu) menu.add_cascade(label="Help", menu=helpmenu) helpmenu.add_command(label="About...", command=callback) #create frames labFrame1 = LabelFrame(self.master, text="Player1 Stats") labFrame2 = LabelFrame(self.master, text="Player2 Stats") labFrame3 = LabelFrame(self.master, text="Player1 Scores") labFrame4 = LabelFrame(self.master, text="Player2 Scores") labFrame5 = LabelFrame(self.master, text="Enter Scores") """ #make frames visible using grid labFrame1.grid(row=0, column=0, rowspan=2, sticky='ew') labFrame3.grid(row=0, column=1, sticky='ew') labFrame4.grid(row=0, column=2, sticky='ew') labFrame2.grid(row=0, column=3, rowspan=2, sticky='ew') labFrame5.grid(row=1, column=1, columnspan=2, sticky='ew') """ #make frames visible using pack labFrame1.pack(side="left", fill="both", expand=True) labFrame2.pack(side="right", fill="both", expand=True) labFrame5.pack(side="bottom", fill="x", expand=True) labFrame3.pack(side="left", fill="both", expand=True) labFrame4.pack(side="right", fill="both", expand=True) #stringvars self.pl1name = StringVar() self.pl2name = StringVar() self.pl1sets = StringVar() self.pl1legs = StringVar() self.pl160 = StringVar() self.pl180 = StringVar() self.pl1100 = StringVar() self.pl1140 = StringVar() self.pl1180 = StringVar() self.pl1avg = StringVar() self.pl1chtpc = StringVar() self.pl1chtnumbs = StringVar() #player to go boolean self.player1_togo = True #frame 1 widgets Label(labFrame1, text="Totals").grid(row=0, column=0, sticky='w') Label(labFrame1, text="Sets:").grid(row=1, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1sets).grid(row=1, column=1) Label(labFrame1, text="Legs:").grid(row=2, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1legs).grid(row=2, column=1) Label(labFrame1, text="60+:").grid(row=3, column=0, sticky='w') Label(labFrame1, textvariable=self.pl160).grid(row=3, column=1) Label(labFrame1, text="80+:").grid(row=4, column=0, sticky='w') Label(labFrame1, textvariable=self.pl180).grid(row=4, column=1) Label(labFrame1, text="100+:").grid(row=5, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1100).grid(row=5, column=1) Label(labFrame1, text="140+:").grid(row=6, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1140).grid(row=6, column=1) Label(labFrame1, text="180:").grid(row=7, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1180).grid(row=7, column=1) Label(labFrame1, text="Averages").grid(row=8, column=0, sticky='w') Label(labFrame1, text="Score:").grid(row=9, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1avg).grid(row=9, column=1) Label(labFrame1, text="Checkout %:").grid(row=10, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1chtpc).grid(row=10, column=1) Label(labFrame1, text="Checkout Hit/Thrown:").grid(row=11, column=0, sticky='w') Label(labFrame1, textvariable=self.pl1chtnumbs).grid(row=11, column=1) #stringvars self.pl2sets = StringVar() self.pl2legs = StringVar() self.pl260 = StringVar() self.pl280 = StringVar() self.pl2100 = StringVar() self.pl2140 = StringVar() self.pl2180 = StringVar() self.pl2avg = StringVar() self.pl2chtpc = StringVar() self.pl2chtnumbs = StringVar() #frame 2 widgets Label(labFrame2, text="Totals").grid(row=0, column=0, sticky='w') Label(labFrame2, text="Sets:").grid(row=1, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2sets).grid(row=1, column=1) Label(labFrame2, text="Legs:").grid(row=2, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2legs).grid(row=2, column=1) Label(labFrame2, text="60+:").grid(row=3, column=0, sticky='w') Label(labFrame2, textvariable=self.pl260).grid(row=3, column=1) Label(labFrame2, text="80+:").grid(row=4, column=0, sticky='w') Label(labFrame2, textvariable=self.pl280).grid(row=4, column=1) Label(labFrame2, text="100+:").grid(row=5, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2100).grid(row=5, column=1) Label(labFrame2, text="140+:").grid(row=6, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2140).grid(row=6, column=1) Label(labFrame2, text="180:").grid(row=7, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2180).grid(row=7, column=1) Label(labFrame2, text="Averages").grid(row=8, column=0, sticky='w') Label(labFrame2, text="Score:").grid(row=9, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2avg).grid(row=9, column=1) Label(labFrame2, text="Checkout %:").grid(row=10, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2chtpc).grid(row=10, column=1) Label(labFrame2, text="Checkout Hit/Thrown:").grid(row=11, column=0, sticky='w') Label(labFrame2, textvariable=self.pl2chtnumbs).grid(row=11, column=1) #frame 3 widgets self.pl1remaining = StringVar() Label(labFrame3, text="Player:").grid(row=0, column=0) Label(labFrame3, textvariable=self.pl1name).grid(row=0, column=1) Label(labFrame3).grid(row=1) Label(labFrame3, text="Remaining").grid(row=2, column=0, columnspan=2, sticky='ew') self.remlabel1 = Label(labFrame3, textvariable=self.pl1remaining) self.remlabel1.grid(row=3, column=0, columnspan=2) self.remlabel1.configure(width=3, background='white', font=(None, 35)) #self.pl1remaining.set(self.pl1dict['score']) #self.pl1name.set(game_state.player1) #frame 4 widgets self.pl2remaining = StringVar() Label(labFrame4, text="Player:").grid(row=0, column=0) Label(labFrame4, textvariable=self.pl2name).grid(row=0, column=1) Label(labFrame4).grid(row=1) Label(labFrame4, text="Remaining").grid(row=2, column=0, columnspan=2, sticky='ew') self.remlabel2 = Label(labFrame4, textvariable=self.pl2remaining) self.remlabel2.grid(row=3, column=0, columnspan=2) self.remlabel2.configure(width=3, background='white', font=(None, 35)) #self.pl2remaining.set(self.pl2dict['score']) #self.pl2name.set(game_state.player2) #frame 5 widgets self.playertogo = StringVar() self.scoreEntered = StringVar() Label(labFrame5, text=" ").grid(row=0, column=0) #Label(labFrame5).grid(row=0, column=1) #Label(labFrame5).grid(row=0, column=2) Label(labFrame5, text="To Go:").grid(row=1, column=1) playerLabel = Label(labFrame5, textvariable=self.playertogo) playerLabel.grid(row=2, column=1) playerLabel.configure(font=(None, 20)) self.number_entry = Entry(labFrame5, textvariable=self.scoreEntered, width=5) self.number_entry.grid(row=2, column=2) self.number_entry.configure(background='white', font=(None, 20)) self.number_entry.focus()
class Confirmation(Toplevel): """ Confirmation window that recapitulate the changes that will be made during the synchronisation. """ def __init__(self, master, a_copier, a_supp, a_supp_avant_cp, original, sauvegarde, show_size): Toplevel.__init__(self, master) self.geometry("%ix%i" % (self.winfo_screenwidth(), self.winfo_screenheight())) self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) self.title(_("Confirmation")) self.a_copier = a_copier self.a_supp = a_supp self.a_supp_avant_cp = a_supp_avant_cp h = max(len(a_supp), len(a_copier)) style = Style(self) style.configure("text.TFrame", background="white", relief="sunken") Label(self, text=_("Synchronization from %(original)s to %(backup)s") % { "original": original, "backup": sauvegarde }).grid(row=0, columnspan=2, padx=10, pady=10) paned = PanedWindow(self, orient='horizontal') paned.grid(row=1, columnspan=2, sticky="eswn", padx=(10, 4), pady=4) paned.columnconfigure(0, weight=1) paned.columnconfigure(1, weight=1) paned.rowconfigure(1, weight=1) # --- copy frame_copie = Frame(paned) frame_copie.columnconfigure(0, weight=1) frame_copie.rowconfigure(1, weight=1) paned.add(frame_copie, weight=1) Label(frame_copie, text=_("To copy:")).grid(row=0, columnspan=2, padx=(10, 4), pady=4) f_copie = Frame(frame_copie, style="text.TFrame", borderwidth=1) f_copie.columnconfigure(0, weight=1) f_copie.rowconfigure(0, weight=1) f_copie.grid(row=1, column=0, sticky="ewsn") txt_copie = Text(f_copie, height=h, wrap="none", highlightthickness=0, relief="flat") txt_copie.grid(row=0, column=0, sticky="eswn") scrollx_copie = Scrollbar(frame_copie, orient="horizontal", command=txt_copie.xview) scrolly_copie = Scrollbar(frame_copie, orient="vertical", command=txt_copie.yview) scrollx_copie.grid(row=2, column=0, sticky="ew") scrolly_copie.grid(row=1, column=1, sticky="ns") txt_copie.configure(yscrollcommand=scrolly_copie.set, xscrollcommand=scrollx_copie.set) txt_copie.insert("1.0", "\n".join(a_copier)) txt_copie.configure(state="disabled") self._size_copy = Label(frame_copie) self._size_copy.grid(row=3, column=0) # --- deletion frame_supp = Frame(paned) frame_supp.columnconfigure(0, weight=1) frame_supp.rowconfigure(1, weight=1) paned.add(frame_supp, weight=1) Label(frame_supp, text=_("To remove:")).grid(row=0, columnspan=2, padx=(4, 10), pady=4) f_supp = Frame(frame_supp, style="text.TFrame", borderwidth=1) f_supp.columnconfigure(0, weight=1) f_supp.rowconfigure(0, weight=1) f_supp.grid(row=1, column=0, sticky="ewsn") txt_supp = Text(f_supp, height=h, wrap="none", highlightthickness=0, relief="flat") txt_supp.grid(row=0, column=0, sticky="eswn") scrollx_supp = Scrollbar(frame_supp, orient="horizontal", command=txt_supp.xview) scrolly_supp = Scrollbar(frame_supp, orient="vertical", command=txt_supp.yview) scrollx_supp.grid(row=2, column=0, sticky="ew") scrolly_supp.grid(row=1, column=1, sticky="ns") txt_supp.configure(yscrollcommand=scrolly_supp.set, xscrollcommand=scrollx_supp.set) txt_supp.insert("1.0", "\n".join(a_supp)) txt_supp.configure(state="disabled") self._size_supp = Label(frame_supp) self._size_supp.grid(row=3, column=0) Button(self, command=self.ok, text="Ok").grid(row=3, column=0, sticky="e", padx=(10, 4), pady=(4, 10)) Button(self, text=_("Cancel"), command=self.destroy).grid(row=3, column=1, sticky="w", padx=(4, 10), pady=(4, 10)) self.wait_visibility() self.grab_set() self.transient(self.master) if show_size: self.compute_size() def compute_size(self): """Compute and display total size of files to copy/to delete.""" def size(path): s = 0 try: with scandir(path) as content: for f in content: try: if f.is_file(): s += f.stat().st_size else: s += size(f.path) except FileNotFoundError: pass except NotADirectoryError: s = getsize(path) return s size_copy = 0 size_supp = 0 for path in self.a_copier: size_copy += size(path) for path in self.a_supp: size_supp += size(path) self._size_copy.configure(text=_("Copy: %(size)s") % {'size': convert_size(size_copy)}) self._size_supp.configure(text=_("Remove: %(size)s") % {'size': convert_size(size_supp)}) def ok(self): """Close dialog and start sync.""" self.grab_release() self.master.copie_supp(self.a_copier, self.a_supp, self.a_supp_avant_cp) self.destroy()
class MemberChecker(PanedWindow): def __init__(self, parent): PanedWindow.__init__(self, parent, background="white") self.parent = parent self.init_data() self.init_log() self.init_ui() self.update_status() def init_data(self): self.data_store = api.DataStore() def init_log(self): self.entrance_log = entrance_log.EntranceLog() def init_ui(self): self.parent.title("Member Checker") self.columnconfigure(3, weight=3) self.pack(fill=BOTH, expand=True) self.input = StringVar() self.input_entry = Entry(self, textvariable=self.input) self.input_entry.bind('<Return>', self.submit) self.input_entry.grid(row=0, column=0, columnspan=3, sticky=E + W) self.result = StringVar() self.result_label = Label(self, textvariable=self.result) self.result_label.grid(row=3, column=0, columnspan=3, sticky=E + W) self.name = StringVar() name_label = Label(self, textvariable=self.name) name_label.grid(row=2, column=0, columnspan=3, sticky=E + W) self.status = StringVar() status_label = Label(self, textvariable=self.status) status_label.grid(row=4, column=0, columnspan=4, sticky=E + W) submit_button = Button(self, text="Submit", command=self.submit) submit_button.grid(row=1, column=2) enter_without_card_button = Button(self, text="Enter without card", command=self.enter_without_card) enter_without_card_button.grid(row=1, column=0) enter_member_without_card_button = Button(self, text="Enter member without card", command=self.enter_member_without_card) enter_member_without_card_button.grid(row=1, column=1) self.entrance_log_list = Listbox(self) self.entrance_log_list.grid(row=0, column=3, rowspan=4, sticky=E + W + S + N) self.input_entry.focus() def load_data(self): if messagebox.askyesno("Load new API Data", "Are you sure you want to load the new API data? All previous data will be removed. The program might be unresponsive for a few seconds, but don't kill it, please! It has feelings too."): self.data_store.load_api_data() def enter_by_identification(self, identification): member = self.data_store.find_member_by_identification(identification) if member is None: if messagebox.askyesno("Not a member", "This university identification is not registered as a member. Do you want to let them in as a non-member?"): self.enter_non_member_by_identification(identification) else: self.enter_member(member) def enter_by_barcode(self, barcode): member = self.data_store.find_member_by_barcode(barcode) if member is None: if messagebox.askyesno("Not a member", "This barcode is not registered as a member. Do you want to let them in as a non-member?"): self.enter_non_member_by_barcode(barcode) else: self.enter_member(member) def enter_non_member_by_identification(self, identification): self.entrance_log.enter_non_member_by_identification(identification) self.enter_non_member() def enter_non_member_by_barcode(self, barcode): self.entrance_log.enter_non_member_by_barcode(barcode) self.enter_non_member() def enter_without_card(self): self.clear_result() self.entrance_log.enter_without_card() self.enter_non_member() self.input_entry.focus() def enter_member(self, member): inside_result = self.entrance_log.is_member_inside(member) if inside_result[0]: if not messagebox.askyesno("Already inside", "This membership card has already been used to enter at {}. Are you sure you want to register it again? Normally you should let this person enter without card (and bill them accordingly).".format( inside_result[1])): return self.entrance_log.enter_member(member) self.result.set('Member!') self.result_label.configure(background='green') self.name.set(member['firstName'] + ' ' + member['lastName']) self.update_status() def enter_non_member(self): self.result.set('Not a member!') self.result_label.configure(background='red') self.name.set('Not in the database') self.update_status() def enter_member_without_card(self): name = self.input.get() if len(name) == 0: messagebox.showinfo('Name required', 'Please enter the name of this person!') return self.entrance_log.enter_member_without_card(name) self.result.set('Member without card!') self.result_label.configure(background="orange") self.name.set('') self.input.set('') self.update_status() def clear_result(self): self.result.set('') self.result_label.configure(background='white') self.name.set('') def submit(self, event=None): self.clear_result() entry = self.input.get() if helpers.is_valid_identification(entry): self.enter_by_identification(entry) elif helpers.is_valid_barcode(entry): self.enter_by_barcode(entry) else: messagebox.showinfo('Invalid entry', 'The data entered was not recognized as a valid bar code or a valid university identification. You should click \'enter without card\' to let this person in.') return self.input.set('') self.input_entry.focus() def clear_log(self): if messagebox.askyesno("Clear log", "Are you sure you want to clear the log of all people who entered?"): self.entrance_log.clear_log() self.update_status() def update_status(self): self.status.set("{} members inside. Total: {}".format(self.entrance_log.members_inside_count(), self.entrance_log.inside_count())) logs = self.entrance_log.get_latest_logs(15) self.entrance_log_list.delete(0, 15) for l in logs: s = l['timestamp'] + ": " data = l['data'] if 'member_id' in data: member = self.data_store.find_member(data['member_id']) s += member['firstName'] + " " + member['lastName'] elif 'barcode' in data: s += data['barcode'] elif 'identification' in data: s += data['identification'] elif 'name' in data: s += '[no card]' + data['name'] else: s += "-" self.entrance_log_list.insert(0, s)
class waitWindowProgressBar(Toplevel): def __init__(self, parent=None): """ Initialises the calculate wait window. Waits for other processes to finish, then packs everything. messages, setup_dataset and stop are the functions that change the layout of the frame. """ super().__init__(parent) self.title("Setting up.......") #self.attributes("-topmost", True) self.pb_val = IntVar(self) self.pb_val.set(0) self.pb = Progressbar(self, length=400, variable=self.pb_val) self.pb.pack(pady=20, padx=20) self.pb.configure(maximum=10) self.labeltext = StringVar() self.labeltext.set("Waiting for other process.....") self.waiting_label = Label(self, textvariable=self.labeltext) self.waiting_label.configure(anchor="center") self.waiting_label.pack(pady=20, padx=20, fill='both', expand=True) self.stopbutton = Button(self, text="Stop!", compound="bottom", command=self.stop) self.stopbutton.pack(side="left", fill="x", expand=True) self.stopflag = 0 self.update() def stop(self): """ Sets the stopflag to 1, thus stopping the calculation. """ self.stopflag = 1 def setup_dataset(self, dataset): """ Sets up the calculation wait window for the different stages of calculation. """ self.dataset = dataset self.title("Calculating Dataset %s" % os.path.basename(dataset.path)) self.waiting_label.pack(pady=20, padx=20) self.update() def errormessage(self, dataset): messagebox.showwarning( "Invalid parameters", "Dataset %s was skipped in the computation because of invalid parameters. Please configure Cut-off frequency and / or Filter type." % os.path.basename(dataset.path)) def return_function(self): """ Returns two functions for further use in the model. """ @ri.rternalize def messages(i, r, each): """ Messages function given to the R environment. Gives feedback on the state of the Monte-Carlo simulation. """ self.pb.step() count = np.asarray((i, r)) if (count[0] == -1): self.title("Computation for Dataset %s" % os.path.basename(self.dataset.path)) self.pb.pack(pady=20, padx=20) self.pb_val.set(0) self.stopbutton["state"] = "normal" if self.dataset.metadata[ "Method"] == "HILDE-Homogeneous" or self.dataset.metadata[ "Method"] == "HILDE-Heterogeneous": self.pb.configure(maximum=int( self.dataset.metadata["Repetitions_Hilde"])) else: self.pb.configure( maximum=int(self.dataset.metadata["Repetitions"])) self.labeltext.set( "Currently computing quantile for Dataset:\n%s \n Press Stop! button to stop computation for current dataset." % os.path.basename(self.dataset.path)) if (count[0] == -2): self.pb.pack_forget() self.labeltext.set( "Calculating fit for Dataset:\n%s\nThis computation cannot be interrupted and may take a few minutes." % os.path.basename(self.dataset.path)) self.stopbutton["state"] = "disabled" self.waiting_label.pack(pady=20, padx=20) self.update() return self.stopflag return messages, self.setup_dataset, self.errormessage
class retailPage(Frame): ''' the main page that actually branches into 2 seperate frames for buying and selling this frame provides the use with the ''' def __init__(self, parent, main, **kw): Frame.__init__(self, parent, **kw) self.main = main self.Head = Label(font=MED_FONT) self.retail_back_b = Button(text='BACK', command=self.back_fb) self.stock_name = StringVar() self.stock_name_ = '' self.stock_name_c = Combobox(textvariable=self.stock_name) self.stock_name_l = Label(text='Stock name: ') self.amount = Entry() self.amount_l = Label(text='Number of stocks :') self.check_avail_b = Button(text='Check') self.cost_l = Label(text='Cost: ') self.cost = Label() self.buy_stock_b = Button(text='BUY Stock') self.sellp_l = Label(text='Current Selling Price: ') self.profit_l = Label(text='PROFIT/LOSS') self.sell_stock_b = Button(text='SELL Stock') self.page = None def showItems(self, main): self.Head.grid(column=0, row=0, columnspan=2) self.Head.configure(text='logged in as %s' % main.present_user) if self.page == 'b': self.buy() elif self.page == 's': self.sell() def hideItems(self, main): self.Head.grid_forget() def buy(self): '''This function creates the buy window ''' self.retail_back_b.grid(column=1, row=5) self.retail_back_b.config(command=self.back_fb) self.stock_name_l.grid(column=0, row=1) self.stock_name_c.grid(column=1, row=1) self.stock_name_c.config(values=self.main.shares_dict.keys()) self.amount_l.grid(column=0, row=2) self.amount.grid(column=1, row=2) self.check_avail_b.config(command=self.check_avail_buy) self.check_avail_b.grid(column=0, row=3) self.cost_l.grid(column=0, row=4, columnspan=2) self.buy_stock_b.config(command=self.buy_stock, text='Buy Stock', state='disabled') self.buy_stock_b.grid(column=0, row=5) def sell(self): '''This function creats the sell window''' self.retail_back_b.grid(column=1, row=6) self.retail_back_b.config(command=self.back_fs) self.check_avail_b.config(command=self.check_avail_sell) self.stock_name_l.grid(column=0, row=1) self.stock_name_c.grid(column=1, row=1) self.stock_name_c.config(values=self.main.shares_dict.keys()) self.amount_l.grid(column=0, row=2) self.amount.grid(column=1, row=2) self.check_avail_b.grid(column=0, row=3) self.sellp_l.grid(column=0, row=4, columnspan=2) self.profit_l.grid(column=0, row=5, columnspan=2) self.sell_stock_b.config(command=self.sell_stock, state='disabled', text='Check') self.sell_stock_b.grid(column=0, row=6) def back_fb(self): '''Back from buy i.e. removes all the items needed to make buy''' self.retail_back_b.grid_forget() self.Head.grid(column=0, row=0, columnspan=2) self.stock_name_l.grid_forget() self.stock_name_c.grid_forget() self.amount_l.grid_forget() self.amount.grid_forget() self.check_avail_b.grid_forget() self.cost_l.grid_forget() self.buy_stock_b.grid_forget() self.buy_stock_b.config(state='disabled') self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.stock_name.set('') self.amount.delete(0, END) def back_fs(self): ''' Back from sell i.e. removes all the items needed to make it sell window''' self.Head.grid(column=0, row=0, columnspan=2) self.retail_back_b.grid_forget() self.check_avail_b.grid_forget() self.stock_name_l.grid_forget() self.stock_name_c.grid_forget() self.amount_l.grid_forget() self.amount.grid_forget() self.sellp_l.grid_forget() self.profit_l.grid_forget() self.sell_stock_b.grid_forget() self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.stock_name.set('') self.amount.delete(0, END) self.check_avail_b.grid_forget() def check_avail_buy(self): ''' Performs a check whether the number of shares requisted are available or not and then check whether the person has the required amounts of fund or not for the transaction to go through''' name = self.stock_name.get() l2 = self.main.accounts[self.main.present_user] if name in self.main.shares_dict.keys(): li = self.main.shares_dict[name] else: self.stock_name.delete(0, END) showinfo(meassage='Enter a Valid Stock name') available_num = int(li['tot_amount']) - int(li['tot_sold']) req = int(self.amount.get()) cost = req * int(li['cost']) if req < 0: showinfo(message='Enter a Valid amount') elif req > available_num: showinfo(message='Enter an amount less than ' + str(available_num)) elif cost > int(l2['balance']): showinfo(message='You have only %s in you account' % l2['balance']) else: self.cost_l.config(text='Cost: \t' + li['cost'] + '*' + str(req) + '=' + str(cost)) self.buy_stock_b.config(state='normal') def check_avail_sell(self): ''' Performs a check whether the user has enough stocks to sell''' name = self.stock_name.get() if name in self.main.shares_dict.keys(): li = self.main.shares_dict[name] else: self.stock_name.delete(0, END) showinfo(message='Enter a Valid Stock name') req = int(self.amount.get()) if req < 0: showinfo(message='Please Enter a Valid amount') self.amount.delete(0, END) li = self.main.p_user_dict ok = False for i in li: if name == i['name']: ok = True buff = i if req > int(buff['tot_owned']): showinfo(message='You dont have that many stocks try less than ' + buff['tot_owned']) self.amount.delete(0, END) cost = self.main.shares_dict[name]['cost'] tot_cost = req * int(cost) try: spent = req * float(buff['money_spent']) / int(buff['tot_owned']) except: spent = 0 pol = tot_cost - spent if pol >= 0: self.profit_l.config() elif pol < 0: self.profit_l.config() if req <= int(buff['tot_owned']): self.sellp_l.config(text='Current Selling Price: \t' + cost) self.profit_l.config(text="PROFIT-LOSS: \t" + str(pol)) self.sell_stock_b.config(command=self.sell_stock, text='Sell Stock') showinfo(message= 'Everthing is ok, \nClicking Sell will execute the trade') self.sell_stock_b.config(state='normal') def buy_stock(self): '''Finally Executes the transaction and asks the user for conformation one last time''' name = self.stock_name.get() li = self.main.shares_dict[name] for i in range(len(self.main.p_user_dict)): if name == self.main.p_user_dict[i]['name']: index = i req = int(self.amount.get()) tot_cost = req * int(li['cost']) self.main.shares_dict[name]['tot_sold'] = str( int(self.main.shares_dict[name]['tot_sold']) + req) self.main.p_user_dict[index]['tot_owned'] = str( int(self.main.p_user_dict[index]['tot_owned']) + req) self.main.p_user_dict[index]['money_spent'] = str( int(self.main.p_user_dict[index]['money_spent']) + tot_cost) self.main.users_dict[ self.main.present_user][index] = self.main.p_user_dict[index] balance = int(self.main.accounts[self.main.present_user]['balance']) self.main.accounts[self.main.present_user]['balance'] = str(balance - tot_cost) self.cost_l.config(text='Cost: ') showinfo( message='You have just bought %s of the stock %s at the price %s' % (str(req), name, str(tot_cost))) self.stock_name.set('') self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.back_fb() def sell_stock(self): '''Asks the user for conformation and then completes the transaction of selling, at this point the profit field is also updated''' name = self.stock_name.get() req = int(self.amount.get()) li = self.main.p_user_dict for i in range(len(li)): if name == li[i]['name']: ok = True buff = i tot_cost = req * int(self.main.shares_dict[name]['cost']) try: spent = req * float( self.main.p_user_dict[buff]['money_spent']) / int( self.main.p_user_dict[buff]['tot_owned']) except ZeroDivisionError: spent = 0 self.main.shares_dict[name]['tot_sold'] = str( int(self.main.shares_dict[name]['tot_sold']) - req) self.main.p_user_dict[buff]['tot_owned'] = str( int(self.main.p_user_dict[buff]['tot_owned']) - req) pol = tot_cost - spent diff = int(self.main.p_user_dict[buff]['money_spent']) - tot_cost self.main.p_user_dict[buff]['money_spent'] = str( diff) if diff > 0 else '0' self.main.users_dict[self.main.present_user] = self.main.p_user_dict profit = int(self.main.accounts[self.main.present_user]['profit']) self.main.accounts[self.main.present_user]['profit'] = str( int(profit + pol)) balance = int(self.main.accounts[self.main.present_user]['balance']) self.main.accounts[self.main.present_user]['balance'] = str(balance + tot_cost) self.retail_back_b.grid_forget() self.profit_l.config(text='PROFIT/LOSS: ') self.sellp_l.config(text='Current selling price: ') self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.back_fs()
class Calculator: equation_to_display = "" def __init__(self): self.root = tk.Tk() self.root.title("Calculator") self.entry_display = Label(self.root, width=50, background="white") self.entry_display.grid(row=0, columnspan=5) self.result_display = Label(self.root, width=37, background="white") self.result_display.grid(row=1, columnspan=3) button_tree = Button(self.root, text="Tree") button_tree.grid(row=0, column=5) button_one = Button(self.root, text="1", command=lambda: self.append_sign("1")) button_one.grid(row=2, column=0) button_two = Button(self.root, text="2", command=lambda: self.append_sign("2")) button_two.grid(row=2, column=1) button_three = Button(self.root, text="3", command=lambda: self.append_sign("3")) button_three.grid(row=2, column=2) button_four = Button(self.root, text="4", command=lambda: self.append_sign("4")) button_four.grid(row=3, column=0) button_five = Button(self.root, text="5", command=lambda: self.append_sign("5")) button_five.grid(row=3, column=1) button_six = Button(self.root, text="6", command=lambda: self.append_sign("6")) button_six.grid(row=3, column=2) button_seven = Button(self.root, text="7", command=lambda: self.append_sign("7")) button_seven.grid(row=4, column=0) button_eight = Button(self.root, text="8", command=lambda: self.append_sign("8")) button_eight.grid(row=4, column=1) button_nine = Button(self.root, text="9", command=lambda: self.append_sign("9")) button_nine.grid(row=4, column=2) button_plus = Button(self.root, text="+", command=lambda: self.append_sign("+")) button_plus.grid(row=5, column=0) button_minus = Button(self.root, text="-", command=lambda: self.append_sign("-")) button_minus.grid(row=5, column=1) button_zero = Button(self.root, text="0", command=lambda: self.append_sign("0")) button_zero.grid(row=5, column=2) button_mul = Button(self.root, text="*", command=lambda: self.append_sign("*")) button_mul.grid(row=6, column=0) button_div = Button(self.root, text="/", command=lambda: self.append_sign("/")) button_div.grid(row=6, column=1) button_eq = Button(self.root, text="=", command=lambda: self.solve_equation()) button_eq.grid(row=6, column=2) button_clear = Button(self.root, text="Clear", command=lambda: self.clear_equation()) button_clear.grid(row=1, column=4) button_clear = Button(self.root, text="<<<", command=lambda: self.back_on_equation()) button_clear.grid(row=1, column=5) button_pow = Button(self.root, text="^", command=lambda: self.append_sign("^")) button_pow.grid(row=2, column=4) button_par_left = Button(self.root, text="(", command=lambda: self.append_sign("(")) button_par_left.grid(row=2, column=5) button_pow = Button(self.root, text="!", command=lambda: self.append_sign("!")) button_pow.grid(row=3, column=4) button_par_right = Button(self.root, text=")", command=lambda: self.append_sign(")")) button_par_right.grid(row=3, column=5) button_sqrt = Button(self.root, text="sqrt", command=lambda: self.append_sign("sqrt")) button_sqrt.grid(row=4, column=4) button_abs_left = Button(self.root, text="|", command=lambda: self.append_sign("|")) button_abs_left.grid(row=4, column=5) button_mod = Button(self.root, text="mod", command=lambda: self.append_sign("mod")) button_mod.grid(row=5, column=4) button_abs_right = Button(self.root, text="|", command=lambda: self.append_sign("|")) button_abs_right.grid(row=5, column=5) button_log = Button(self.root, text="log", command=lambda: self.append_sign("log")) button_log.grid(row=6, column=4) button_dot = Button(self.root, text=".", command=lambda: self.append_sign(".")) button_dot.grid(row=6, column=5) def start_interface(self): self.root.mainloop() def append_sign(self, sign): if not sign.isnumeric() and sign != '.': sign = sign + " " if len(self.equation_to_display) > 0: if self.equation_to_display[-1] != " ": sign = " " + sign self.equation_to_display += sign self.entry_display.configure(text=self.equation_to_display) print(self.equation_to_display) def clear_equation(self): self.equation_to_display = "" self.entry_display.configure(text=self.equation_to_display) print(self.equation_to_display) def solve_equation(self): tree = parse_tree.infix_to_tree(self.equation_to_display) result = parse_tree.calculate_equation(tree) self.result_display.configure(text=str(result)) print(self.equation_to_display) def back_on_equation(self): if self.equation_to_display[-1] == " ": self.equation_to_display = self.equation_to_display[:-1] self.equation_to_display = self.equation_to_display[:-1] self.entry_display.configure(text=self.equation_to_display)
class Register(Frame): def __init__(self, master): super().__init__(master=master) self.layout_components() # Setup Callbacks self.show_sign_in: Callable = None self.sign_in: Callable = None self.search_email: Callable = None self.search_username: Callable = None self.search_password: Callable = None self.register: Callable = None self.username_valid: bool = False self.email_valid: bool = False self.password_valid: bool = False self.passcnfm_valid: bool = False # Refocus to Email Entry self.email_Entry.focus() def layout_components(self): self.pack(fill=tk.BOTH, expand=False, padx=PADX, pady=PADY) error_font = font.Font(family="Ariel", size=8) # Variables self.username = tk.StringVar() self.username.set("") self.email = tk.StringVar() self.email.set("") self.password = tk.StringVar() self.password.set("") self.passcnfm = tk.StringVar() self.passcnfm.set("") # Email Row email_Frame = Frame(self) email_Frame.pack(fill=tk.X) email_Label = Label(email_Frame, text="Email:", width=LABEL_WIDTH) email_Label.pack(side=tk.LEFT, padx=PADX, pady=PADY) self.email_Entry = Entry(email_Frame, width=ENTRY_WIDTH, textvariable=self.email) self.email_Entry.pack(fill=tk.X, padx=PADX, pady=PADY, expand=True) self.email_Entry.bind("<FocusOut>", self._validate_email) # Email Error Row email_errFrame = Frame(self) email_errFrame.pack(fill=tk.X) self.email_errLabel = Label(email_errFrame, text="", foreground="red", font=error_font) self.email_errLabel.pack(side=tk.LEFT, anchor="center", expand=True, padx=PADX, pady=PADY) # Username Row user_Frame = Frame(self) user_Frame.pack(fill=tk.X) user_Label = Label(user_Frame, text="Username:"******"<FocusOut>", self._validate_username) # Username Error Row user_errFrame = Frame(self) user_errFrame.pack(fill=tk.X) self.user_errLabel = Label(user_errFrame, text="", foreground="red", font=error_font) self.user_errLabel.pack(side=tk.LEFT, anchor="center", expand=True, padx=PADX, pady=PADY) # Original Password Row pass_Frame = Frame(self) pass_Frame.pack(fill=tk.X) pass_Label = Label(pass_Frame, text="Password:"******"*") self.pass_Entry.pack(fill=tk.X, padx=PADX, pady=PADY, expand=True) self.pass_Entry.bind("<FocusOut>", self._validate_password) # Confirming Password Row pass_cnfmFrame = Frame(self) pass_cnfmFrame.pack(fill=tk.X) pass_cnfmLabel = Label(pass_cnfmFrame, text="Confirm:", width=LABEL_WIDTH) pass_cnfmLabel.pack(side=tk.LEFT, padx=PADX, pady=PADY) self.pass_cnfmEntry = Entry(pass_cnfmFrame, width=ENTRY_WIDTH, textvariable=self.passcnfm, show="*") self.pass_cnfmEntry.pack(fill=tk.X, padx=PADX, pady=PADY, expand=True) self.pass_cnfmEntry.bind("<FocusOut>", self._validate_password) # Password Error Row pass_errFrame = Frame(self) pass_errFrame.pack(fill=tk.X) self.pass_errLabel = Label(pass_errFrame, text="", foreground="red", font=error_font) self.pass_errLabel.pack(side=tk.LEFT, anchor="center", expand=True, padx=PADX, pady=PADY) # Button Row button_Frame = Frame(self) button_Frame.pack(fill=tk.X) # Cancel Button cncl_Button = Button(button_Frame, text="Cancel", command=self.cancel) cncl_Button.pack(side=tk.RIGHT, padx=PADX, pady=PADY, expand=False) # Register Button self.register_Button = Button(button_Frame, text="Register", state="disabled", command=self._register) self.register_Button.pack(side=tk.RIGHT, padx=PADX, pady=PADY, expand=False) # View Password Button self.view_pass_Button = Button(button_Frame, text="View Password", command=self.view_password) self.view_pass_Button.pack(side=tk.LEFT, padx=PADX, pady=PADY) # Go Back Button Row gbck_Frame = Frame(self) gbck_Frame.pack(fill=tk.X) gbck_Label = Label(gbck_Frame, text="Have an Account? Go Ahead and ") gbck_Label.pack(side=tk.LEFT, padx=PADX, pady=PADY, expand=False) gbck_Button = Button(gbck_Frame, text="Sign In", command=self._show_sign_in) gbck_Button.pack(side=tk.RIGHT, padx=PADX, pady=PADY, expand=False) def cancel(self): self.email.set("") self.username.set("") self.password.set("") self.passcnfm.set("") self.email_Entry.focus() self.email_errLabel.configure(text="") self.user_errLabel.configure(text="") self.pass_errLabel.configure(text="") def view_password(self): self.pass_Entry.configure(show="") self.pass_cnfmEntry.configure(show="") self.view_pass_Button.configure(text="Hide Password", command=self.hide_password) def hide_password(self): self.pass_Entry.configure(show="*") self.pass_cnfmEntry.configure(show="*") self.view_pass_Button.configure(text="View Passwrod", command=self.view_password) def _show_sign_in(self): if self.show_sign_in is not None: self.show_sign_in() self.cancel() def _register(self): if self.register is not None: self.register() def _validate_email(self, event): email = self.email.get() if len(email) == 0: self.email_errLabel.configure(text="Email Must not be Empty...") self.email_valid = False elif not validate_email(email): self.email_errLabel.configure(text="Email Format Invalide...") self.email_valid = False elif self.search_email is not None and not self.search_email(email): self.email_errLabel.configure(text="Email Already Registered...") self.email_valid = False else: self.email_errLabel.configure(text="") self.email_valid = True self.enable_register() def _validate_username(self, event): username = self.username.get() if len(username) == 0: self.user_errLabel.configure(text="Username Must not be Empty...") self.username_valid = False elif self.search_username is not None and not self.search_username( username): self.username_valid = False else: self.user_errLabel.configure(text="") self.username_valid = True self.enable_register() def _validate_password(self, event): password = self.password.get() passcnfm = self.passcnfm.get() if len(password) == 0: self.pass_errLabel.configure(text="Password Must Not be Empty...") self.password_valid = False elif len(password) < 8: self.pass_errLabel.configure( text="Password Must be Longer than 8 Characters...") self.password_valid = False elif password != passcnfm: self.pass_errLabel.configure(text="Password Must Match... ") self.passcnfm_valid = False elif self.search_password is not None and not self.search_password( password): self.pass_errLabel.configure(text="") self.password_valid = False else: self.pass_errLabel.configure(text="") self.passcnfm_valid = True self.password_valid = True self.enable_register() def enable_register(self): if (self.email_valid and self.username_valid and self.password_valid and self.passcnfm_valid): self.register_Button.configure(state="normal") def failed_register(self): self.email.set("") self.username.set("") self.pass_errLabel.configure(text="Email or Username Already used") self.email_Entry.focus()
class GUI(Frame): def __init__(self, jointNumber): super().__init__() self.jointNumber = jointNumber self.initGUI() def quit(self): self.master.quit() self.master.destroy() def initGUI(self): try: self.master.title('VRGlove') self.master.geometry('1280x720') self.pack(fill=BOTH, expand=True) # Color list: https://xkcd.com/color/rgb/ self.colorList = ['xkcd:purple', 'xkcd:green', \ 'xkcd:blue', 'xkcd:pink', 'xkcd:brown', 'xkcd:red', \ 'xkcd:light blue', 'xkcd:teal', 'xkcd:orange', 'xkcd:light green', \ 'xkcd:magenta', 'xkcd:yellow', 'xkcd:cyan', 'xkcd:grey', \ 'xkcd:lime green', 'xkcd:light purple', 'xkcd:violet', 'xkcd:dark green', \ 'xkcd:turquoise', 'xkcd:lavender', 'xkcd:dark blue', 'xkcd:tan'] ################################################## # frameCalibrate = Frame(self) # frameCalibrate.pack(side=RIGHT, fill=Y) # labelPredict = Label(frameCalibrate, text='CALIBRATE', width=32) # labelPredict.pack(side=TOP, padx=5, pady=5) ################################################## framePredict = Frame(self) framePredict.pack(side=RIGHT, fill=Y) labelPredict = Label(framePredict, text='PREDICT') labelPredict.pack(side=TOP, padx=5, pady=5) self.textPredictResult = Label(framePredict, text='N/A', font=("Arial", 50), foreground='red') self.textPredictResult.pack(side=TOP, padx=5, pady=50) labelTrainer = Label(framePredict, text='TRAINER') labelTrainer.pack(side=TOP, padx=5, pady=5) labelTrainingCharacter = Label(framePredict, text='Training character') labelTrainingCharacter.pack(side=TOP, padx=5, pady=5) entryTrainingCharacter = Entry(framePredict, width=5, justify=CENTER) entryTrainingCharacter.pack(side=TOP, padx=5, pady=5) entryTrainingCharacter.insert(END, '5') labelSampleCount = Label(framePredict, text='Sample count') labelSampleCount.pack(side=TOP, padx=5, pady=5) self.textSampleCount = Label(framePredict, text=0) self.textSampleCount.pack(side=TOP, padx=5, pady=5) def sample(): messagebox.showerror("Infor", "Sorry, no answer available") # global threadQuatProcess # if not threadQuatProcess.collectSampleEnable: # threadQuatProcess.sampleCount = 0 # threadQuatProcess.collectSampleEnable = True # threadQuatProcess.trainingCharacter = entryTrainingCharacter.get() # print('\nStarted sampling!') # print('Sampling character: ' + threadQuatProcess.trainingCharacter + '\n') # buttonSample.configure(text='Stop sampling') # else: # threadQuatProcess.collectSampleEnable = False # print('\nStopped sampling!\n') # buttonSample.configure(text='Start sampling') buttonSample = Button(framePredict, text='Start sampling', command=sample) buttonSample.pack(side=TOP, padx=5, pady=5) def trainModel(): messagebox.showerror("Infor", "Sorry, no answer available") # global threadPredict # threadPredict.predictEnable = False # global threadQuatProcess # if threadQuatProcess.collectSampleEnable: # sample() # global threadTrainingModel # threadTrainingModel.train() # statusText = 'Training done!\nTime elapsed: ' + str(threadTrainingModel.timeElapsed) + ' ms\n' # statusText += 'Testing done!\nTraining accuracy: ' + str(threadTrainingModel.trainScore) + '%\n' # statusText += 'Saving done!\nFilename: ' + threadTrainingModel.modelFile # labelTrainingStatus.configure(text=statusText) # threadPredict.predictEnable = True buttonTrain = Button(framePredict, text='Train model', command=trainModel) buttonTrain.pack(side=TOP, padx=5, pady=5) labelTrainingStatus = Label(framePredict, text='Ready') labelTrainingStatus.pack(side=TOP, padx=5, pady=5) ################################################## frameGraph = Frame(self) frameGraph.pack(side=RIGHT, fill=BOTH, expand=True) labelGraph = Label(frameGraph, text='PREDICTION') labelGraph.pack(side=TOP, padx=5, pady=5) self.fig = plt.Figure(dpi = 100) ax = self.fig.add_subplot(111) ax.set(xlim = (0, 100), ylim = (-100, 100)) canvas = FigureCanvasTkAgg(self.fig, frameGraph) canvas.get_tk_widget().pack(fill=BOTH, padx=5, expand=True) # self.x = np.arange(0, 101, 1) # self.y = [] # self.line = [] # for i in range(jointNumber): # self.y.append([]) # for j in range(101): # self.y[i].append(0) # self.line.append(ax.plot(self.x, self.y[i], color=self.colorList[i], lw=1)[0]) # serialPort = StringVar(frameGraph) # serialPort.set('/dev/rfcomm0') # serialPortList = ['/dev/rfcomm0', '/dev/ttyACM0', '/dev/ttyACM1'] # serialPortOption = OptionMenu(frameGraph, serialPort, serialPortList[0], *serialPortList) # serialPortOption.pack(side=LEFT, padx=10, pady=10) def connect(): start = timer() loadmodel= joblib.load('finalizedModel.sav') temp = np.array(jointAngle).reshape(1,-1) yPredict = loadmodel.predict(temp) end = timer() predictResult = characterList[int(yPredict)] predictTime=end-start predictTime=round(predictTime,3) self.textPredictResult.configure(text=predictTime) img=mpimg.imread(ImageIndex[int(yPredict)]) imgplot=plt.imshow(img) plt.show() # global threadQuatProcess # threadQuatProcess.receiveQuatEnable = False # threadQuatProcess.changeSerialPort(serialPort.get()) # threadQuatProcess.receiveQuatEnable = True # print('\nConnected to ' + threadQuatProcess.serialPort + '!\n') buttonConnect = Button(frameGraph, text='Connect', command=connect) buttonConnect.pack(side=TOP, padx=5, pady=5) except: self.quit() def updateGraph(self, i): for i in range(jointNumber): global jointAngle self.y[i].pop(0) self.y[i].append(jointAngle[i]*180.0/3.1416) # self.y[i].append(randint(-90, 90)) self.line[i].set_ydata(self.y[i]) return self.line[i], #def updateParameters(self): # global threadPredict # global threadQuatProcess # self.textPredictResult.configure(text=threadPredict.predictResult) # self.textSampleCount.configure(text=threadQuatProcess.sampleCount) # self.master.after(100, self.updateParameters) #messagebox.showerror("Infor", "Sorry, no answer available") def run(self): self.ani = animation.FuncAnimation(self.fig, self.updateGraph, interval=100) #self.master.after(100, self.updateParameters) self.master.mainloop()
class MainWindow(object): def __init__(self, root, options): ''' ----------------------------------------------------- | main button toolbar | ----------------------------------------------------- | < ma | in content area > | | | | | File list | File name | | | | ----------------------------------------------------- | status bar area | ----------------------------------------------------- ''' # Obtain and expand the current working directory. if options.path: base_path = os.path.abspath(options.path) else: base_path = os.path.abspath(os.getcwd()) self.base_path = os.path.normcase(base_path) # Create a filename normalizer based on the CWD. self.filename_normalizer = filename_normalizer(self.base_path) # Set up dummy coverage data self.coverage_data = {'lines': {}, 'total_coverage': None} # Root window self.root = root self.root.title('Duvet') self.root.geometry('1024x768') # Prevent the menus from having the empty tearoff entry self.root.option_add('*tearOff', tk.FALSE) # Catch the close button self.root.protocol("WM_DELETE_WINDOW", self.cmd_quit) # Catch the "quit" event. self.root.createcommand('exit', self.cmd_quit) # Setup the menu self._setup_menubar() # Set up the main content for the window. self._setup_button_toolbar() self._setup_main_content() self._setup_status_bar() # Now configure the weights for the root frame self.root.columnconfigure(0, weight=1) self.root.rowconfigure(0, weight=0) self.root.rowconfigure(1, weight=1) self.root.rowconfigure(2, weight=0) ###################################################### # Internal GUI layout methods. ###################################################### def _setup_menubar(self): # Menubar self.menubar = tk.Menu(self.root) # self.menu_Apple = Menu(self.menubar, name='Apple') # self.menubar.add_cascade(menu=self.menu_Apple) self.menu_file = tk.Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_file, label='File') self.menu_help = tk.Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_help, label='Help') # self.menu_Apple.add_command(label='Test', command=self.cmd_dummy) # self.menu_file.add_command(label='New', command=self.cmd_dummy, accelerator="Command-N") # self.menu_file.add_command(label='Close', command=self.cmd_dummy) self.menu_help.add_command(label='Open Documentation', command=self.cmd_duvet_docs) self.menu_help.add_command(label='Open Duvet project page', command=self.cmd_duvet_page) self.menu_help.add_command(label='Open Duvet on GitHub', command=self.cmd_duvet_github) self.menu_help.add_command(label='Open BeeWare project page', command=self.cmd_beeware_page) # last step - configure the menubar self.root['menu'] = self.menubar def _setup_button_toolbar(self): ''' The button toolbar runs as a horizontal area at the top of the GUI. It is a persistent GUI component ''' # Main toolbar self.toolbar = tk.Frame(self.root) self.toolbar.grid(column=0, row=0, sticky=(tk.W, tk.E)) # Buttons on the toolbar self.refresh_button = tk.Button(self.toolbar, text='Refresh', command=self.cmd_refresh) self.refresh_button.grid(column=0, row=0) # Coverage summary for currently selected file. self.coverage_total_summary = tk.StringVar() self.coverage_total_summary_label = Label( self.toolbar, textvariable=self.coverage_total_summary, anchor=tk.E, padding=(5, 0, 5, 0), font=('Helvetica','20') ) self.coverage_total_summary_label.grid(column=1, row=0, sticky=(tk.W, tk.E)) self.toolbar.columnconfigure(0, weight=0) self.toolbar.columnconfigure(1, weight=1) self.toolbar.rowconfigure(0, weight=0) def _setup_main_content(self): ''' Sets up the main content area. It is a persistent GUI component ''' # Main content area self.content = PanedWindow(self.root, orient=tk.HORIZONTAL) self.content.grid(column=0, row=1, sticky=(tk.N, tk.S, tk.E, tk.W)) # Create the tree/control area on the left frame self._setup_left_frame() self._setup_project_file_tree() self._setup_global_file_tree() # Create the output/viewer area on the right frame self._setup_code_area() # Set up weights for the left frame's content self.content.columnconfigure(0, weight=1) self.content.rowconfigure(0, weight=1) self.content.pane(0, weight=1) self.content.pane(1, weight=4) def _setup_left_frame(self): ''' The left frame mostly consists of the tree widget ''' # The left-hand side frame on the main content area # The tabs for the two trees self.tree_notebook = Notebook( self.content, padding=(0, 5, 0, 5) ) self.content.add(self.tree_notebook) def _setup_project_file_tree(self): self.project_file_tree_frame = tk.Frame(self.content) self.project_file_tree_frame.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.E, tk.W)) self.tree_notebook.add(self.project_file_tree_frame, text='Project') self.project_file_tree = FileView(self.project_file_tree_frame, normalizer=self.filename_normalizer, root=self.base_path) self.project_file_tree.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.E, tk.W)) # # The tree's vertical scrollbar self.project_file_tree_scrollbar = tk.Scrollbar(self.project_file_tree_frame, orient=tk.VERTICAL) self.project_file_tree_scrollbar.grid(column=1, row=0, sticky=(tk.N, tk.S)) # # Tie the scrollbar to the text views, and the text views # # to each other. self.project_file_tree.config(yscrollcommand=self.project_file_tree_scrollbar.set) self.project_file_tree_scrollbar.config(command=self.project_file_tree.yview) # Setup weights for the "project_file_tree" tree self.project_file_tree_frame.columnconfigure(0, weight=1) self.project_file_tree_frame.columnconfigure(1, weight=0) self.project_file_tree_frame.rowconfigure(0, weight=1) # Handlers for GUI events self.project_file_tree.bind('<<TreeviewSelect>>', self.on_file_selected) def _setup_global_file_tree(self): self.global_file_tree_frame = tk.Frame(self.content) self.global_file_tree_frame.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.E, tk.W)) self.tree_notebook.add(self.global_file_tree_frame, text='Global') self.global_file_tree = FileView(self.global_file_tree_frame, normalizer=self.filename_normalizer) self.global_file_tree.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.E, tk.W)) # # The tree's vertical scrollbar self.global_file_tree_scrollbar = tk.Scrollbar(self.global_file_tree_frame, orient=tk.VERTICAL) self.global_file_tree_scrollbar.grid(column=1, row=0, sticky=(tk.N, tk.S)) # # Tie the scrollbar to the text views, and the text views # # to each other. self.global_file_tree.config(yscrollcommand=self.global_file_tree_scrollbar.set) self.global_file_tree_scrollbar.config(command=self.global_file_tree.yview) # Setup weights for the "global_file_tree" tree self.global_file_tree_frame.columnconfigure(0, weight=1) self.global_file_tree_frame.columnconfigure(1, weight=0) self.global_file_tree_frame.rowconfigure(0, weight=1) # Handlers for GUI events self.global_file_tree.bind('<<TreeviewSelect>>', self.on_file_selected) def _setup_code_area(self): self.code_frame = tk.Frame(self.content) self.code_frame.grid(column=1, row=0, sticky=(tk.N, tk.S, tk.E, tk.W)) # Label for current file self.current_file = tk.StringVar() self.current_file_label = Label(self.code_frame, textvariable=self.current_file) self.current_file_label.grid(column=0, row=0, sticky=(tk.W, tk.E)) # Code display area self.code = CodeView(self.code_frame) self.code.grid(column=0, row=1, sticky=(tk.N, tk.S, tk.E, tk.W)) # Set up weights for the code frame's content self.code_frame.columnconfigure(0, weight=1) self.code_frame.rowconfigure(0, weight=0) self.code_frame.rowconfigure(1, weight=1) self.content.add(self.code_frame) def _setup_status_bar(self): # Status bar self.statusbar = tk.Frame(self.root) self.statusbar.grid(column=0, row=2, sticky=(tk.W, tk.E)) # Coverage summary for currently selected file. self.coverage_file_summary = tk.StringVar() self.coverage_file_summary_label = Label(self.statusbar, textvariable=self.coverage_file_summary) self.coverage_file_summary_label.grid(column=0, row=0, sticky=(tk.W, tk.E)) self.coverage_file_summary.set('No file selected') # Main window resize handle self.grip = Sizegrip(self.statusbar) self.grip.grid(column=1, row=0, sticky=(tk.S, tk.E)) # Set up weights for status bar frame self.statusbar.columnconfigure(0, weight=1) self.statusbar.columnconfigure(1, weight=0) self.statusbar.rowconfigure(0, weight=0) ###################################################### # Utility methods for controlling content ###################################################### def show_file(self, filename, line=None, breakpoints=None): """Show the content of the nominated file. If specified, line is the current line number to highlight. If the line isn't currently visible, the window will be scrolled until it is. breakpoints is a list of line numbers that have current breakpoints. If refresh is true, the file will be reloaded and redrawn. """ # Set the filename label for the current file self.current_file.set(self.filename_normalizer(filename)) # Update the code view; this means changing the displayed file # if necessary, and updating the current line. if filename != self.code.filename: self.code.filename = filename missing = self.coverage_data['missing'].get(os.path.normcase(filename), []) executed = self.coverage_data['lines'].get(os.path.normcase(filename), []) n_executed = len(executed) n_missing = len(missing) self.code.highlight_missing(missing) self.coverage_file_summary.set('%s/%s lines executed' % (n_executed, n_executed + n_missing)) self.code.line = line def load_coverage(self): "Load and display coverage data" # Store the old list of files that have coverage data. # We do this so we can identify stale data on the tree. old_files = set(self.coverage_data['lines'].keys()) old_total_coverage = self.coverage_data['total_coverage'] loaded = False retry = True while not loaded and retry: try: # Load the new coverage data cov = coverage.coverage() cov.load() # Override precision for coverage reporting. coverage.results.Numbers.set_precision(1) if cov.data.measured_files(): self.coverage_data = { 'lines': {}, 'missing': {}, } totals = coverage.results.Numbers() # Update the coverage display of every file mentioned in the file. for filename in cov.data.measured_files(): filename = os.path.normcase(filename) node = nodify(filename) dirname, basename = os.path.split(filename) # If the normalized version of the filename is the same as the # filename, then the file *isn't* under the project root. if filename == self.filename_normalizer(filename): file_tree = self.global_file_tree else: file_tree = self.project_file_tree try: # # Make sure the file exists on the tree. file_tree.insert_filename(dirname, basename) # Compute the coverage percentage analysis = cov._analyze(filename) self.coverage_data['lines'][filename] = analysis.statements self.coverage_data['missing'][filename] = analysis.missing file_coverage = analysis.numbers.pc_covered totals = totals + analysis.numbers file_tree.set(node, 'coverage', analysis.numbers.pc_covered_str) # file_tree.set(node, 'branch_coverage', str(len(lines))) # Set the color of the tree node based on coverage if file_coverage < 70.0: file_tree.item(node, tags=['file', 'code', 'bad']) elif file_coverage < 80.0: file_tree.item(node, tags=['file', 'code', 'poor']) elif file_coverage < 90.0: file_tree.item(node, tags=['file', 'code', 'ok']) elif file_coverage < 99.9: file_tree.item(node, tags=['file', 'code', 'good']) else: file_tree.item(node, tags=['file', 'code', 'perfect']) except coverage.misc.NoSource: # could mean the file was deleted after running coverage file_tree.item(node, tags=['bad']) # We've updated the file, so we know it isn't stale. try: old_files.remove(filename) except KeyError: # File wasn't loaded before; ignore this. pass # Clear out any stale coverage data for filename in old_files: node = nodify(filename) if file_tree.exists(node): file_tree.set(node, 'coverage', '') file_tree.item(node, tags=['file', 'code']) # Compute the overall coverage total_coverage = totals.pc_covered self.coverage_data['total_coverage'] = total_coverage coverage_text = u'%.1f%%' % total_coverage # Update the text with up/down arrows to reflect change if old_total_coverage is not None: if total_coverage > old_total_coverage: coverage_text = coverage_text + u' ⬆' elif total_coverage < old_total_coverage: coverage_text = coverage_text + u' ⬇' self.coverage_total_summary.set(coverage_text) # Set the color based on coverage level. if total_coverage < 70.0: self.coverage_total_summary_label.configure(foreground='red') elif total_coverage < 80.0: self.coverage_total_summary_label.configure(foreground='orange') elif total_coverage < 90.0: self.coverage_total_summary_label.configure(foreground='blue') elif total_coverage < 99.9: self.coverage_total_summary_label.configure(foreground='cyan') else: self.coverage_total_summary_label.configure(foreground='green') # Refresh the file display current_file = self.code._filename if current_file: self.code._filename = None self.show_file(current_file) loaded = True else: retry = tkMessageBox.askretrycancel( message="Couldn't find coverage data file. Have you generated coverage data? Is the .coverage in your current working directory", title='No coverage data found' ) except Exception as e: retry = tkMessageBox.askretrycancel( message="Couldn't load coverage data -- data file may be corrupted (Error was: %s)" % e, title='Problem loading coverage data' ) return loaded ###################################################### # TK Main loop ###################################################### def mainloop(self): self.root.mainloop() ###################################################### # TK Command handlers ###################################################### def cmd_quit(self): "Quit the program" self.root.quit() def cmd_refresh(self, event=None): "Refresh the coverage data" self.load_coverage() def cmd_duvet_page(self): "Show the Duvet project page" webbrowser.open_new('http://pybee.org/duvet') def cmd_duvet_github(self): "Show the Duvet GitHub repo" webbrowser.open_new('http://github.com/pybee/duvet') def cmd_duvet_docs(self): "Show the Duvet documentation" # If this is a formal release, show the docs for that # version. otherwise, just show the head docs. if len(NUM_VERSION) == 3: webbrowser.open_new('https://duvet.readthedocs.io/en/v%s/' % VERSION) else: webbrowser.open_new('https://duvet.readthedocs.io/') def cmd_beeware_page(self): "Show the BeeWare project page" webbrowser.open_new('http://pybee.org/') ###################################################### # Handlers for GUI actions ###################################################### def on_file_selected(self, event): "When a file is selected, highlight the file and line" if event.widget.selection(): filename = event.widget.selection()[0] # Display the file in the code view if os.path.isfile(filename): self.show_file(filename=filename) else: self.code.filename = None
class TtkScale(Scale): def __init__(self, parent, length=0, from_=0, to=255, orient='horizontal', variable=0, digits=0, tickinterval=None, sliderlength=32, command=None, style=None, showvalue=True, resolution=1): self.from_ = from_ self.to = to self.variable = variable self.length = length self.command = command self.parent = parent self.orient = orient super().__init__(parent, length=length, from_=from_, to=to, orient=orient, variable=variable, command=command, style=style) self.digits = digits self.tickinterval = tickinterval self.showvalue = showvalue self.resolution = resolution self.sliderlength = sliderlength # = 32 theme_sl = { 'alt': 9, 'clam': 30, 'classic': 30, 'default': 30, 'lime': 9, 'winnative': 9 } theme_bw = { 'alt': 0, 'clam': 1, 'classic': 2, 'default': 1, 'lime': 6, 'winnative': 0 } # set trough borderwidth st = Style(self) theme_used = st.theme_use() if theme_used in ('alt', 'clam', 'classic', 'default', 'lime', 'winnative'): self.bw_val = bw_val = theme_bw[theme_used] self.sliderlength = sliderlength = theme_sl[theme_used] else: self.bw_val = bw_val = 1 if showvalue: self.configure(command=self.display_value) def_font = font.nametofont('TkDefaultFont') # if from_ more than to swap values if from_ < to: pass else: from_, to = to, from_ data = np.arange(from_, (to + 1 if tickinterval >= 1 else to + tickinterval), tickinterval) self.data = data = np.round(data, 1) range_vals = tuple(data) len_rvs = len(range_vals) if self.orient == 'horizontal': vals_size = [def_font.measure(str(i)) for i in range_vals] data_size = sum(vals_size) space_size = len_rvs * def_font.measure('0') else: lspace = def_font.metrics('linespace') data_size = len_rvs * lspace space_size = len_rvs * 3 sizes = data_size + space_size min_len = (sizes if sizes % 50 == 0 else sizes + 50 - sizes % 50) self.len_val = len_val = min_len if length < min_len else length self.configure(length=len_val) self.rel_min = rel_min = (sliderlength // 2 + bw_val) / len_val self.rel_max = rel_max = 1 - (sliderlength // 2 + bw_val) / len_val if range_vals[-1] == to: pass else: max_rv = range_vals[-1] self.mult_l = ((max_rv - from_) * rel_max / (to - from_)) self.bind("<Button-1>", self.resolve) self.build(from_, to, rel_min, rel_max, range_vals, len_rvs) def build(self, from_, to, rel_min, rel_max, range_vals, len_rvs): if self.orient == 'horizontal': for i, rv in enumerate(range_vals): item = Label(self.parent, text=rv) item.place( in_=self, bordermode='outside', relx=(rel_min + i / (len_rvs - 1) * ((rel_max if range_vals[-1] == to else self.mult_l) - rel_min)), rely=1, anchor='n') else: for i, rv in enumerate(range_vals): item = Label(self.parent, text=rv) item.place( in_=self, bordermode='outside', rely=(rel_min + i / (len_rvs - 1) * ((rel_max if range_vals[-1] == to else self.mult_l) - rel_min)), relx=1, anchor='w') if self.showvalue: self.disp_lab = Label(self.parent, text=self.get()) rel_l = self.convert_to_rel(float(self.get())) if self.orient == 'horizontal': self.disp_lab.place(in_=self, bordermode='outside', relx=rel_l, rely=0, anchor='s') else: self.disp_lab.place(in_=self, bordermode='outside', rely=rel_l, relx=0, anchor='e') def convert_to_rel(self, curr_val): return ((curr_val - self.from_) * (self.rel_max - self.rel_min) / (self.to - self.from_) + self.rel_min) def convert_to_act(self, curr_val): l_max = self.rel_max * self.len_val l_min = self.rel_min * self.len_val return ((curr_val - self.from_) * (l_max - l_min) / (self.to - self.from_) + l_min) def display_value(self, value): # position (in pixel) of the center of the slider rel_l = self.convert_to_rel(float(value)) self.disp_lab.config(text=value) # text="" if self.orient == 'horizontal': self.disp_lab.place_configure(relx=rel_l) else: self.disp_lab.place_configure(rely=rel_l) digits = self.digits self.disp_lab.configure(text=f'{float(value):.{digits}f}') # if your python is not 3.6 or above use the following 2 lines # instead of the line above #my_precision = '{:.{}f}'.format #self.disp_lab.configure(text=my_precision(float(value), digits)) def resolve(self, evt): resolution = self.resolution if resolution < 1 or self.tickinterval < 1: pass else: value = self.get() curr_l = self.convert_to_act(value) if self.orient == 'horizontal': if evt.x < curr_l - self.sliderlength / 2: self.set(value - resolution + 1) elif evt.x > curr_l + self.sliderlength / 2: self.set(value + resolution - 1) else: if evt.y < curr_l - self.sliderlength / 2: self.set(value - resolution + 1) elif evt.y > curr_l + self.sliderlength / 2: self.set(value + resolution - 1)