def toggle_items(self, btn: tk.Button, frm: tk.Frame): if btn['bg'] == 'gray': frm.pack(side=tk.BOTTOM) btn['bg'] = 'white' else: frm.pack_forget() btn['bg'] = 'gray'
class LoginScreen(Window): def __init__(self, program): super().__init__(program) self.levels = None self.settings = program.settings self.level_handler = LevelHandler(program.settings) self.frame = Frame(program.master, width=800, height=800) self.frame.pack(side='top', fill='both', expand=1) self.show() def add_button(self, text, command): button = Button(self.frame, text=text, width=100, height=20, command=command) button.pack() def dispose(self): self.frame.pack_forget() self.frame.destroy() self.frame = None def show(self): self.add_button('New Game', self.new_game) self.add_button('Load Game', self.load_game) self.add_button('Exit', self.exit) self.frame.tkraise() def new_game(self): self.dispose() g = Game(self.program) g.new() self.change(Game(self.program)) def exit(self): self.program.exit() def load_game(self): self.dispose() lg = LoadGame(self.program) lg.show() self.change(lg) def clear(self): self.frame.pack_forget() self.level_handler = None self.frame.destroy()
class Level: def __init__(self, calc, levels, current=None): self.calc = calc self.master = calc.master self.levels = levels #allowed levels in current game self.current = current self.leveldone_image = Image.open(r'images\done.png').resize((20, 20), Image.ANTIALIAS) self.levelundone_image = Image.open(r'images\undone.png').resize((20, 20), Image.ANTIALIAS) self.levelpending_image = Image.open(r'images\pending.png').resize((20, 20), Image.ANTIALIAS) self.leveldone_photo = ImageTk.PhotoImage(self.leveldone_image) self.levelundone_photo = ImageTk.PhotoImage(self.levelundone_image) self.levelpending_photo = ImageTk.PhotoImage(self.levelpending_image) self.field = Frame(self.master) self.update() def response(self, i): self.calc.start_game(i) def update(self): #assuming levels preserves order and current >= levels[0] self.field.pack_forget() image = self.leveldone_photo labeling = False if self.current is None: self.current = self.identify_level() self.labels = dict() for i in self.levels: if i == self.current: image = self.levelpending_photo self.labels[i] = Button(self.field, image=image, command=lambda x=i: self.response(x), bg='green') self.labels[i].pack(side="left") image = self.levelundone_photo labeling = True continue if not(labeling): self.labels[i] = Button(self.field, image=image, command=lambda x=i: self.response(x)) self.labels[i].pack(side="left") else: self.labels[i] = Label(self.field, image=image) self.labels[i].pack(side="left") self.field.grid(row=0, column=5, columnspan=2, sticky="nesw") def remove(self): for n in self.labels.values(): n.pack_forget() def identify_level(self): return read('register.txt', pprint=False, allowed=self.levels)
class LoadGame(Window): def __init__(self, program): super().__init__(program) self.frame = Frame(program.master, width=800, height=800) self.frame.pack(side='top', fill='both', expand=1) self.listbox = Listbox() self.save_names = [] def dispose(self): self.listbox.pack_forget() self.frame.pack_forget() self.listbox.destroy() self.frame.destroy() self.listbox = None self.frame = None def show(self): for file_name, file_path in self.program.settings.list_saves(): self.listbox.insert(END, file_name) self.save_names.append(file_name) self.listbox.pack() self.add_button('Back', self.back) self.add_button('Load', self.load) def load(self): selection = next(iter(map(int, self.listbox.curselection()))) self.dispose() g = Game(self.program) g.load(self.save_names[selection]) self.change(g) def back(self): self.dispose() self.change(LoginScreen(self.program)) def add_button(self, text, command): button = Button(self.frame, text=text, width=100, height=20, command=command) button.pack()
class Confirmation: def __init__(self, root, message, experiment): self.experiment = experiment self.frame = Frame(root) self.frame.pack(fill=X) self.label = Label(self.frame, text=message) self.label.pack() self.button = Button(self.frame, text="Open", command=self.open) self.button.pack() self.button = Button(self.frame, text="Dismiss", command=self.close) self.button.pack() def open(self): webbrowser.open( f'https://app.labstep.com/experiment-workflow/{self.experiment.id}/results', new=2) self.frame.pack_forget() def close(self): self.frame.pack_forget()
class Window: """ Abstract Window class """ def __init__(self, root): self.root = root self.frame = Frame(master=self.root, bd=0, height=670, width=1280, bg=BACKGROUND) def show(self): self.frame.pack(side=TOP) self.frame.pack_propagate(0) def hide(self): self.frame.pack_forget() def update(self): self.frame.update()
class Component: def __init__(self, app): self.nav = Frame(app.nav, bg="#5a5a5a") self.app = app self.range = [0, 200] def render(self): self.nav.pack(side="left") def receive_range(self): self.range = self.app.current_range def receive_grid(self, grid): pass def size_changed(self): pass def uninstall(self): self.nav.pack_forget() self.app.components.remove(self)
class Scene(object): scenemanager = SceneManager() def __init__(self, root): self.frame = Frame(root) def hide_scene(self): self.frame.pack_forget() def show_scene(self, *args, **kwargs): self.frame.pack(fill="both", expand=True) def start_scene(self): pass def update(self): pass def tick_update(self): pass def __repr__(self): return f"SceneObject<{self.__class__.__name__}>"
def pack_forget(self, *args, **kargs): self._game_scene.restart_game() Frame.pack_forget(self, *args, **kargs)
class View: def __init__(self): self.root = Tk() self.root.title("Stroop Test") self.root.geometry('800x600') self.root.resizable(0, 0) # Configuramos la pantalla inicial self.initial_screen = Frame(self.root) self.initial_screen.config(bg='lightblue') self.initial_screen_name_label = Label( self.initial_screen, text='Nombre') self.initial_screen_name_entry = Entry( self.initial_screen) self.initial_screen_age_label = Label( self.initial_screen, text='Edad') self.initial_screen_age_entry = Entry(self.initial_screen) self.initial_screen_email_label = Label( self.initial_screen, text='Email') self.initial_screen_email_entry = Entry(self.initial_screen) self.initial_screen_instructions_label = Label( self.initial_screen, text='Para realizar este test debe' 'presionar en su teclado la flecha que corresponde\n' 'a la palabra que figura en pantalla. \n Para Rojo presione ←, ' 'para Azul presione ↑, para Verde ' 'presione ↓ y para Amarillo presione →', font=('Candara', 12), bg='lightblue') self.initial_screen_start_button = Button( self.initial_screen, text='Comenzar') # Entradas con los datos del usuario self.initial_screen_name_entry.insert(0, '') self.initial_screen_age_entry.insert(0, '') self.initial_screen_email_entry.insert(0, '') # Configuramos la pantalla del test self.test_screen = Frame(self.root) self.test_screen.config(bg="black") self.test_screen_label = Label( self.test_screen, width=40, text="Presioná cualquier tecla\npara comenzar", font=("Calibri", 35), fg='white', bg='black') # Configuramos la pantalla de los resultados self.score_board = Frame(self.root) self.score_board.config(bg="lightblue") self.score_board_user_label = Label(self.score_board) self.score_board_user_result = Label( self.score_board) self.score_board_first_place = Label( self.score_board, text='1.') self.score_board_second_place = Label( self.score_board, text='2.') self.score_board_third_place = Label( self.score_board, text='3.') self.score_board_erase_button = Button( self.score_board, text='Borrar tu resultado') self.show_initial_screen() return def show_initial_screen(self): self.initial_screen.pack(side='top', fill='both', expand=True) self.initial_screen_name_label.pack( side='top', pady=50) self.initial_screen_name_entry.pack(side='top') self.initial_screen_age_label.pack( side='top', pady=40) self.initial_screen_age_entry.pack(side='top') self.initial_screen_email_label.pack( side='top', pady=40) self.initial_screen_email_entry.pack(side='top') self.initial_screen_start_button.pack( side='bottom', anchor=SE, padx=30, pady=40) self.initial_screen_instructions_label.pack( side='bottom', anchor=CENTER, pady=20) return def hide_initial_screen(self): # Nos sirve para que no aparezca ningún widget de la pantalla inicial self.initial_screen.pack_forget() return def change_from_initial_to_test_screen(self): # Cambiamos a la pantalla inicial a la pantalla del test self.hide_initial_screen() self.show_test_screen() return def show_error_message_pop_up(self, message): # Creamos una ventana de error messagebox.showerror('Error', message) return def show_test_screen(self): self.test_screen.pack(side='top', fill='both', expand=True) self.test_screen_label.pack(side='top', pady=250) self.test_screen.focus_set() return def hide_test_screen(self): self.test_screen.pack_forget() return def change_from_test_to_score_board(self): # Cambiamos de la pantalla del test a la pantalla de resultados self.hide_test_screen() self.show_score_board() return def show_score_board(self): self.score_board.pack(side='top', fill='both', expand=True) self.score_board_user_label.pack(side='top', anchor=NW, pady=50) self.score_board_user_result.pack(side='top') self.score_board_first_place.pack(side='top') self.score_board_second_place.pack(side='top') self.score_board_third_place.pack(side='top') self.score_board_erase_button.pack(side='bottom', pady=50) return def set_score_board_current_user_name(self, name): # Dato del nombre del usuario actual self.score_board_user_label.config(text='Nombre: ' + name) return def set_score_board_current_test_score(self, test_score): # Dato del último resultado del usuario actual self.score_board_user_result.config( text='Tu puntaje fue de: %.2f' % test_score) return def set_score_board_first_place_user(self, user): # Consultamos el primer lugar con nombre de usuario y resultado self.score_board_first_place.config( text='1. %s (%.2f)' % (user.name, user.average_score)) return def set_score_board_second_place_user(self, user): # Consultamos el segundo lugar con nombre de usuario y resultado self.score_board_second_place.config( text='1. %s (%.2f)' % (user.name, user.average_score)) return def set_score_board_third_place_user(self, user): # Consultamos el tercer lugar con nombre de usuario y resultado self.score_board_third_place.config( text='1. %s (%.2f)' % (user.name, user.average_score)) return def disable_erase_button(self): # Desactivamos el botón Borrar los resultados una vez presionado self.score_board_erase_button.config(state=DISABLED) return def show_user_data_deleted_message(self): # Ventana emergente que corrobora que los datos fueron borrados messagebox.showinfo('OK', 'Datos borrados con éxito') return def start_gui(self): self.root.mainloop() return
class GraphyInspector: def __init__(self, parent): self.parent = parent self.width = self.parent.right_frame_width self.padding = self.parent.right_frame_padding self.frame = Frame(master=self.parent.right_frame) self.frame.pack(side='top', fill='y', ) # "Inspector" title bar self.title_frame = Frame(master=self.frame) self.title_frame.pack(side='top') self.title_label = Label(master=self.title_frame, text="Inspector", width=self.width, bg='lightgray') self.title_label.pack() # identifier for type of object selected self.type_frame = Frame(master=self.frame, relief='sunken') self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.type_label1 = Label(master=self.type_frame, width=int(self.width/2)-self.padding, text='Object:') self.type_label1.pack(side='left', padx=self.padding, pady=self.padding) self.type_label2 = Label(master=self.type_frame, width=int(self.width / 2) - self.padding, text='', bg='white') self.type_label2.pack(side='right', padx=self.padding, pady=self.padding) # label of selected object (i.e. name user gives them, no canvas IDs here) self.label_frame = Frame(master=self.frame, relief='sunken') self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_label = Label(master=self.label_frame, width=int(self.width/2)-self.padding, text="Label:") self.label_label.pack(side='left', padx=self.padding, pady=self.padding) self.label_var = StringVar() self.label_var.set('') self.label_entry = Entry(self.label_frame, width=int(self.width/2)-self.padding, textvariable=self.label_var) self.label_entry.pack(side='right', padx=self.padding, pady=self.padding) self.label_entry.bind('<Button-1>', self.select_label_text) self.label_entry.bind('<Return>', self.drop_widget_focus) # status identifier (for vertices and layers) self.status_frame = Frame(master=self.frame, relief='sunken') self.status_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.status_label1 = Label(master=self.status_frame, width=int(self.width/2)-self.padding, text='Status:') self.status_label1.pack(side='left', padx=self.padding, pady=self.padding) self.status_label2 = Label(master=self.status_frame, width=int(self.width/2)-self.padding, text='', bg='white') self.status_label2.pack(side='right', padx=self.padding, pady=self.padding) self.activation_var = StringVar() self.activation_var.set('') self.activation_menu = OptionMenu(self.status_frame, self.activation_var, "Identity", "Sigmoid", "ReLU", "Logarithmic", "Exponential") self.activation_menu.pack(side='right', padx=self.padding, pady=self.padding) # weight identifier (for edges only) self.weight_frame = Frame(master=self.frame, relief='sunken') self.weight_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.weight_label = Label(master=self.weight_frame, width=int(self.width/2)-self.padding, text="Weight:") self.weight_label.pack(side='left', padx=self.padding, pady=self.padding) self.weight_var = DoubleVar() self.weight_entry = Entry(self.weight_frame, width=int(self.width / 2) - self.padding, textvariable=self.weight_var) self.weight_entry.pack(side='right', padx=self.padding, pady=self.padding) self.weight_entry.bind('<Button-1>', self.select_weight_text) self.weight_entry.bind('<Return>', self.drop_widget_focus) # node count identifier (for layers only) self.node_frame = Frame(master=self.frame, relief='sunken') self.node_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.node_label = Label(master=self.node_frame, width=int(self.width/2)-self.padding, text="Node Count:") self.node_label.pack(side='left', padx=self.padding, pady=self.padding) self.node_var = IntVar() self.node_entry = Entry(self.node_frame, width=int(self.width / 2) - self.padding, textvariable=self.node_var) self.node_entry.pack(side='right', padx=self.padding, pady=self.padding) self.node_entry.bind('<Button-1>', self.select_node_text) self.node_entry.bind('<Return>', self.drop_widget_focus) # leakiness self.leakiness_frame = Frame(master=self.frame, relief='sunken') self.leakiness_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.leakiness_label = Label(master=self.leakiness_frame, width=int(self.width/2)-self.padding, text="Leakiness") self.leakiness_label.pack(side='left', padx=self.padding, pady=self.padding) self.leakiness_var = DoubleVar() self.leakiness_entry = Entry(self.leakiness_frame, width=int(self.width / 2) - self.padding, textvariable=self.leakiness_var) self.leakiness_entry.pack(side='right', padx=self.padding, pady=self.padding) self.leakiness_entry.bind('<Button-1>', self.select_leakiness_text) self.leakiness_entry.bind('<Return>', self.drop_widget_focus) # bias self.bias_frame = Frame(master=self.frame, relief='sunken') self.bias_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.bias_label = Label(master=self.bias_frame, width=int(self.width/2)-self.padding, text="Bias:") self.bias_label.pack(side='left', padx=self.padding, pady=self.padding) self.bias_var = DoubleVar() self.bias_entry = Entry(self.bias_frame, width=int(self.width / 2) - self.padding, textvariable=self.bias_var) self.bias_entry.pack(side='right', padx=self.padding, pady=self.padding) self.bias_entry.bind('<Button-1>', self.select_bias_text) self.bias_entry.bind('<Return>', self.drop_widget_focus) # output bound self.bound_frame = Frame(master=self.frame, relief='sunken') self.bound_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.bound_label = Label(master=self.bound_frame, width=int(self.width/2)-self.padding, text="Output Bound:") self.bound_label.pack(side='left', padx=self.padding, pady=self.padding) self.bound_var = DoubleVar() self.bound_entry = Entry(self.bound_frame, width=int(self.width / 2) - self.padding, textvariable=self.bound_var) self.bound_entry.pack(side='right', padx=self.padding, pady=self.padding) self.bound_entry.bind('<Button-1>', self.select_bound_text) self.bound_entry.bind('<Return>', self.drop_widget_focus) # noise self.noise_frame = Frame(master=self.frame, relief='sunken') self.noise_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.noise_label = Label(master=self.noise_frame, width=int(self.width/2)-self.padding, text="Weight Noise:") self.noise_label.pack(side='left', padx=self.padding, pady=self.padding) self.noise_var = DoubleVar() self.noise_entry = Entry(self.noise_frame, width=int(self.width / 2) - self.padding, textvariable=self.noise_var) self.noise_entry.pack(side='right', padx=self.padding, pady=self.padding) self.noise_entry.bind('<Button-1>', self.select_noise_text) self.noise_entry.bind('<Return>', self.drop_widget_focus) # input / output self.input_output_frame = Frame(master=self.frame, relief='sunken') self.input_output_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.input_var = BooleanVar() self.input_var.set(False) self.output_var = BooleanVar() self.output_var.set(False) self.input_toggle = Checkbutton(master=self.input_output_frame, text="Is Input", variable=self.input_var) self.output_toggle = Checkbutton(master=self.input_output_frame, text="Is Output", variable=self.output_var) self.input_toggle.pack(side='left', padx=self.padding, pady=self.padding) self.output_toggle.pack(side='left', padx=self.padding, pady=self.padding) self.selected = None self.selected_type = None self.set_unselected() self.label_var.trace('w', self.set_selected_label) self.weight_var.trace('w', self.set_selected_weight) self.activation_var.trace('w', self.set_selected_activation) self.leakiness_var.trace('w', self.set_selected_leakiness) self.node_var.trace('w', self.set_selected_node_count) self.bias_var.trace('w', self.set_selected_bias) self.bound_var.trace('w', self.set_selected_bound) self.noise_var.trace('w', self.set_selected_noise) self.input_var.trace('w', self.set_input) self.output_var.trace('w', self.set_output) # mode self.mode = parent.mode self.set_mode(parent.mode) # object is a vertex or edge, type is 'vertex' or 'edge'... def set_selected(self, selected_object, selected_object_type): self.selected = selected_object self.selected_type = selected_object_type if self.mode == "Graph": if selected_object_type == 'vertex': self.type_label2.config(text="Vertex") self.status_label2.config(text=selected_object.status) self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.status_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_var.set(selected_object.label) elif selected_object_type == 'edge': self.type_label2.config(text="Edge") self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.weight_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_var.set(selected_object.label) self.weight_var.set(selected_object.weight) else: print('dafuq is going on') elif self.mode == "Net": if selected_object_type == 'vertex': self.type_label2.config(text="Layer") self.status_label2.config(text=selected_object.status) self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.status_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.node_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.leakiness_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.bias_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.bound_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.input_output_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_var.set(selected_object.label) self.node_var.set(selected_object.node_count) self.activation_var.set(selected_object.status) self.leakiness_var.set(selected_object.leakiness) self.bias_var.set(selected_object.bias) self.bound_var.set(selected_object.bound) self.input_var.set(selected_object.is_input_layer) self.output_var.set(selected_object.is_output_layer) elif selected_object_type == 'edge': self.type_label2.config(text="Weights") self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.weight_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.noise_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding) self.label_var.set(selected_object.label) self.weight_var.set(selected_object.weight) self.noise_var.set(selected_object.noise) else: print('This will never happen.') # nothing is selected def set_unselected(self): self.type_frame.pack_forget() self.label_frame.pack_forget() self.status_frame.pack_forget() self.weight_frame.pack_forget() self.node_frame.pack_forget() self.bias_frame.pack_forget() self.bound_frame.pack_forget() self.noise_frame.pack_forget() self.input_output_frame.pack_forget() self.leakiness_frame.pack_forget() self.selected = None self.selected_type = None # set label of selected object def set_selected_label(self, *args): self.selected.set_label(self.label_var.get()) # set weight of selected object def set_selected_weight(self, *args): self.selected.set_weight(self.weight_var.get()) def set_selected_activation(self, *args): self.selected.set_status(self.activation_var.get()) def set_selected_node_count(self, *args): self.selected.set_node_count(self.node_var.get()) def set_selected_bias(self, *args): self.selected.set_bias(self.bias_var.get()) def set_selected_bound(self, *args): self.selected.set_bound(self.bound_var.get()) def set_selected_noise(self, *args): self.selected.set_noise(self.noise_var.get()) def set_input(self, *args): self.selected.set_input_layer(self.input_var.get()) def set_output(self, *args): self.selected.set_output_layer(self.output_var.get()) def set_selected_leakiness(self, *args): self.selected.set_leakiness(self.leakiness_var.get()) def update(self): if self.selected: selected = self.selected type = self.selected_type self.set_unselected() self.set_selected(selected, type) def select_label_text(self, event): if event: # delay so the default click doesn't undo selection, then recall and fall through to "else" self.parent.tk.after(50, self.select_label_text, False) else: self.label_entry.select_range(0, 'end') self.label_entry.icursor(0) def select_weight_text(self, event): if event: # delay so the default click doesn't undo selection, then recall and fall through to "else" self.parent.tk.after(50, self.select_weight_text, False) else: self.weight_entry.select_range(0, 'end') self.weight_entry.icursor(0) def select_node_text(self, event): if event: self.parent.tk.after(50, self.select_node_text, False) else: self.node_entry.select_range(0, 'end') self.node_entry.icursor(0) def select_bias_text(self, event): if event: self.parent.tk.after(50, self.select_bias_text, False) else: self.bias_entry.select_range(0, 'end') self.bias_entry.icursor(0) def select_noise_text(self, event): if event: self.parent.tk.after(50, self.select_noise_text, False) else: self.noise_entry.select_range(0, 'end') self.noise_entry.icursor(0) def select_bound_text(self, event): if event: self.parent.tk.after(50, self.select_bound_text, False) else: self.bound_entry.select_range(0, 'end') self.bound_entry.icursor(0) def select_leakiness_text(self, event): if event: self.parent.tk.after(50, self.select_leakiness_text, False) else: self.leakiness_entry.select_range(0, 'end') self.leakiness_entry.icursor(0) def drop_widget_focus(self, event): self.frame.focus() def set_mode(self, mode): if mode == "Graph": self.mode = mode self.weight_label.config(text="Weight:") self.status_label1.config(text="Status:") self.activation_menu.pack_forget() self.input_output_frame.pack_forget() self.status_label2.pack(side='right', padx=self.padding, pady=self.padding) elif mode == "Net": self.mode = mode self.weight_label.config(text="Start Weight:") self.status_label1.config(text="Activation:") self.status_label2.pack_forget() self.activation_menu.pack(side='right', padx=self.padding, pady=self.padding) else: print("This will never happen.")
class TelaInicial(): #================================================================== def __init__(self, janela): janela.title("Puro Fit") self.janela = janela self.janela.configure(background="azure2") self.janela.geometry("325x300+400+200") #=Criação e posicionamento de elementos da tela self.frm_upper = Frame(janela, bg="azure2") self.frm_down = Frame(janela, bg="azure2") tam = 10 self.lb_title = Label(self.frm_upper, text="Puro Fit", font=('arial', '30'), fg="midnight blue", bg="azure2") self.btn_plotar = Button(self.frm_down, text="Novo ajuste", command=self.proxJanelaNovo, bg="LightSkyBlue4", width=tam) self.btn_sair = Button(self.frm_down, text="Sair", command=self.janela.destroy, bg="LightSkyBlue4", width=tam) self.ocupar = Label(self.frm_upper, width=37, height=3, bg="azure2") self.ocupar2 = Label(self.frm_upper, width=37, height=3, bg="azure2") self.ocupar.pack(side=TOP) self.lb_title.pack(side=TOP) self.ocupar2.pack(side=TOP) self.frm_upper.pack(side=TOP) self.frm_down.pack(side=TOP) self.lb_title.pack(side=TOP) self.btn_plotar.pack(side=TOP) self.btn_sair.pack(side=BOTTOM) #================================================================== #=Passa para a próxima janela, limpando a anterior antes def proxJanelaNovo(self): self.limparJanela() TelaPontos(self.janela, self) #================================================================== #= Caso seja necessário retornar a essa janela, os objetos devem ser #= redesenhados. def redesenhar(self): self.frm_upper.pack(side=TOP) self.frm_down.pack(side=TOP) self.ocupar.pack(side=TOP) self.lb_title.pack(side=TOP) self.ocupar2.pack(side=TOP) self.btn_plotar.pack(side=TOP) self.btn_sair.pack(side=BOTTOM) #================================================================== #= Caso seja necessário sair dessa janela, os objetos devem ser apagados. def limparJanela(self): self.lb_title.pack_forget() self.btn_plotar.pack_forget() self.btn_sair.pack_forget() self.ocupar.pack_forget() self.ocupar2.pack_forget() self.frm_upper.pack_forget() self.frm_down.pack_forget()
class TestApp(Frame): def __init__(self, parent=None): self.root = tk() root = self.root self.parent = parent Frame.__init__(self) top_frame = Frame(root) bottom = Frame(root) box_frame = Frame(top_frame) label_frame = Frame(box_frame) input_frame = Frame(box_frame) bottom.pack(side=BOTTOM, fill=BOTH, expand=True) # Packings top_frame.pack(side=TOP) bottom.pack(side=BOTTOM, fill=BOTH, expand=True) box_frame.pack(side=LEFT) label_frame.pack(side=TOP) input_frame.pack(side=BOTTOM) # create the widgets for the top part of the GUI, # and lay them out self.ticker_field = Text(top_frame, width=5, height=1) self.time_range = Text(top_frame, width=2, height=1) ticker_label = Label(top_frame, text="Ticker:", width=5, height=1) time_label = Label(top_frame, text="Hrs", width=2, height=1) button1 = Button(root, text="Recent Posts", width=10, height=2, command=self.recent_posts) button3 = Button(root, text="Summary", width=10, height=2, command=self.trending_posts) button2 = Button(root, text="All Posts", width=10, height=2, command=self.all_posts) button4 = Button(root, text="Open Url", width=10, height=2, command=self.open_url) button1.pack(in_=top_frame, side=LEFT) button3.pack(in_=top_frame, side=LEFT) button2.pack(in_=top_frame, side=LEFT) button4.pack(in_=top_frame, side=LEFT) ticker_label.pack(in_=label_frame, side=LEFT) time_label.pack(in_=label_frame, side=LEFT) self.ticker_field.pack(in_=input_frame, side=LEFT) self.time_range.pack(in_=input_frame, side=LEFT) self.main = self.master self.main.geometry('1200x800+200+100') self.main.title('Table app') # btn2 = Button(self.root, text="Ticker Post History", command=self.button2) # btn2.pack() # urlbtn = Button(self.root, text="Open url", command=self.open_url) # urlbtn.pack() self.f = Frame(self.main) self.f.pack(fill=BOTH, expand=1) # df = panda_db.get_trending() df = panda_db.get_all_posts("8") # df = panda_db.get_posts_by_ticker("AI") self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() return def all_posts(self): date_range = str(self.time_range.get("1.0", END)) df = panda_db.get_all_posts(date_range) self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() self.table.redraw() def recent_posts(self): ticker = str(self.ticker_field.get("1.0", END)) print(ticker) date_range = str(self.time_range.get("1.0", END)) self.f.pack_forget() df = panda_db.get_posts_by_ticker(ticker.upper(), date_range) self.f.pack(fill=BOTH, expand=1) self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() self.table.redraw() def trending_posts(self): self.f.pack_forget() date_range = str(self.time_range.get("1.0", END)) df = panda_db.get_trending(date_range) self.f.pack(fill=BOTH, expand=1) self.table = Table(self.f, dataframe=df, showtoolbar=True, showstatusbar=True) self.table.show() self.table.redraw() def open_url(self): url = self.table.selection_get() webbrowser.register( 'chrome', None, webbrowser.BackgroundBrowser( "C://Users//awgra//AppData//Local//Google//Chrome//Application//chrome.exe" )) webbrowser.get('chrome').open(url)
class AOTGui: def __init__(self): self.gui = Tk() self.gui.title(client_title) self.gui.geometry('800x500') self.numRow = 0 scrollbar = Scrollbar(self.gui) self.canvas = Canvas(self.gui, bg='pink', yscrollcommand=scrollbar.set) scrollbar.config(command=self.canvas.yview) scrollbar.pack(side=RIGHT, fill=Y) self.frame = Frame(self.canvas) self.canvas.pack(side=LEFT, fill=BOTH, expand=True) self.canvas.create_window(0, 0, window=self.frame, anchor=NW) self.var_city = StringVar(self.frame) self.var_file = StringVar(self.frame) self.var_city.set(city_list[0]) self.var_file.set(file_list[0]) Label(self.frame, text='Version '+str(client_version), bg='turquoise').grid(row=0, column=0) Label(self.frame, text='City').grid(row=1, column=0, sticky=W) OptionMenu(self.frame, self.var_city, *city_list).grid(row=1, column=1, sticky=W) Label(self.frame, text='Items', padx=15).grid(row=1, column=2, sticky=W) OptionMenu(self.frame, self.var_file, *file_list).grid(row=1, column=3, sticky=W) Button(self.frame, text='Search', command=self.cmd_search).grid(row=1, column=4, sticky=W) Label(self.frame, text='Item').grid(row=2, column=0, columnspan=2, sticky=W) Label(self.frame, text='Price', padx=15).grid(row=2, column=2, sticky=W) Label(self.frame, text='Black Market', padx=15).grid(row=2, column=3, sticky=W) Label(self.frame, text='Profit', padx=15).grid(row=2, column=4, sticky=W) self.gui.update() self.canvas.config(scrollregion=self.canvas.bbox('all')) self.gui.mainloop() def human_readable_value(self,value): if 1e3 <= value < 1e6: return str(round(value/1e3)) + ' k' elif 1e6 <= value: return str(round(value/1e6, 1)) + ' m' else: return str(value) def add_item(self, item_id, name, price, blackmarket, profit): img = PhotoImage(file='img/'+item_id+'.png') label = Label(self.frame, image=img) label.image = img label.grid(row=3+self.numRow, column=0, sticky=W) Label(self.frame, text=name).grid(row=3+self.numRow, column=1, sticky=W) Label(self.frame, text=self.human_readable_value(price), padx=15).grid(row=3+self.numRow, column=2, sticky=W) Label(self.frame, text=self.human_readable_value(blackmarket), padx=15).grid(row=3+self.numRow, column=3, sticky=W) Label(self.frame, text=self.human_readable_value(profit), padx=15).grid(row=3+self.numRow, column=4, sticky=W) self.numRow += 1 self.gui.update() self.canvas.config(scrollregion=self.canvas.bbox('all')) def reset(self): self.numRow = 0 for widget in self.frame.winfo_children()[10:]: widget.destroy() self.frame.pack_forget() def cmd_search(self): self.reset() city = self.var_city.get() item_file = 'items/' + self.var_file.get() item_query = open(item_file, 'r').read().replace('\n', ',')[:-1] item_array = open(item_file, 'r').read().split('\n') r = item_requests(item_array, city) if not item_query: return response_city= r[0] response_blackmarket = r[1] # response_city = requests.get(data_route + item_query + '?locations=' + city).json() # response_blackmarket = requests.get(data_route + item_query + '?locations=blackmarket').json() offer_dict = {} for entry in response_city: item = entry['item_id'] value = entry['sell_price_min'] quality = entry['quality'] name = item + "#" + str(quality) if value: offer_dict[name] = [value, 0] for entry in response_blackmarket: item = entry['item_id'] value = entry['buy_price_max'] time = entry['sell_price_min_date'] a = datetime.now() - datetime.strptime(time, '%Y-%m-%dT%H:%M:%S') qualities = [x for x in range(entry['quality'], 6)] items_to_purchase = [item+"#"+str(x) for x in qualities] city_values = [] for item_key in items_to_purchase: if item_key in offer_dict.keys(): item_city_value = offer_dict[item_key][0] city_values.append(item_city_value) if len(city_values) > 0: offer_dict[items_to_purchase[0]] = [min(city_values), value, a] full_list = sorted(offer_dict.items(), key=lambda x:(x[0], -x[1][1]+x[1][0], time)) profit_list = [] for item in full_list: name = item[0] values_pair = item[1] time = values_pair[2] profit = round(values_pair[1]*(1-tax) - values_pair[0]) if profit > 0 and (1 - values_pair[0] / profit) < 0.85: profit_list.append([name, values_pair, profit, time]) profit_list.sort(key=lambda x:(x[2])) i = 0 for item in profit_list[::-1]: _id, _quality = item[0].split('#') enchant = item[0][-3] if "@" in item[0] else '0' tier = _id[1] quality = quality_list[int(_quality) -1] if _id in id_to_name.keys(): translated_name = id_to_name[_id] else: tier = '' enchant = '' translated_name = _id name = f'{tier}.{enchant} {translated_name}, {quality}' item_id = item[0].split('#')[0] price = item[1][0] blackmarket = item[1][1] profit = item[2] time = item [3] self.add_item(item_id, name, price, blackmarket, profit) i += 1
class View(): """This calls contains all the tkinter specific code""" def __init__(self, control, master): """View constructor""" self.control = control # Link back to talk to controller self.master = master master.wm_state('zoomed') # Full screen. Might not work on Mac self.frame = Frame(master) self.create_menus() self.create_context_menus() self.create_toolbar() self.frame.pack(fill=BOTH, expand=YES) self.frame.focus_set() self.create_events() def create_menus(self): """creates the menus""" # main menu menubar = Menu(self.master) # file menus filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="New", accelerator="^N", command=self.control.cmd_new) filemenu.add_command(label="Open", accelerator="^O", command=self.control.cmd_open) filemenu.add_command(label="Save", accelerator="^S", command=self.control.cmd_save) filemenu.add_command(label="Save as", command=self.control.cmd_save_as) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.control.cmd_exit) menubar.add_cascade(label="File", menu=filemenu) # edit menus editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label="Undo", accelerator="^Z", command=self.control.cmd_null) editmenu.add_command(label="Redo", accelerator="^C", command=self.control.cmd_null) editmenu.add_separator() editmenu.add_command(label="Cut", accelerator="^X", command=self.control.cmd_null) editmenu.add_command(label="Copy", accelerator="^C", command=self.control.cmd_null) editmenu.add_command(label="Paste", accelerator="^V" , command=self.control.cmd_null) editmenu.add_separator() editmenu.add_command(label="Delete", command = self.control.cmd_null) editmenu.add_separator() editmenu.add_command(label="Select all", command = self.control.cmd_null) menubar.add_cascade(label="Edit", menu=editmenu) # drawing menus drawingmenu = Menu(menubar, tearoff=0) drawingmenu.add_command(label="Select", command=self.control.cmd_null) drawingmenu.add_command(label="Line", command=self.control.cmd_line) drawingmenu.add_command(label="Rectangle", command=self.control.cmd_rectangle) drawingmenu.add_command(label="Circle", command=self.control.cmd_circle) drawingmenu.add_command(label="Group", command=self.control.cmd_null) drawingmenu.add_command(label="Instance", command=self.control.cmd_null) menubar.add_cascade(label="Drawing", menu=drawingmenu) # toolbar menus toolbarmenu = Menu(menubar, tearoff=0) toolbarmenu.add_checkbutton(label='Tools', command=self.control.cmd_tools) menubar.add_cascade(label="Toolbar", menu=toolbarmenu) # help menus helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label="About", command = self.control.cmd_null) menubar.add_cascade(label="Help", menu = helpmenu) self.master.config(menu=menubar) # lock in menubar def create_context_menus(self): """Creates the connects menus, i.e. for right click""" self.context = Menu(self.master, tearoff=0) self.context.add_command(label="Dirty", command=self.control.cmd_dirty) self.context.add_command(label="Clean", command=self.control.cmd_clean) def create_toolbar(self): """Creates toolbar, hopefully floating dockable but not yet""" self.toolbar = Frame(self.master, bd=1, relief=RAISED) self.img = Image.open("exit.png") eimg = ImageTk.PhotoImage(self.img) exitButton = Button(self.toolbar, image=eimg, bd=1, relief=RAISED, command=self.control.cmd_exit) exitButton.image = eimg exitButton.pack(side=TOP, padx=2, pady=2) anotherButton = Button(self.toolbar, image=eimg, bd=1, relief=RAISED, command=self.control.cmd_null) anotherButton.image = eimg anotherButton.pack(side=TOP, padx=2, pady=2) anotherButton = Button(self.toolbar, image=eimg, bd=1, relief=RAISED, command=self.control.cmd_null) anotherButton.image = eimg anotherButton.pack(side=TOP, padx=2, pady=2) self.toolbar.pack(side=LEFT, fill=Y) def create_events(self): """Binds keyboard events to handlers""" self.frame.bind("<Control-o>", self.key_open) self.frame.bind("<Control-s>", self.key_save) self.frame.bind("<Button-1>", self.left_click) self.frame.bind("<Button-3>", self.right_click) self.frame.bind("<Configure>", self.on_resize) # Window closing event self.master.protocol('WM_DELETE_WINDOW', self.control.cmd_exit) def on_resize(self,e): """Called when window changes size""" pass @staticmethod def question_box(title, text): """Just a wrapped for tkinter so command calls can be tkinter independent""" return messagebox.askquestion(title, text) == "yes" @staticmethod def warning_box(title, text): """Just a wrapped for tkinter so command calls can be tkinter independent""" messagebox.showwarning(title, text) @staticmethod def info_box(title, text): """Just a wrapped for tkinter so command calls can be tkinter independent""" messagebox.showinfo(title, text) @staticmethod def open_file_dialog(): """Just a wrapped for tkinter so command calls can be tkinter independent""" return filedialog.askopenfilename(filetypes=(("Gcode","*.gcode"), ("All files","*.*"))) @staticmethod def save_file_dialog(initial_file): """Just a wrapped for tkinter so command calls can be tkinter independent""" return filedialog.asksaveasfile(mode='w', initialfile=initial_file, filetypes=(("Gcode","*.gcode"),("All files","*.*")), defaultextension=".gcode") def key_open(self, e): self.control.cmd_open() def key_save(self, e): self.control.cmd_open() def left_click(self, e): self.control.cmd_left_click(e.x_root, e.y_root) def right_click(self, e): self.control.cmd_right_click(e.x_root, e.y_root) def show_context_menu(self, x, y): self.context.tk_popup(x, y, 0) def show_toolbar(self): # self.frame = Frame(self.master) self.create_menus() self.create_context_menus() self.create_toolbar() self.create_toolbar() self.create_toolbar() self.frame.pack(fill=BOTH, expand=YES) self.frame.focus_set() self.create_events() def hide_toolbar(self): self.toolbar.pack_forget()
class Tile(object): __spawn_anim_duration_ms = 100 __anim_update_interval_ms = 10 __move_speed = 5 def __init__(self, size, value, config: GameConfig): """ Create a tile :param size: tile size (squared width and height) in px :param value: tile value :param fg: tile foreground hex color string :param bg: tile background hex color string :param font: tile label font Tuple (face, size) """ self.config = config self.size = size self.value = value self.fg, self.bg = config.get_tile_colors(value) self.font = config.get_label_font() self.__futures = [] self.__current_move_future = None self.__current_position = None self.__merge_event = None self.__destination = None self.__tile = None self.__label = None def __update_value(self, new_value): """ Update tile value to new one :param new_value: new value to set :return: None """ self.__change_value(new_value) self.__update_label() def spawn_at(self, root, x, y): """ Spawn the tile at specified position :param root: tile master widget :param x: x :param y: y :return: None """ self.__tile = Frame(root, width=1, height=1) self.__current_position = (x, y) self.__tile.place(x=x, y=y, anchor=CENTER) self.__tile.pack_propagate(False) self.__update_label() self.__play_spawn_anim() pass def move_to(self, x=None, y=None): """ Move the tile to specified position :param x: x :param y: y :return: None """ if not self.__current_position: # do nothing if not been placed on board return if self.__current_move_future and not self.__current_move_future.done(): self.__current_move_future.cancel() self.__current_position = self.__destination self.__tile.place(x=self.__current_position[0], y=self.__current_position[1], anchor=CENTER) self.__proceed_with_merge() if not x: x = self.__current_position[0] if not y: y = self.__current_position[1] dest = (x, y) if dest == self.__current_position: return self.__destination = dest self.__play_move_anim() def move_and_merge(self, merge_callback, new_value, x=None, y=None): self.__merge_event = (merge_callback, new_value) self.move_to(x, y) def __proceed_with_merge(self): if not self.__merge_event: return callback, new_value = self.__merge_event self.__merge_event = None if callback: callback() self.__update_value(new_value) def __change_value(self, new_value): self.value = new_value self.fg, self.bg = self.config.get_tile_colors(self.value) def __update_label(self): if self.__label: self.__label.config(text=self.value, bg=self.bg, fg=self.fg) return self.__label = Label(self.__tile, text=self.value, bg=self.bg, fg=self.fg, justify=CENTER, font=self.font) self.__label.pack(fill=BOTH, expand=True) @staticmethod def __get_direction(start, end): diff = end - start if not diff: return 0 return diff / abs(diff) def __play_move_anim(self): destination_x, destination_y = self.__destination current_x, current_y = self.__current_position x_dir = self.__get_direction(current_x, destination_x) y_dir = self.__get_direction(current_y, destination_y) async def anim(): x, y = self.__current_position new_x = x + x_dir * Tile.__move_speed * Tile.__anim_update_interval_ms new_y = y + y_dir * Tile.__move_speed * Tile.__anim_update_interval_ms new_x = min(destination_x, new_x) if x_dir > 0 else max(destination_x, new_x) new_y = min(destination_y, new_y) if y_dir > 0 else max(destination_y, new_y) self.__current_position = (new_x, new_y) self.__tile.place(x=new_x, y=new_y, anchor=CENTER) if (new_x, new_y) != self.__destination: await asyncio.sleep(Tile.__anim_update_interval_ms / 1000) # update every 10ms await anim() else: self.__proceed_with_merge() def start_anim(): f = asyncio.ensure_future(anim()) self.__current_move_future = f f.add_done_callback(self.__remove_finished_futures) self.__futures.append(f) io_loop = asyncio.get_event_loop() io_loop.call_soon_threadsafe(start_anim) def __play_spawn_anim(self): step = (self.size - 1) / Tile.__spawn_anim_duration_ms async def anim(current_size): new_size = min(self.size, int(step * Tile.__anim_update_interval_ms + current_size)) self.__tile.config(width=new_size, height=new_size) if new_size < self.size: await asyncio.sleep(Tile.__anim_update_interval_ms / 1000) # update every 10ms await anim(new_size) def start_anim(): f = asyncio.ensure_future(anim(1)) f.add_done_callback(self.__remove_finished_futures) self.__futures.append(f) io_loop = asyncio.get_event_loop() io_loop.call_soon_threadsafe(start_anim) def __remove_finished_futures(self, f): self.__futures.remove(f) def destroy(self): for f in self.__futures: f.cancel() # cancel any playing animations on destroy if self.__tile: self.__tile.pack_forget() self.__tile.destroy()
class TelaGrafico(): #================================================================== def __init__(self, janela, jAnterior, px, err_x, py, err_y): style.use("bmh") self.jAnterior = jAnterior self.janela = janela.geometry("500x620+200+0") tam = 8 #=Frame feito para conter a imagem do plot======================== self.frm_graphic = Frame(janela, bd=10, height=300, width=500, bg="azure2") self.frm_buttons = Frame(janela, bd=10, bg="azure2") self.btn_return = Button(self.frm_buttons, text="Voltar", command=self.voltar, bg="LightSkyBlue4", width=tam) self.btn_plot = Button(self.frm_buttons, text="Salvar", command=self.salvar_imagem, bg="LightSkyBlue4", width=tam) #=====Botoes de ajuste===== self.btn_linear = Button(self.frm_buttons, text="Linear", bg="LightSkyBlue4", width=tam) self.btn_linear["command"] = partial(self.curve_plot, px, err_x, py, err_y, Fit_linear, "Linear") self.btn_expo = Button(self.frm_buttons, text="Exponencial", bg="LightSkyBlue4", width=tam) self.btn_expo["command"] = partial(self.curve_plot, px, err_x, py, err_y, Fit_exponencial, "Exponencial") self.btn_quadra = Button(self.frm_buttons, text="Quadrática", bg="LightSkyBlue4", width=tam) self.btn_quadra["command"] = partial(self.curve_plot, px, err_x, py, err_y, Fit_quadrada, "Quadrática") self.btn_cube = Button(self.frm_buttons, text="Cúbica", bg="LightSkyBlue4", width=tam) self.btn_cube["command"] = partial(self.curve_plot, px, err_x, py, err_y, Fit_cubica, "Cúbica") self.btn_racio = Button(self.frm_buttons, text="Racional", bg="LightSkyBlue4", width=tam) self.btn_racio["command"] = partial(self.curve_plot, px, err_x, py, err_y, Fit_racional, "Racional") #========================== self.frm_graphic.pack(side=TOP) self.frm_buttons.pack(side=BOTTOM) self.btn_linear.grid(row=3, column=0) self.btn_expo.grid(row=3, column=1) self.btn_quadra.grid(row=3, column=2) self.btn_cube.grid(row=3, column=3) self.btn_racio.grid(row=3, column=4) self.btn_return.grid(row=5, column=0) self.btn_plot.grid(row=5, column=1) #====================================================== #=Código para desenhar o gráfico no frame da janela # #=Primeira linha cria a figura onde o plot será feito self.fig = Figure(figsize=(7, 5)) #=Não sei bem o que o add_subplot faz ainda, mas parece que é algum tipo #=de "preparação" pro plot ser feito em uma variável self.grafico = self.fig.add_subplot(111) #=função simples para plotar as duas variáveis. "bo" é o tipo de "linha" self.grafico.plot(px, py, "bo") self.grafico.set_xlabel('x', labelpad=5) self.grafico.set_ylabel('y', labelpad=5) #=Um "canvas" (tela de pintura) precisa ser feito no tkinter para desenhar o gráfico. #=aparentemente, esse método FigureCanvastkAgg cria essa "tela" e assoscia ela ao #=tkinter. Ela passa com parâmetro a figura que será desenhada e em qual janela, #=frame, etc ela será desenhada. self.canvas = FigureCanvasTkAgg(self.fig, master=self.frm_graphic) #=aparentemente é o que posiciona a imagem no frame, assim como fazemos #=com os widgets na janela. self.canvas.get_tk_widget().pack() #=faz o desenho do plot (seria interessante testar o código sem isso e ver se # simplesmente não vai aparecer o plot) self.canvas.draw() #================================================================== def limparJanela(self): self.btn_return.grid_forget() self.btn_plot.grid_forget() self.btn_linear.grid_forget() self.btn_expo.grid_forget() self.btn_quadra.grid_forget() self.btn_cube.grid_forget() self.btn_racio.grid_forget() self.frm_buttons.pack_forget() self.frm_graphic.pack_forget() #================================================================== def voltar(self): self.limparJanela() self.jAnterior.redesenhar() #================================================================== def limpar_grafico(self): self.canvas.get_tk_widget().pack_forget() #================================================================== def curve_plot(self, px, err_x, py, err_y, Funcao, f_nome): funct = Funcao(px, py, err_x, err_y) popt, pcov, qui_quadrado = funct.gerar_qui_quadrado() x_teste = [] d0 = px.min() while d0 < px.max(): x_teste.append(d0) d0 += 1 x_teste.append(px.max()) x_teste = array(x_teste) self.limpar_grafico() def gerar_legenda(): legenda = "" for coef, err_coef, letra in zip(popt, pcov, ['A', 'B', 'C', 'D']): legenda += letra + f" = {coef:.2f} +/- {err_coef:.2f}\n" legenda += r'$\chi^2$/ndof =' legenda += f"{qui_quadrado:.2f}" return legenda self.fig = Figure(figsize=(7, 5)) self.grafico = self.fig.add_subplot(111) self.grafico.plot(x_teste, funct.funcao(popt, x_teste), "k", label=gerar_legenda()) self.grafico.errorbar(px, py, yerr=array(err_y), fmt='o') self.grafico.legend(fontsize='x-small') self.grafico.set_xlabel('x', labelpad=5) self.grafico.set_ylabel('y', labelpad=5) self.canvas = FigureCanvasTkAgg(self.fig, master=self.frm_graphic) self.canvas.get_tk_widget().pack() self.canvas.draw() self.resultados(popt, pcov, qui_quadrado, f_nome) #========================================================================== def salvar_imagem(self): filename = filedialog.asksaveasfilename() self.fig.savefig(filename) #========================================================================== def resultados(self, popt, pcov, qui_quadrado, f_nome): top_res = Toplevel(bd=10) top_res.resizable(False, False) top_res.title("Resultados: " + f_nome) top_res.configure(background="azure2") txt_a_value = Entry(top_res) txt_a_value.insert(0, popt[0]) txt_a_value.config(state='readonly') Label(top_res, text="A: ", bg="azure2").grid(row=0, column=0) txt_a_value.grid(row=0, column=1) txt_a_error = Entry(top_res) txt_a_error.insert(0, pcov[0]) txt_a_error.config(state='readonly') Label(top_res, text="+/-", bg="azure2").grid(row=0, column=2) txt_a_error.grid(row=0, column=3) txt_b_value = Entry(top_res) txt_b_value.insert(0, popt[1]) txt_b_value.config(state='readonly') Label(top_res, text="B: ", bg="azure2").grid(row=1, column=0) txt_b_value.grid(row=1, column=1) txt_b_error = Entry(top_res) txt_b_error.insert(0, pcov[1]) txt_b_error.config(state='readonly') Label(top_res, text="+/-", bg="azure2").grid(row=1, column=2) txt_b_error.grid(row=1, column=3) if (len(popt) > 2): txt_c_value = Entry(top_res) txt_c_value.insert(0, popt[2]) txt_c_value.config(state='readonly') Label(top_res, text="C: ", bg="azure2").grid(row=2, column=0) txt_c_value.grid(row=2, column=1) txt_c_error = Entry(top_res) txt_c_error.insert(0, pcov[2]) txt_c_error.config(state='readonly') Label(top_res, text="+/-", bg="azure2").grid(row=2, column=2) txt_c_error.grid(row=2, column=3) if (len(popt) > 3): txt_d_value = Entry(top_res) txt_d_value.insert(0, popt[3]) txt_d_value.config(state='readonly') Label(top_res, text="D: ", bg="azure2").grid(row=3, column=0) txt_d_value.grid(row=3, column=1) txt_d_error = Entry(top_res) txt_d_error.insert(0, pcov[3]) txt_d_error.config(state='readonly') Label(top_res, text="+/-", bg="azure2").grid(row=3, column=2) txt_d_error.grid(row=3, column=3) txt_q_entry = Entry(top_res) txt_q_entry.insert(0, round(qui_quadrado, 4)) txt_q_entry.config(state='readonly') Label(top_res, text="x²/ndof: ", bg="azure2").grid(row=4, column=0) txt_q_entry.grid(row=4, column=1)
class QuantMonitor(object): # 背景色 bgColor = rgb_to_hex(245, 245, 245) bgColorW = "white" def __init__(self, frame, control, language): self.parentFrame = frame self._controller = control self._logger = self._controller.get_logger() self.language = language # Monitor不同标签的背景色 self.rColor = self.bgColorW self.lColor = self.bgColor self.sColor = self.bgColor self.eColor = self.bgColor self.createButtonFrame() # 执行列表、监控日志、信号记录、错误 self.executeList = Frame(self.parentFrame) self.monitorLog = Frame(self.parentFrame) self.sigRecord = Frame(self.parentFrame) self.errRecord = Frame(self.parentFrame) self.executeList.pack(side=TOP, fill=BOTH, expand=YES) self.monText = None self.sigText = None self.errText = None def createButtonFrame(self): btnFrame = Frame(self.parentFrame, height=30, bg=self.bgColor) btnFrame.pack_propagate(0) btnFrame.pack(side=TOP, fill=X) # 利用frame做出button的黑色边框 # f1 = Frame(btnFrame, highlightbackground="black", highlightthickness=1, bd=0) # f1.pack(side=LEFT) self.runBtn = Button(btnFrame, text="策略运行", relief=FLAT, padx=14, pady=1.5, bg=self.rColor, bd=0, highlightthickness=1, command=self.toMonFrame) self.logBtn = Button(btnFrame, text="运行日志", relief=FLAT, padx=14, pady=1.5, bg=self.lColor, bd=0, highlightthickness=1, command=self.toLogFrame) self.sigBtn = Button(btnFrame, text="信号记录", relief=FLAT, padx=14, pady=1.5, bg=self.sColor, bd=0, highlightthickness=1, command=self.toSigFrame) self.errBtn = Button(btnFrame, text="错误信息", relief=FLAT, padx=14, pady=1.5, bg=self.eColor, bd=0, highlightthickness=1, command=self.toErrFrame) self.runBtn.pack(side=LEFT, expand=NO) self.logBtn.pack(side=LEFT, expand=NO) self.sigBtn.pack(side=LEFT, expand=NO) self.errBtn.pack(side=LEFT, expand=NO) for btn in (self.runBtn, self.logBtn, self.sigBtn, self.errBtn): btn.bind("<Enter>", self.handlerAdaptor(self.onEnter, button=btn)) btn.bind("<Leave>", self.handlerAdaptor(self.onLeave, button=btn)) def createMonitor(self): # monitorRightBar = Scrollbar(self.monitorLog) # monitorRightBar.pack(side=RIGHT, fill=Y), yscrollcommand=monitorRightBar.set self.monText = MonitorText(self.monitorLog, height=20, bd=0) self.monText.createScrollbar() self.monText.pack(fill=BOTH, expand=YES) def createSignal(self): self.sigText = SignalText(self.sigRecord, height=20, bd=0) self.sigText.createScrollbar() self.sigText.pack(fill=BOTH, expand=YES) def createExecute(self): headList = [ "编号", "策略名称", "基准合约", "频率", "运行状态", "实盘运行", "初始资金", "可用资金", "最大回撤", "累计收益", "胜率" ] widthList = [5, 50, 50, 5, 10, 5, 20, 10, 20, 20, 5] self.executeBar = ttk.Scrollbar(self.executeList, orient="vertical") self.executeBar.pack(side=RIGHT, fill=Y) self.executeListTree = ttk.Treeview(self.executeList, show="headings", height=28, columns=tuple(headList), yscrollcommand=self.executeBar.set, style="Filter.Treeview") self.executeBar.config(command=self.executeListTree.yview) self.executeListTree.pack(fill=BOTH, expand=YES) self.executeListTree.bind("<Button-3>", self.createMenu) for key, w in zip(headList, widthList): self.executeListTree.column(key, width=w, anchor=CENTER) self.executeListTree.heading(key, text=key) def createMenu(self, event): """创建运行策略右键菜单""" RunMenu(self._controller, self.executeListTree).popupmenu(event) def _formatMonitorInfo(self, dataDict): """ 格式化监控需要的信息 :param dataDict: 策略的所有信息 :return: 需要展示的信息 """ try: Id = dataDict['StrategyId'] StName = dataDict['StrategyName'] BenchCon = dataDict['Config']['Contract'][0] kLineType = FrequencyDict[dataDict['Config']['Sample'] ['KLineType']] kLineSlice = dataDict['Config']['Sample']['KLineSlice'] Frequency = str(kLineSlice) + kLineType RunType = "是" if dataDict['Config']['RunMode']['Actual'][ 'SendOrder2Actual'] else "否" Status = StrategyStatus[dataDict["StrategyState"]] InitFund = dataDict['Config']['Money']['InitFunds'] if 'RunningData' in dataDict: # Available = "{:.2f}".format(dataDict['RunningData']['Fund'][-1]['Available']) Available = "{:.2f}".format( dataDict['RunningData']['Available']) # 年化单利收益率 # AnnualizedReturns = "{:.2f}".format(dataDict['RunningData']['Detail']['AnnualizedSimple']) MaxRetrace = "{:.2f}".format( (dataDict['RunningData']['MaxRetrace'])) TotalProfit = "{:.2f}".format( dataDict['RunningData']['NetProfit']) WinRate = "{:.2f}".format(dataDict['RunningData']['WinRate']) else: Available = InitFund # AnnualizedReturns = 0 MaxRetrace = 0 TotalProfit = 0 WinRate = 0 except KeyError: traceback.print_exc() return values = [ Id, StName, BenchCon, Frequency, Status, RunType, InitFund, Available, MaxRetrace, TotalProfit, WinRate ] return values def updateSingleExecute(self, dataDict): values = self._formatMonitorInfo(dataDict) if not values: return strategyId = dataDict["StrategyId"] try: if self.executeListTree.exists(strategyId): self.updateStatus(strategyId, dataDict) return except Exception as e: self._logger.warn("updateSingleExecute exception") self.executeListTree.insert("", END, iid=strategyId, values=tuple(values), tag=0) def createErr(self): # 错误信息展示 self.errText = ErrorText(self.errRecord, height=20, bd=0) self.errText.createScrollbar() self.errText.pack(fill=BOTH, expand=YES) def updateRun(self): pass def updateLogText(self): guiQueue = self._controller.get_logger().getGuiQ() try: data = guiQueue.get_nowait() except: return else: self.monText.setText(data) def updateSigText(self): sigQueue = self._controller.get_logger().getSigQ() try: sigData = sigQueue.get_nowait() except: return else: # self.toSigFrame() self.sigText.setText(sigData) def updateErrText(self): errQueue = self._controller.get_logger().getErrQ() try: errData = errQueue.get_nowait() except: return else: self.toErrFrame() self.errText.setText(errData) def toMonFrame(self): self.runBtn.config(bg="white") self.rColor = self.runBtn['bg'] self.lColor = self.bgColor self.sColor = self.bgColor self.eColor = self.bgColor self.errBtn.config(bg=self.rColor) self.sigBtn.config(bg=self.sColor) self.logBtn.config(bg=self.lColor) self.monitorLog.pack_forget() self.sigRecord.pack_forget() self.errRecord.pack_forget() self.executeList.pack(side=TOP, fill=BOTH, expand=YES) def toLogFrame(self): self.logBtn.config(bg="white") self.lColor = self.logBtn['bg'] self.rColor = self.bgColor self.sColor = self.bgColor self.eColor = self.bgColor self.runBtn.config(bg=self.rColor) self.sigBtn.config(bg=self.sColor) self.errBtn.config(bg=self.eColor) self.sigRecord.pack_forget() self.executeList.pack_forget() self.errRecord.pack_forget() self.monitorLog.pack(side=TOP, fill=BOTH, expand=YES) def toSigFrame(self): self.sigBtn.config(bg="white") self.sColor = self.sigBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.eColor = self.bgColor self.runBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.errBtn.config(bg=self.eColor) self.monitorLog.pack_forget() self.executeList.pack_forget() self.errRecord.pack_forget() self.sigRecord.pack(side=TOP, fill=BOTH, expand=YES) def toErrFrame(self): self.errBtn.config(bg="white") self.eColor = self.errBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.sColor = self.bgColor self.runBtn.config(bg=self.rColor) self.sigBtn.config(bg=self.sColor) self.logBtn.config(bg=self.lColor) self.parentFrame.update() self.monitorLog.pack_forget() self.executeList.pack_forget() self.sigRecord.pack_forget() self.errRecord.pack(side=TOP, fill=BOTH, expand=YES) def handlerAdaptor(self, fun, **kwargs): return lambda event, fun=fun, kwargs=kwargs: fun(event, **kwargs) def onEnter(self, event, button): if button == self.runBtn: button.config(bg='white') self.logBtn.config(bg=self.bgColor) self.sigBtn.config(bg=self.bgColor) self.errBtn.config(bg=self.bgColor) elif button == self.logBtn: button.config(bg='white') self.runBtn.config(bg=self.bgColor) self.sigBtn.config(bg=self.bgColor) self.errBtn.config(bg=self.bgColor) elif button == self.sigBtn: button.config(bg='white') self.runBtn.config(bg=self.bgColor) self.logBtn.config(bg=self.bgColor) self.errBtn.config(bg=self.bgColor) else: button.config(bg='white') self.runBtn.config(bg=self.bgColor) self.logBtn.config(bg=self.bgColor) self.sigBtn.config(bg=self.bgColor) def onLeave(self, event, button): button.config(bg=rgb_to_hex(227, 230, 233)) if button == self.runBtn: button['bg'] = self.rColor self.logBtn['bg'] = self.lColor self.sigBtn['bg'] = self.sColor self.errBtn['bg'] = self.eColor elif button == self.logBtn: button['bg'] = self.lColor self.runBtn['bg'] = self.rColor self.sigBtn['bg'] = self.sColor self.errBtn['bg'] = self.eColor elif button == self.sigBtn: button['bg'] = self.sColor self.runBtn['bg'] = self.rColor self.logBtn['bg'] = self.lColor self.errBtn['bg'] = self.eColor else: button['bg'] = self.eColor self.runBtn['bg'] = self.rColor self.logBtn['bg'] = self.lColor self.sigBtn['bg'] = self.sColor def deleteStrategy(self, strategyId): """删除策略""" self.executeListTree.delete(strategyId) def updateStatus(self, strategyId, dataDict): """更新策略ID对应的策略状态""" values = self._formatMonitorInfo(dataDict) self.executeListTree.item(strategyId, values=values)
class SongGUI: def __init__(self, root): self.root = root self.root.title('Find my tune') self.root.geometry() self.root.minsize(800, 800) self.searchname = tkinter.StringVar() # creating help button help_button_img = PhotoImage(file='images/help_button.png') help_button_img = help_button_img.subsample(2) help_img_label = Label(image=help_button_img) help_img_label.image = help_button_img self.help_button = Button(self.root, image=help_button_img, command=self.helpFrame, border=0) self.help_button.pack(side=TOP, anchor=NE, padx=10, pady=10) # creating input frame self.input_frame = Frame(self.root) self.input_frame.pack() # creating heading heading = Label(self.input_frame, text="Find My Tune", font=("Helvetica", 30), fg="black") heading.pack(pady=20, side=TOP) # creating search bar self.search_box_input = Entry(self.input_frame, font=("Helvetica", 20), textvariable=self.searchname) self.search_box_input.pack() # creating search button search_button_img = PhotoImage(file='images/search_button.png') search_button_img = search_button_img.subsample(2) search_img_label = Label(image=search_button_img) search_img_label.image = search_button_img self.search_button = Button(self.input_frame, image=search_button_img, border=0, command=self.searchSong) self.search_button.pack(pady=10, side=LEFT) # creating refresh button refresh_button_img = PhotoImage(file='images/refresh_button.png') refresh_button_img = refresh_button_img.subsample(2) refresh_img_label = Label(image=refresh_button_img) refresh_img_label.image = refresh_button_img self.refresh_button = Button(self.input_frame, image=refresh_button_img, fg='green', command=self.refreshFrame, border=0) self.refresh_button.pack(pady=10, side=RIGHT) def helpFrame(self): '''shows help Window in new frame''' self.help_button['state'] = DISABLED # Toplevel object which will be treated as a new window self.help_window = Toplevel(self.root) # sets the title of the Toplevel widget self.help_window.title("Help Window") # sets the geometry of toplevel self.help_window.geometry("550x800") # making help_window unresizable self.help_window.resizable(0, 0) # reading content from help_window.txt info_file = open("help_window.txt") lines = info_file.readlines() heading = Label(self.help_window, font=("Helvetica 20 underline"), text="HELP WINDOW") heading.pack(side=TOP, padx=10, pady=10) # code, to show content in help_window Label(self.help_window, wraplength=500, justify="left", font=("", 12), text=lines[0]).pack(side=TOP, pady=10, padx=5) Label(self.help_window, font=("Helvetica 16 underline bold"), text="INSTRUCTIONS").pack(anchor=W, padx=10, pady=10) for i in range(1, 9): Label(self.help_window, wraplength=500, justify="left", font=("", 12), text=str(i) + ". " + lines[i]).pack(anchor=W, pady=2, padx=10) Label(self.help_window, font=("Helvetica 16 underline"), text="NOTE").pack(anchor=W, padx=10, pady=10) for i in range(8, 11): Label(self.help_window, wraplength=500, justify="left", font=("", 12), text=str(i - 7) + ". " + lines[i]).pack(anchor=W, pady=2, padx=10) self.help_window.protocol("WM_DELETE_WINDOW", self.close_window) def close_window(self): '''function which closes the help_window''' self.help_window.destroy() self.help_button['state'] = NORMAL def searchSong(self): ''''function reads the search_input and searchs for the song''' self.songname = self.searchname.get() self.searchname.set('') # if the search box is not empty if (self.songname): self.songlist = findMySong(self.songname) self.search_button['state'] = DISABLED self.searchname.set('') self.result_frame = Frame(self.root) self.result_frame.pack() self.results = ttk.Treeview(self.result_frame) # if search is not empty if (self.songlist): # creates four cols, 1 phantom columns self.results['columns'] = ('S.NO', 'Name', 'Duration') style = ttk.Style() style.configure("Treeview", rowheight=18, columns=30000) self.results.column("#0", stretch=YES, width=0, minwidth=0) self.results.column("S.NO", stretch=YES, anchor=W, width=40) self.results.column("Name", anchor=W, stretch=YES, width=600) self.results.column("Duration", stretch=YES, anchor=W, width=80) # Create Headings self.results.heading("S.NO", text="S.NO", anchor=W) self.results.heading("Name", text="Name", anchor=CENTER) self.results.heading("Duration", text="Duration", anchor=W) self.results.pack(pady=10, expand=1, fill=BOTH) for i in range(len(self.songlist)): self.results.insert(parent='', index='end', iid=i, text='', values=(str(i + 1), self.songlist[i]['title'], self.songlist[i]['duration'])) self.down_button = Button(self.result_frame, text='DOWNLOAD', fg='white', bg='green', command=self.downloadSong) self.down_button.pack(padx=10, side=TOP) else: tkinter.messagebox.showerror( 'No Song Foumd', "Could'nt find your song, please try again") self.search_button['state'] = NORMAL else: tkinter.messagebox.showerror('Search box Empty', "Please enter song name") self.search_button['state'] = NORMAL def downloadSong(self): '''Function which download the song''' self.down_button['state'] = DISABLED songNumber = self.results.focus() # if option is selected if (songNumber): songNumber = int(songNumber) downloadMySong(self.songlist[songNumber]['download-link']) filename = [f for f in os.listdir() if f.endswith('.mp3')] if (filename): # rename file and save in download folder os.rename(filename[0], 'downloads/' + filename[0][:-14] + ".mp3") tkinter.messagebox.showinfo('Song Downloaded Successfully', "Your song is downloaded.") else: tkinter.messagebox.showerror( 'Song Not Downloaded', "Could'nt download your song, please try again later.") filename = [ f for f in os.listdir() if f.endswith('.crdownload') ] if (filename): for file in filename: os.remove(file) else: tkinter.messagebox.showerror( 'Song Not Selected', "Please choose one item from list, then press download button") self.down_button['state'] = NORMAL def refreshFrame(self): '''clears the search window''' self.search_button['state'] = NORMAL self.searchname.set('') try: self.result_frame.pack_forget() except AttributeError: tkinter.messagebox.showinfo('Already Refreshed', "window already refreshed")
class LogicAnalyzer : def __init__(self,master) : self.master = master self.BLOCK_LEN = 2048 * 32 self.RxTimerState = 1 self.deviceIndex = -1 self.dev = None self.rx_buffer = bytearray() self.timeout = 0; self.x = np.arange(0, 30, 1) self.axis = np.arange(25, 100, 1) self.z = [0] * 75 self.index_max = 0 self.results = [] self.index = [] for i in range(0,16): tempList = [] self.results.append(tempList) self.startPosition = 0 self.sampPitch = 1 self.sampOnScreen = 30 self.finishPosition = 0 self.channelActiveMask = 0 self.coreFrq = 300000000 #300MHz self.coreFrqPeriod = 1000000000/self.coreFrq self.sampFrq = 300000000.0 self.AARate = 0; self.BBSamp = 0; self.HHTrigPos = 0; self.EEVolt = 0; self.decoder_instances = [] self.dec_instance_state = [] for i in range(0,8): inst_temp = i2c(self.master) self.decoder_instances.append(inst_temp) self.dec_instance_state.append("_") self.channel_count = 0 self.channel_decode = [0]*16 self.decode_count = 0 self.decode_decode = [0]*8 self.top1 = Frame(self.master, height = 500, width = 260, borderwidth=2,highlightbackground="gray" , highlightthickness=1) self.top1.pack(side="left", fill="both") self.top2 = Frame(self.master, height = 500, width = 500, borderwidth=2,highlightbackground="gray" , highlightthickness=1) self.top2.pack(side="right", fill="both") self.top_slider = Frame(self.top2, height = 5, width = 500) self.top_slider.pack(side="top", fill="x") self.plot_frame = Frame(self.top2) self.plot_frame.pack(side="top", fill="both",expand = 1) self.right_slider = Frame(self.plot_frame) self.right_slider.pack(side="right", fill="y") self.AxisFrame = Frame(self.plot_frame, height = 5, width = 500) self.AxisFrame.pack(side="top") self.RSB1 = Button(self.right_slider, text = "+",height=1, width=4, command = self.zoomSliderP) self.RSB1.pack(side="top") self.w1 = Scale(self.right_slider, from_=1000, to=0,showvalue = 0,command = self.calcPosition)#command = self.calcPosition self.w1.set(0) self.w1.pack(side="top", fill="y",expand = 1) self.RSB2 = Button(self.right_slider, text = "-",height=1, width=4, command = self.zoomSliderM) self.RSB2.pack(side="top") self.w2 = Scale(self.top_slider, from_=0, to=100000, orient=HORIZONTAL, showvalue = 0,command = self.calcPosition) #command = self.calcPosition self.w2.set(0) self.SB1 = Button(self.top_slider, text = "<<<",height=1, width=3, command = self.shiftSliderMM) self.SB1.pack(side="left") self.SB2 = Button(self.top_slider, text = "<",height=1, width=3, command = self.shiftSliderM) self.SB2.pack(side="left") self.w2.pack(side="left", fill="both",expand=1) self.SB3 = Button(self.top_slider, text = ">>>",height=1, width=3, command = self.shiftSliderPP) self.SB3.pack(side="right") self.SB4 = Button(self.top_slider, text = ">",height=1, width=3, command = self.shiftSliderP) self.SB4.pack(side="right") self.AxisFig = plt.Figure(figsize=(25,2), dpi=100) self.AxisFig.set_figheight(0.25) self.AxisFig.subplots_adjust(left=-0.05, right=1.05, top=2, bottom=1) self.af = self.AxisFig.add_subplot(111) self.AxisFig.patch.set_facecolor('whitesmoke') self.af.axes.get_yaxis().set_visible(False) self.af.step(self.axis, self.z, where='post', label='post') self.af.set_frame_on(False) self.axVar = StringVar() self.axLab = Label(self.AxisFrame, textvariable=self.axVar,height = 1,width=2) self.axVar.set("sp") self.axLab.pack(side="left") self.AxCanvas = FigureCanvasTkAgg(self.AxisFig, self.AxisFrame) self.AxCanvas.get_tk_widget().pack(side = "left",pady=2) self.decode_frame = Frame(self.plot_frame) self.decode_frame.pack(side="top", fill="both",expand = 0) self.channel_frame = Frame(self.plot_frame) self.channel_frame.pack(side="top", fill="both",expand = 0)#<----------------------------- self.plot_frames = [] for i in range(0,16): self.plotFrame = Frame(self.channel_frame) self.plot_frames.append(self.plotFrame) self.decode_frames = [] for i in range(0,8): self.decodeFrame = Frame(self.decode_frame) self.decode_frames.append(self.decodeFrame) self.plot_figures = [] self.plot_axes = [] self.plot_canvases = [] self.plot_labels = [] self.plot_label_values = [] for i in range(0,16): self.figure = plt.Figure(figsize=(25,2), dpi=150) self.plot_figures.append(self.figure) self.plot_figures[i].set_figheight(0.2)#<------------------------------------------------ self.plot_figures[i].subplots_adjust(left=-0.05, right=1.05, top=1, bottom=0) self.plot_figures[i].patch.set_visible(False) self.ax = self.plot_figures[i].add_subplot(111) self.plot_axes.append(self.ax) self.canvas = FigureCanvasTkAgg(self.plot_figures[i], self.plot_frames[i]) self.plot_canvases.append(self.canvas) self.insideVar = StringVar() self.plot_label_values.append(self.insideVar) self.plot_label_values[i].set(str(i)) self.plotLabel = Label(self.plot_frames[i], textvariable=self.plot_label_values[i],height = 1,width=2) self.plot_labels.append(self.plotLabel) self.plot_labels[i].pack(side="left") self.plot_canvases[i].get_tk_widget().pack(side="right", fill="both", expand=1,pady=2) self.decode_figures = [] self.decode_axes = [] self.decode_canvases = [] self.decode_labels = [] self.decode_label_values = [] for i in range(0,8): self.figure = plt.Figure(figsize=(25,2), dpi=100) self.decode_figures.append(self.figure) self.decode_figures[i].set_figheight(0.3) self.decode_figures[i].subplots_adjust(left=-0.05, right=1.05, top=1, bottom=0) self.decode_figures[i].patch.set_visible(False) self.ax = self.decode_figures[i].add_subplot(111) self.decode_axes.append(self.ax) self.canvas = FigureCanvasTkAgg(self.decode_figures[i], self.decode_frames[i]) self.decode_canvases.append(self.canvas) self.insideVar = StringVar() self.decode_label_values.append(self.insideVar) self.decode_label_values[i].set(str(i+1)) self.decodeLabel = Label(self.decode_frames[i], textvariable=self.decode_label_values[i],height = 1,width=2) self.decode_labels.append(self.decodeLabel) self.decode_labels[i].pack(side="left") self.decode_canvases[i].get_tk_widget().pack(side="right", fill="both", expand=1,pady=2) self.BStart = Button(self.top1, text = "Start",height=2, width=30, command = self.StartCallBack) self.BStart.place(x = 20,y = 10) self.L2var = StringVar() self.L2 = Label(self.top1, textvariable=self.L2var) self.L2var.set("Duration:") self.L2.place(x = 20,y = 70) self.STB1var = StringVar() self.STB1var.set("255") self.STB1 = Entry(self.top1, width=11,textvariable = self.STB1var) self.STB1.place(x = 85,y = 70) self.comboDuration = Combobox(self.top1, values=[ "samp", "sec", "msec", "usec", "nsec"], state="readonly", width = 8) self.comboDuration.place(x = 170,y = 70) self.comboDuration.current(0) self.L3var = StringVar() self.L3 = Label(self.top1, textvariable = self.L3var) self.L3var.set("Samp. rate:") self.L3.place(x = 20,y = 90) self.STB2var = StringVar() self.STB2var.set("300") self.STB2 = Entry(self.top1, width=11,textvariable = self.STB2var) self.STB2.place(x = 85,y = 90) self.comboRate = Combobox(self.top1, values=[ "Hz", "kHz", "MHz"], state="readonly", width = 8) self.comboRate.place(x = 170,y = 90) self.comboRate.current(2) self.L6var = StringVar() self.L6 = Label(self.top1, textvariable=self.L6var) self.L6var.set("Input threshold, V:") self.L6.place(x = 20,y = 110) self.STB3var = StringVar() self.STB3var.set("3") self.STB3 = Entry(self.top1, width=11,textvariable = self.STB3var) self.STB3.place(x = 170,y = 110) self.var1 = IntVar() self.CB1 = Checkbutton(self.top1, text='Trigger',variable=self.var1, onvalue=1, offvalue=0, command=self.TriggerCallBack) # self.CB1.place(x = 20,y = 145) self.L4var = StringVar() self.L4 = Label(self.top1, textvariable=self.L4var) self.L4var.set("Trigger type:") self.L4.place(x = 20,y = 165) self.comboTriggerT = Combobox(self.top1, values=["Rising edge", "Falling edge", "High", "Low"], state="disabled", width = 15) self.comboTriggerT.place(x = 125,y = 165) self.comboTriggerT.current(0) self.L5var = StringVar() self.L5 = Label(self.top1, textvariable=self.L5var) self.L5var.set("Trigger channel:") self.L5.place(x = 20,y = 185) self.comboTriggerCh = Combobox(self.top1, values=["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"], state="disabled", width = 15) self.comboTriggerCh.place(x = 125,y = 185) self.comboTriggerCh.current(0) self.channel_active_int = [] for i in range(0,16): self.channel_active_int.append(0) self.decode_active_int = [] for i in range(0,8): self.decode_active_int.append(0) self.L61var = StringVar() self.L61 = Label(self.top1, textvariable=self.L61var) self.L61var.set("Samp. before trig:") self.L61.place(x = 20,y = 205) self.STB31var = StringVar() self.STB31var.set("3") self.STB31 = Entry(self.top1, width=18,state="disabled",textvariable = self.STB31var) self.STB31.place(x = 125,y = 205) self.L7var = StringVar() self.L7 = Label(self.top1, textvariable=self.L7var) self.L7var.set("Channels:") self.L7.place(x = 20,y = 240) self.channel_active = [] self.channel_ch_box = [] for i in range(0,16): self.chAct = IntVar() self.channel_active.append(self.chAct) self.chActChB = Checkbutton(self.top1, text=str(i),variable=self.channel_active[i], onvalue=1, offvalue=0, command=self.RefreshCh) self.channel_ch_box.append(self.chActChB) self.channel_ch_box[i].place(x = 20+(i%4)*60,y = 260+(i//4)*20) self.L8var = StringVar() self.L8 = Label(self.top1, textvariable=self.L8var) self.L8var.set("Decoders:") self.L8.place(x = 20,y = 355) self.decode_cb = [] self.decode_cb_var = [] self.decode_combo = [] self.decode_buttons = [] for i in range(0,8): dec_cb = IntVar() self.decode_cb_var.append(dec_cb) decActChB = Checkbutton(self.top1, text=str(i+1),variable=self.decode_cb_var[i], onvalue=1, offvalue=0, command=self.ResetDecodes) # self.decode_cb.append(decActChB) self.decode_cb[i].place(x = 20,y = 375+(i*28)) decodeCombo = Combobox(self.top1, values=["i2c"],state="disabled",width = 20) self.decode_combo.append(decodeCombo) self.decode_combo[i].place(x = 60,y = 375+(i*28)) self.decode_combo[i].current(0) self.decode_combo[i].bind("<<ComboboxSelected>>", self.ComboUpdate) self.decodeButton = Button(self.top1, text = "set",height=1, width=3, state="disabled") self.decode_buttons.append(self.decodeButton) self.decode_buttons[i].place(x = 210,y = 372+(i*28)) self.decode_buttons[i].configure(command=lambda:self.decoder_instances[i].set_decode(self.channel_active_int)) self.BDecode = Button(self.top1, text = "Decode",height=2, width=30, command = self.ResetDecodes) self.BDecode.place(x = 20,y = 600) self.BFill = Button(self.top1, text = "Fill",height=2, width=13, command = self.FillCallBack) self.BFill.place(x = 20,y = 650) self.BSort = Button(self.top1, text = "Sort",height=2, width=13, command = self.SortCallBack) self.BSort.place(x = 140,y = 650) for root, dirs, files in os.walk("."): for filename in files: if(filename[0:3]== "la_" and filename[-3:]== ".py"): print(filename) module_name = filename[3:len(filename)-3] for i in range(0,8): if module_name not in self.decode_combo[i]['values']: self.decode_combo[i]['values'] += (module_name,) self.drawDecodes([1,0,0,0,0,0,0,0],0) self.drawPlots([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],1,1) self.drawDecodes([0,0,0,0,0,0,0,0],0) self.master.protocol("WM_DELETE_WINDOW",self.exit_handler) def calcPosition(self,*args): sampOnScreenMin = 30 sampOnScreenMax = 10000 self.index_max = 0 for i in range(0,16): if(self.index_max < len(self.results[i])): self.index_max = len(self.results[i]) if (self.index_max > sampOnScreenMin and self.index_max < sampOnScreenMax): self.sampOnScreen = sampOnScreenMin + int(((self.index_max-sampOnScreenMin) / 1000) * (1000-self.w1.get())) elif (self.index_max > sampOnScreenMax): self.sampOnScreen = sampOnScreenMin + int(((sampOnScreenMax-sampOnScreenMin) / 1000) * (1000-self.w1.get())) else: self.sampOnScreen = self.index_max self.sampPitch = (self.sampOnScreen // 1000) +1# if (self.index_max > sampOnScreenMin): self.startPosition = int((self.index_max - self.sampOnScreen)/100000 * self.w2.get()) else: self.startPosition = 0 self.finishPosition = self.startPosition + self.sampOnScreen self.drawPlots(self.channel_active_int,0,0) def RefreshCh(self): for i in range(0,16): if(self.index_max < len(self.results[i])): self.index_max = len(self.results[i]) for i in range(0,16): if(len(self.results[i])<self.index_max and self.channel_active[i].get() == 1): self.results[i] = [0]*self.index_max self.calcPosition() self.ResetPlots() def ResetPlots(self): self.channelActiveMask = 0 self.channel_count = 0 for i in range(0,16): self.channel_active_int[i] = self.channel_active[i].get() if(self.channel_active_int[i]==1): self.channel_count += 1 self.channel_decode[i] = self.channel_count-1 for i in range(0,16): self.channelActiveMask = (self.channelActiveMask << 1) | self.channel_active_int[15-i] print(self.channel_active_int) self.drawPlots(self.channel_active_int,1,0) def ResetDecodes(self): self.decodeActiveMask = 0 self.decode_count = 0 for i in range(0,8): self.decode_active_int[i] = self.decode_cb_var[i].get() if(self.decode_active_int[i]==1): self.decode_count += 1 self.decode_decode[i] = self.decode_count-1 self.decode_combo[i]["state"] = "readonly" self.decode_buttons[i]["state"] = "normal" else: self.decode_combo[i]["state"] = "disabled" self.decode_buttons[i]["state"] = "disabled" self.UpdateDecodeInstances() for i in range(0,8): if(self.decode_active_int[i] == 1): self.decoder_instances[i].decode(self.results,self.index_max,self.sampFrq) self.drawDecodes(self.decode_active_int,0) def drawPlots(self,plot_state,refreshFlag,sortFlag): self.index = np.arange(0, self.index_max, 1) self.z = [0] * self.index_max self.af.clear() self.af.axes.get_yaxis().set_visible(False) self.af.step(self.index[self.startPosition:self.finishPosition:1], self.z[self.startPosition:self.finishPosition:1], where='post', label='post') self.af.set_frame_on(False) self.AxCanvas.draw() self.AxisFrame.pack(side="top") if(sortFlag == 1): for i in range(0,16): self.plot_frames[i].pack_forget() for i in range(0,16): if(refreshFlag == 1): self.plot_axes[i].clear() self.plot_figures[i].patch.set_visible(False) if(plot_state[i]==1): self.plot_axes[i].clear() self.plot_figures[i].patch.set_visible(False) self.plot_axes[i].step(self.index[self.startPosition:self.finishPosition:1], #self.sampPitch self.results[i][self.startPosition:self.finishPosition:1], #self.sampPitch where='post', label='post') self.plot_axes[i].set_ylim(-0.01,1.01) self.plot_axes[i].axis('off') self.plot_canvases[i].draw() self.plot_canvases[i].get_tk_widget().update_idletasks() if(refreshFlag == 1): self.plot_frames[i].pack(side="top", fill="both", expand=1) elif(refreshFlag == 1): self.plot_frames[i].pack_forget() self.ResetDecodes() def drawDecodes(self,decode_state,sortFlag): if(sortFlag == 1): for i in range(0,8): self.decode_frames[i].pack_forget() for i in range(0,8): self.decode_axes[i].clear() self.decode_figures[i].patch.set_visible(False) if(decode_state[i]==1): self.decode_ind_temp = [] self.decode_state1_temp = [] self.decode_state2_temp = [] if(len(self.decoder_instances[i].decode_index)>0): for f in range(0,len(self.decoder_instances[i].decode_index)): if(self.decoder_instances[i].decode_index[f] > self.startPosition+0.5 and self.decoder_instances[i].decode_index[f] < self.finishPosition-0.5): self.decode_ind_temp.append(self.decoder_instances[i].decode_index[f]) self.decode_state1_temp.append(self.decoder_instances[i].decode_state1[f]) self.decode_state2_temp.append(self.decoder_instances[i].decode_state2[f]) if(len(self.decode_ind_temp)==0): self.decode_ind_temp.append(self.startPosition) self.decode_state1_temp.append(0) self.decode_state2_temp.append(1) self.decode_ind_temp.insert(0,self.startPosition) self.decode_state1_temp.insert(0,self.decode_state1_temp[0]) self.decode_state2_temp.insert(0,self.decode_state2_temp[0]) self.decode_ind_temp.append(self.finishPosition) self.decode_state1_temp.append(self.decode_state1_temp[-1]) self.decode_state2_temp.append(self.decode_state2_temp[-1]) self.decode_axes[i].plot(self.decode_ind_temp, self.decode_state1_temp, color='r') self.decode_axes[i].plot(self.decode_ind_temp, self.decode_state2_temp, color='r') self.decode_axes[i].set_ylim(-0.01,1.01) self.decode_axes[i].axis('off') for d in range(0,len(self.decoder_instances[i].decode_position)): self.decode_axes[i].text(self.decoder_instances[i].decode_position[d],0.1,self.decoder_instances[i].decode_text[d], fontsize=10) self.decode_canvases[i].draw() self.decode_frames[i].pack(side="top", fill="both", expand=1) else: self.decode_frames[i].pack_forget() def TriggerCallBack(self): if(self.var1.get() == 1): self.comboTriggerCh["state"] = "readonly" self.comboTriggerT["state"] = "readonly" self.STB31["state"] = "normal" else: self.comboTriggerCh["state"] = "disabled" self.comboTriggerT["state"] = "disabled" #self.STB31var.set(3) self.STB31["state"] = "disabled" def ft_init(self): #Get the device list and save the index of logic analyzer into deviceIndex self.deviceList = ftd2xx.listDevices(0) # returns the list of ftdi devices S/Ns self.deviceIndex = -1; self.status = -1; if self.deviceList : print(len(self.deviceList), 'ftdi devices found') for x in range(0,len(self.deviceList)): if ( "LogicAnalyzer" in str(ftd2xx.getDeviceInfoDetail(x)['description'])) : print("Device %d details: "%x) print('-------------------------------------------------') print("Serial : " + str(ftd2xx.getDeviceInfoDetail(x)['serial'])) print("Type : " + str(ftd2xx.getDeviceInfoDetail(x)['type'])) print("ID : " + str(ftd2xx.getDeviceInfoDetail(x)['id'])) print("Description : " + str(ftd2xx.getDeviceInfoDetail(x)['description'])) print('-------------------------------------------------') if self.deviceIndex < 0: self.deviceIndex = x break else: print("no ftdi devices connected") def connect(self): if self.deviceIndex >= 0 : print('Connecting to device with index %d'% self.deviceIndex) self.dev = ftd2xx.open(self.deviceIndex) #FT4HNA7Z self.status = 1 time.sleep(0.1) self.dev.setBitMode(0x00, 0x40) print('Device connected') elif ftd2xx.listDevices(0): print("no FTDI devices to be connected") self.messagebox.showinfo(title=None, message="Logic Analyzer was not found") def disconnect(self): self.dev.close() print("Device disconnected") def timerHandler(self): self.read() print("check if all data collected %d"%len(self.rx_buffer)) print("needed %d"%(self.BBSamp-self.BBSamp*0.01)) if (len(self.rx_buffer) < (self.BBSamp-self.BBSamp*0.01) and (self.timeout < 50 or self.var1.get() == 1)) : self.timeout += 1 self.master.after(1, self.timerHandler) else: print("data collected") self.disconnect() self.w1.set(0) self.w2.set(0) self.calcPosition() def send(self): print("Send data") self.tx_data = "#>HH" self.tx_data = "#$FF" + self.HHTrigPosStr self.tx_data += "#$EE" + self.EEVoltStr self.tx_data += "#$AA" + self.AARateStr self.tx_data += "#$BB" + self.BBSampStr self.tx_data += "#$CC" + self.CCTrigStr self.tx_data += "#$DD" + self.DDMaskStr self.tx_data += "#>GG" self.tx_data = self.tx_data.upper() self.tx_data += self.tx_data for a in range(0,16): self.results[a] = [] print(self.tx_data) b=bytearray() b.extend(map(ord,self.tx_data)) if len(self.tx_data)>0 : print("\r\nSending %d bytes:"%len(self.tx_data)) print('-------------------------------------------------') print(self.tx_data) print('-------------------------------------------------') self.written = self.dev.write(self.tx_data) else : print("Please enter data into a top text field") #self.timer1.start() self.timeout = 0 self.rx_buffer = bytearray() self.timerHandler() def read(self): rx_data = bytearray() while self.dev.getQueueStatus()>0 : rx_data = self.dev.read(self.dev.getQueueStatus()) if len(rx_data)>0 : self.rx_buffer += rx_data print("\r\nReceived %d bytes:"%len(rx_data)) print('-------------------------------------------------') self.timeout = 0 # reset timeout if some data received if(self.channel_count <= 8): for i in range(0,len(rx_data),1): x = bytearray() x.append(rx_data[i]); if(self.channel_count <= 2): for ind in range(0,16): if(self.channel_active_int[ind] == 1): self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>self.channel_decode[ind]+6)&1)) self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>self.channel_decode[ind]+4)&1)) self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>self.channel_decode[ind]+2)&1)) self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>self.channel_decode[ind])&1)) elif(self.channel_count <= 4): for ind in range(0,16): if(self.channel_active_int[ind] == 1): self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>self.channel_decode[ind]+4)&1)) self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>self.channel_decode[ind])&1)) elif(self.channel_count <= 8): for ind in range(0,16): if(self.channel_active_int[ind] == 1): self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>self.channel_decode[ind])&1)) elif(self.channel_count > 8 and self.channel_count <= 16): for i in range(0,len(rx_data)//2,2): for ind in range(0,16): x = bytearray() x.append(rx_data[i]) x.append(rx_data[i+1]) self.results[ind].append((int(int.from_bytes(x, byteorder='big', signed=False)>>ind)&1)) def updSet(self): temp1 = 1 ##AA DATA RATE if (self.comboRate.get() == "Hz"): temp1 = 1 elif(self.comboRate.get() == "kHz"): temp1 = 1000 elif(self.comboRate.get() == "MHz"): temp1 = 1000000 self.AARate = self.coreFrq // (float(self.STB2var.get())*temp1)-1 if (self.AARate > 16777215): self.AARate = 16777215 elif(self.AARate < 0): self.AARate = 0 self.sampFrq = self.coreFrq / ((self.AARate+1)*temp1) self.STB2var.set(str(self.sampFrq)) self.sampFrq = self.coreFrq / (self.AARate+1) AARateByte = hex(int(self.AARate)) self.AARateStr = str(AARateByte) self.AARateStr = self.AARateStr[2:] for ind in range(0,6-len(self.AARateStr)): self.AARateStr = '0' + self.AARateStr print("AA(Frq) = %d"%self.AARate) print(self.AARateStr) ##BB DURATION if (self.comboDuration.get() == "samp"): self.BBSamp = float(self.STB1var.get()) // 1 self.STB1var.set(str(int(self.BBSamp))) else: if (self.comboDuration.get() == "sec"): temp1 = 1000000000 elif(self.comboDuration.get() == "msec"): temp1 = 1000000 elif(self.comboDuration.get() == "usec"): temp1 = 1000 elif(self.comboDuration.get() == "nsec"): temp1 = 1 self.BBSamp = (temp1 * float(self.STB1var.get())) // self.coreFrqPeriod self.BBSamp += 1 if(self.channel_count>0 and self.channel_count<=2): self.BBSamp = self.BBSamp / 4 print("2") elif(self.channel_count>2 and self.channel_count<=4): self.BBSamp = self.BBSamp / 2 print("4") elif(self.channel_count>8): self.BBSamp = self.BBSamp * 2 print("16") if (self.BBSamp > 16777215): self.BBSamp = 16777215 elif(self.BBSamp < 0): self.BBSamp = 0 BBSampByte = hex(int(self.BBSamp)) self.BBSampStr = str(BBSampByte) self.BBSampStr = self.BBSampStr[2:] for ind in range(0,6-len(self.BBSampStr)): #fill most sign bits with 0 self.BBSampStr = '0' + self.BBSampStr print("BB(Samp) = %d"%self.BBSamp) print(self.BBSampStr) #CC TRIGGER CH if (self.var1.get() == 1): if(self.comboTriggerT.get()=="Rising edge"): CCTrigTStr = '0' elif(self.comboTriggerT.get()=="Falling edge"): CCTrigTStr = '1' elif(self.comboTriggerT.get()=="High"): CCTrigTStr = '2' elif(self.comboTriggerT.get()=="Low"): CCTrigTStr = '3' else: CCTrigTStr = 'F' CCTrigChByte = hex(int(self.comboTriggerCh.get())) CCTrigChStr = str(CCTrigChByte) self.CCTrigStr = "0000" + CCTrigTStr + CCTrigChStr[2:] print("CC(TrigCh) = %d"%int(self.comboTriggerCh.get())) print(self.CCTrigStr) #HH TRIGGER POSITION self.HHTrigPos = int(self.STB31var.get()) if(self.channel_count>0 and self.channel_count<=2): self.HHTrigPos = self.HHTrigPos // 8 print("2") elif(self.channel_count>2 and self.channel_count<=4): self.HHTrigPos = self.HHTrigPos // 4 print("4") elif(self.channel_count>4 and self.channel_count<=8): self.HHTrigPos = self.HHTrigPos // 2 print("8") if (self.HHTrigPos > 64000): self.HHTrigPos = 64000 elif(self.HHTrigPos < 0): self.HHTrigPos = 0 HHTrigPosByte = hex(self.HHTrigPos) self.HHTrigPosStr = str(HHTrigPosByte) self.HHTrigPosStr = self.HHTrigPosStr[2:] for ind in range(0,6-len(self.HHTrigPosStr)): self.HHTrigPosStr = '0' + self.HHTrigPosStr print("лала(TrigPos) = %d"%self.HHTrigPos) print(self.HHTrigPosStr) #DD CH BITMAP DDMaskByte = hex(self.channelActiveMask) self.DDMaskStr = str(DDMaskByte) self.DDMaskStr = self.DDMaskStr[2:] for i in range(0,6-len(self.DDMaskStr)): self.DDMaskStr = '0' + self.DDMaskStr print("DD(Mask) = %d"%self.channelActiveMask) print(self.DDMaskStr) #EE VOLTAGE EEVoltFl = float(self.STB3var.get()) if (EEVoltFl > 5): self.STB3var.set("5") if (EEVoltFl > 3.6): EEVoltFl = 3.6 elif (EEVoltFl < 0.6): self.STB3var.set("0.6") EEVoltFl = 0.6 self.EEVolt = (EEVoltFl-0.6) * 65 self.EEVolt = int(255 - self.EEVolt) EEVoltByte = hex(self.EEVolt) self.EEVoltStr = str(EEVoltByte) self.EEVoltStr = "0000" + self.EEVoltStr[2:] print("EE(Volt) = %d"%self.EEVolt) print(self.EEVoltStr) def StartCallBack(self): self.updSet() self.ft_init() self.connect() self.send() def FillCallBack(self): self.decode_frame.pack_forget() self.channel_frame.pack_forget() if(self.BFill['text'] == "Fill"): self.BFill['text'] = "standart view" self.decode_frame.pack(side="top", fill="both",expand = 1) self.channel_frame.pack(side="top", fill="both",expand = 1) else: self.BFill['text'] = "Fill" self.decode_frame.pack(side="top", fill="both",expand = 0) self.channel_frame.pack(side="top", fill="both",expand = 0) def SortCallBack(self): self.drawDecodes(self.decode_active_int,1) self.drawPlots(self.channel_active_int,1,1) def ComboUpdate(self,event): self.UpdateDecodeInstances() def UpdateDecodeInstances(self): for i in range(0,8): if(self.dec_instance_state[i] != self.decode_combo[i].get() and self.decode_cb_var[i].get() == 1): self.dec_instance_state[i] = self.decode_combo[i].get() if(self.decode_combo[i].get() == "i2c"): self.decoder_instances[i] = i2c(self.master) else: filename = "la_" + self.decode_combo[i].get() module = importlib.import_module(filename) class_ = getattr(module, filename[3:]) self.decoder_instances[i] = class_(self.master) self.decode_buttons[i].configure(command=lambda x=i :self.setDecode(x)) def setDecode(self,ch): self.decoder_instances[ch].set_decode(self.channel_active_int) def zoomSliderP(self): temp = self.w1.get() temp += 1 self.w1.set(temp) def zoomSliderM(self): temp = self.w1.get() temp -= 1 self.w1.set(temp) def shiftSliderMM(self): temp1 = self.index_max/100000 temp2 = int(self.sampOnScreen/temp1) temp = self.w2.get() temp -= temp2 self.w2.set(temp) def shiftSliderM(self): temp1 = self.index_max/100000 temp2 = int(self.sampOnScreen/temp1/10) temp = self.w2.get() temp -= temp2 self.w2.set(temp) def shiftSliderP(self): temp1 = self.index_max/100000 temp2 = int(self.sampOnScreen/temp1/10) temp = self.w2.get() temp += temp2 self.w2.set(temp) def shiftSliderPP(self): temp1 = self.index_max/100000 temp2 = int(self.sampOnScreen/temp1) temp = self.w2.get() temp += temp2 self.w2.set(temp) def disconnectCallBack(self): self.disconnect() def sendCallBack(self): self.send() def exit_handler(self): #disconnect() #add checking if connected self.drawPlots([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],1,0) self.drawDecodes([0,0,0,0,0,0,0,0],0) print('Bye! :)') self.master.destroy()
class UserInterface(): '''用户界面,包括图形化窗口与交互逻辑''' def __init__(self, main): self.main = main self.window = Tk() self.window.withdraw() #隐藏窗口(等到窗口宽高位置设定好后再显示) self.window.title('Period Calculator V%s' % self.main.version) #窗口标题 with open('temp.ico', 'wb') as temp_ico: #生成临时ico图标文件 temp_ico.write(base64.b64decode(icon.encoded_img)) self.window.iconbitmap('temp.ico') #设置窗口左上角图标 os.remove('temp.ico') #删除临时ico图标文件 self.scale_factor = 1 #缩放因子 self.dpi_adapt() #高DPI适配 self.window_width = int(self.main.window_width * self.scale_factor) self.window_height = int(self.main.window_height * self.scale_factor) window_x = int((self.window.winfo_screenwidth() * self.scale_factor - self.window_width) / 2) window_y = int((self.window.winfo_screenheight() * self.scale_factor - self.window_height) / 2) self.window.geometry('{}x{}+{}+{}'.format( self.window_width, #窗口宽 self.window_height, #窗口高 window_x, #窗口位置x window_y #窗口位置y )) self.window.resizable(False, False) #锁定窗口大小 self.window.deiconify() #显示窗口 self.init_frame_left() #初始化左边栏 self.init_frame_stats() #默认初始页=数据统计页 self.current_frame = self.frame_stats #记录当前页面引用 #弹窗通知记录文件加载异常(如有) if self.main.load_error: messagebox.showwarning(message=self.main.error_msg) def dpi_adapt(self): '''解决高分屏下程序界面模糊问题(高DPI适配)''' if self.main.dpi_adapt: try: #设置由应用程序自己控制缩放 ctypes.windll.shcore.SetProcessDpiAwareness(1) #获得显示设置的缩放因子 self.scale_factor = ctypes.windll.shcore.GetScaleFactorForDevice( 0) / 100 #设置缩放 self.window.tk.call('tk', 'scaling', self.scale_factor * 1.6) except Exception: pass def init_frame_left(self): '''左边栏框架''' self.frame_left = Frame( self.window, bd=self.window_width / 120, relief='groove', width=self.window_width * 0.3, height=self.window_height, bg='#FFC0CB' #pink ) self.frame_left.pack(side='left') self.frame_left.pack_propagate(0) self.init_btn_add() self.init_btn_calendar() self.init_btn_stats() self.init_btn_list() self.init_btn_settings() self.init_btn_about() self.init_indicator() def init_btn_add(self): '''左边栏新增开始/结束按钮''' self.btn_add = Button( self.frame_left, text='新增开始/结束', bd=self.window_width / 150, relief='groove', width=14, height=3, bg='#DA70D6', #orchid fg='#FFFFFF', #white activebackground='#DA70D6', activeforeground='#FFFFFF', command=self.click_add) self.btn_add.place(relx=0.5, rely=0.17, anchor='center') def init_btn_calendar(self): '''左边栏日历按钮''' self.btn_calendar = Button( self.frame_left, text='日历', bd=self.window_width / 150, relief='groove', width=10, height=1, bg='#FFF0F5', #lavenderblush fg='#FF1493', #deeppink activebackground='#FFF0F5', activeforeground='#FF1493', command=self.click_calendar) self.btn_calendar.place(relx=0.5, rely=0.35, anchor='center') def init_btn_stats(self): '''左边栏统计数据按钮''' self.btn_stats = Button( self.frame_left, text='统计数据', bd=self.window_width / 150, relief='groove', width=10, height=1, bg='#FFF0F5', #lavenderblush fg='#FF1493', #deeppink activebackground='#FFF0F5', activeforeground='#FF1493', command=self.click_stats) self.btn_stats.place(relx=0.5, rely=0.48, anchor='center') def init_btn_list(self): '''左边栏查看记录按钮''' self.btn_list = Button( self.frame_left, text='查看记录', bd=self.window_width / 150, relief='groove', width=10, height=1, bg='#FFF0F5', #lavenderblush fg='#FF1493', #deeppink activebackground='#FFF0F5', activeforeground='#FF1493', command=self.click_list) self.btn_list.place(relx=0.5, rely=0.61, anchor='center') def init_btn_settings(self): '''左边栏设置按钮''' self.btn_settings = Button( self.frame_left, text='设置', bd=self.window_width / 150, relief='groove', width=10, height=1, bg='#FFF0F5', #lavenderblush fg='#FF1493', #deeppink activebackground='#FFF0F5', activeforeground='#FF1493', command=self.click_settings) self.btn_settings.place(relx=0.5, rely=0.74, anchor='center') def init_btn_about(self): '''左边栏关于按钮''' self.btn_about = Button( self.frame_left, text='关于', bd=self.window_width / 150, relief='groove', width=10, height=1, bg='#FFF0F5', #lavenderblush fg='#FF1493', #deeppink activebackground='#FFF0F5', activeforeground='#FF1493', command=self.click_about) self.btn_about.place(relx=0.5, rely=0.87, anchor='center') def init_indicator(self): '''左边栏指示标志(爱心)''' self.indicator = Canvas( self.frame_left, highlightthickness=0, width=14 * self.window_width / 375, height=14 * self.window_width / 375, bg='#FFC0CB' #pink ) self.indicator.create_polygon( 2 * self.window_width / 375, 0, 5 * self.window_width / 375, 0, 7 * self.window_width / 375, 2 * self.window_width / 375, 9 * self.window_width / 375, 0, 12 * self.window_width / 375, 0, 13 * self.window_width / 375, 1 * self.window_width / 375, 14 * self.window_width / 375, 3 * self.window_width / 375, 14 * self.window_width / 375, 6 * self.window_width / 375, 13 * self.window_width / 375, 8 * self.window_width / 375, 7 * self.window_width / 375, 14 * self.window_width / 375, 1 * self.window_width / 375, 8 * self.window_width / 375, 0, 6 * self.window_width / 375, 0, 3 * self.window_width / 375, 1 * self.window_width / 375, 1 * self.window_width / 375, fill='#DA70D6', #orchid ) #画一个多边形爱心 self.indicator.place(relx=0.9, rely=0.48, anchor='center') def init_frame_calendar(self): '''日历页框架''' self.frame_calendar = Frame( self.window, bd=self.window_width / 120, relief='groove', width=self.window_width * 0.7, height=self.window_height, bg='#FFF0F5' #lavenderblush ) self.frame_calendar.pack(side='right') self.frame_calendar.pack_propagate(0) self.init_calendar() def init_calendar(self): '''日历页''' text_calendar = Label( self.frame_calendar, text='此功能开发中...', justify='left', bg='#FFF0F5' #lavenderblush ) text_calendar.place(relx=0.5, rely=0.4, anchor='n') def init_frame_stats(self): '''统计数据页框架''' self.frame_stats = Frame( self.window, bd=self.window_width / 120, relief='groove', width=self.window_width * 0.7, height=self.window_height, bg='#FFF0F5' #lavenderblush ) self.frame_stats.pack(side='right') self.frame_stats.pack_propagate(0) self.init_stats() def init_stats(self): '''统计数据页''' self.main.show_stats() #子框架,实现所有控件上下排列的同时整体居中 frame_stats_amid = Frame( self.frame_stats, bg='#FFF0F5' #lavenderblush ) frame_stats_amid.pack(side='top', expand='yes') text_ongoing = Label( frame_stats_amid, text=self.main.print_ongoing, bg='#FFF0F5' #lavenderblush ) text_ongoing.pack(side='top') def click_reset(): ans = messagebox.askokcancel(message='确定要取消进行中的经期吗?') if ans: self.main.reset() self.click_stats() if self.main.ongoing_date is not None: #重置按钮,点击后重置进行中的经期并刷新本页面 btn_reset = Button( frame_stats_amid, text='重置', bd=2, relief='groove', bg='#FFFFFF', #white fg='#FF1493', #deeppink activebackground='#FFFFFF', activeforeground='#FF1493', command=click_reset) btn_reset.pack(side='top', pady=self.window_height / 60) text_stats = Label( frame_stats_amid, text=self.main.print_stats, justify='left', bg='#FFF0F5' #lavenderblush ) text_stats.pack(side='top') text_future = Label( frame_stats_amid, text=self.main.print_future, justify='left', bg='#FFF0F5' #lavenderblush ) text_future.pack(side='top') def init_frame_list(self): '''查看记录页框架''' self.frame_list = Frame( self.window, bd=self.window_width / 120, relief='groove', width=self.window_width * 0.7, height=self.window_height, bg='#FFF0F5' #lavenderblush ) self.frame_list.pack(side='right') self.frame_list.pack_propagate(0) self.init_list() def init_list(self): '''查看记录页''' self.main.show_list() label_list_titles = Label( self.frame_list, text='\n序号 起始日期 持续天数 间隔天数', bg='#FFF0F5' #lavenderblush ) label_list_titles.pack(side='top', anchor='w', padx=self.window_width / 40) frame_list_top = Frame( self.frame_list, padx=self.window_width / 40, bg='#FFF0F5' #lavenderblush ) frame_list_top.pack(side='top', fill='x') #滚动条控件 scrollbar_list = Scrollbar(frame_list_top, orient='vertical') scrollbar_list.pack(side='right', anchor='n', fill='y') listbox_list = Listbox( frame_list_top, activestyle='none', selectmode='single', height=20, font=('consolas', 10), yscrollcommand=scrollbar_list.set #列表绑定滚动条 ) listbox_list.insert('end', *self.main.print_list) #载入全部记录 listbox_list.insert('end', ' +') #末尾空行方便插入最新记录 listbox_list.pack(side='right', anchor='n', expand='yes', fill='x') scrollbar_list.configure(command=listbox_list.yview) #滚动条绑定列表 listbox_list.yview_moveto(1) #视图默认滚动到底 # listbox_list.selection_set(self.main.count - 1) # listbox_list.event_generate("<<ListboxSelect>>") #默认选择最后一条记录 frame_list_bottom = Frame( self.frame_list, padx=self.window_width / 40, pady=self.window_height / 20, bg='#FFF0F5' #lavenderblush ) frame_list_bottom.pack(side='top', fill='x') def click_insert(): '''点击插入记录''' if len(listbox_list.curselection()) == 1: index = listbox_list.curselection()[0] dialog_insert = Toplevel() #弹出对话框 dialog_insert.wm_transient(self.window) #与父窗口关联,窗口管理器不会当成独立窗口 dialog_insert.focus_set() #焦点切换到对话框 dialog_insert.grab_set() #事件不会传入父窗口(父窗口无法点击) dialog_insert.withdraw() #隐藏窗口(等到窗口宽高位置设定好后再显示) dialog_insert.title('插入经期记录 (第{}行)'.format(index + 1)) #窗口标题 frame_insert = Frame( dialog_insert, padx=self.window_width / 20, pady=self.window_width / 20, bg='#FFF0F5' #lavenderblush ) frame_insert.pack() #以下为开始日期控件组 frame_insert_fromdate = Frame( frame_insert, bg='#FFF0F5' #lavenderblush ) frame_insert_fromdate.pack(side='top', anchor='s') label_from = Label(frame_insert_fromdate, text='开始日期: ', bg='#FFF0F5') label_from.pack(side='left', anchor='n') box_yyyy1 = Combobox(frame_insert_fromdate, width=4, state='readonly') #年选项框 box_yyyy1['value'] = tuple(range(2000, date.today().year + 1)) box_yyyy1.current(date.today().year - 2000) #默认值为今天 box_yyyy1.pack(side='left', anchor='n') label_year1 = Label(frame_insert_fromdate, text='年 ', bg='#FFF0F5') label_year1.pack(side='left', anchor='n') box_mm1 = Combobox(frame_insert_fromdate, width=2, state='readonly') #月选项框 box_mm1['value'] = tuple(range(1, 13)) box_mm1.current(date.today().month - 1) #默认值为今天 box_mm1.pack(side='left', anchor='n') label_month1 = Label(frame_insert_fromdate, text='月 ', bg='#FFF0F5') label_month1.pack(side='left', anchor='n') box_dd1 = Combobox(frame_insert_fromdate, width=2, state='readonly') #日选项框 box_dd1['value'] = tuple(range(1, 32)) box_dd1.current(date.today().day - 1) #默认值为今天 box_dd1.pack(side='left', anchor='n') label_day1 = Label(frame_insert_fromdate, text='日\n', bg='#FFF0F5') label_day1.pack(side='left', anchor='n') #以下为结束日期控件组 frame_insert_todate = Frame( frame_insert, bg='#FFF0F5' #lavenderblush ) frame_insert_todate.pack(side='top', anchor='s') label_to = Label(frame_insert_todate, text='结束日期: ', bg='#FFF0F5') label_to.pack(side='left', anchor='n') box_yyyy2 = Combobox(frame_insert_todate, width=4, state='readonly') #年选项框 box_yyyy2['value'] = tuple(range(2000, date.today().year + 1)) box_yyyy2.current(date.today().year - 2000) #默认值为今天 box_yyyy2.pack(side='left', anchor='n') label_year2 = Label(frame_insert_todate, text='年 ', bg='#FFF0F5') label_year2.pack(side='left', anchor='n') box_mm2 = Combobox(frame_insert_todate, width=2, state='readonly') #月选项框 box_mm2['value'] = tuple(range(1, 13)) box_mm2.current(date.today().month - 1) #默认值为今天 box_mm2.pack(side='left', anchor='n') label_month2 = Label(frame_insert_todate, text='月 ', bg='#FFF0F5') label_month2.pack(side='left', anchor='n') box_dd2 = Combobox(frame_insert_todate, width=2, state='readonly') #日选项框 box_dd2['value'] = tuple(range(1, 32)) box_dd2.current(date.today().day - 1) #默认值为今天 box_dd2.pack(side='left', anchor='n') label_day2 = Label(frame_insert_todate, text='日\n\n', bg='#FFF0F5') label_day2.pack(side='left', anchor='n') def insert(): '''点击对话框中的插入记录按钮''' #获取开始日期 yyyy1 = int(box_yyyy1.get()) mm1 = int(box_mm1.get()) dd1 = int(box_dd1.get()) #获取结束日期 yyyy2 = int(box_yyyy2.get()) mm2 = int(box_mm2.get()) dd2 = int(box_dd2.get()) self.main.insert(index, yyyy1, mm1, dd1, yyyy2, mm2, dd2) if self.main.add_error: #插入记录异常 messagebox.showinfo(message=self.main.error_msg, parent=dialog_insert) else: #插入记录成功 dialog_insert.destroy() #关闭对话框 self.refresh() #刷新页面相关信息 messagebox.showinfo(message='插入记录成功!') #对话框的插入记录按钮 btn_insert_enter = Button( frame_insert, text='插入记录', bd=2, relief='groove', bg='#FFFFFF', #white fg='#FF1493', #deeppink activebackground='#FFFFFF', activeforeground='#FF1493', command=insert) btn_insert_enter.pack(side='top', anchor='n') dialog_insert.update_idletasks() #手动更新显示,以获得布局后的窗口宽高来设置窗口位置 dialog_insert_x = int( (dialog_insert.winfo_screenwidth() * self.scale_factor - dialog_insert.winfo_width()) / 2) dialog_insert_y = int( (dialog_insert.winfo_screenheight() * self.scale_factor - dialog_insert.winfo_height()) / 2) dialog_insert.geometry('+{}+{}'.format( dialog_insert_x, dialog_insert_y)) #设置窗口位置 dialog_insert.resizable(False, False) #锁定窗口大小 dialog_insert.deiconify() #显示窗口 # dialog_insert.wait_window() #插入记录按钮 btn_insert = Button( frame_list_bottom, text='在选中行上方\n插入记录', height=2, bd=2, relief='groove', bg='#FFFFFF', #white fg='#FF1493', #deeppink activebackground='#FFFFFF', activeforeground='#FF1493', command=click_insert) btn_insert.pack(side='left', expand='yes') def delete(): '''点击删除选中记录''' if len(listbox_list.curselection()) == 1: index = listbox_list.curselection()[0] if index < self.main.count: ans = messagebox.askokcancel(message='确定要删除选中的记录吗?') if ans: self.main.delete(index) self.click_list() #删除选中记录按钮 btn_delete = Button( frame_list_bottom, text='删除选中记录', height=2, bd=2, relief='groove', bg='#FFFFFF', #white fg='#FF1493', #deeppink activebackground='#FFFFFF', activeforeground='#FF1493', command=delete) btn_delete.pack(side='left', expand='yes') def delete_all(): '''点击删除全部记录''' if self.main.count > 0: ans = messagebox.showwarning(title='警告', message='危险操作') if ans: ans = messagebox.askokcancel(title='警告:危险操作', message='确定要删除全部记录吗?') if ans: ans = messagebox.askokcancel(title='点击确定将删除全部记录', message='真的要删除全部记录吗?') if ans: self.main.delete_all() self.click_list() #删除全部记录按钮 btn_delete_all = Button( frame_list_bottom, text='删除全部记录', height=2, bd=2, relief='groove', bg='#FFFFFF', #white fg='#FF1493', #deeppink activebackground='#FFFFFF', activeforeground='#FF1493', command=delete_all) btn_delete_all.pack(side='left', expand='yes') def init_frame_settings(self): '''设置页框架''' self.frame_settings = Frame( self.window, bd=self.window_width / 120, relief='groove', width=self.window_width * 0.7, height=self.window_height, bg='#FFF0F5' #lavenderblush ) self.frame_settings.pack(side='right') self.frame_settings.pack_propagate(0) self.init_settings() def init_settings(self): '''设置页''' def change_dpi_adapt(): '''更改dpi_adapt设置项''' self.main.dpi_adapt = self.dpi_adapt.get() self.main.save_settings() #设置项:高dpi屏幕显示缩放适配 self.dpi_adapt = BooleanVar( value=self.main.dpi_adapt) #选框默认值。必须设为实例变量,否则会被回收 checkbox_dpi_adapt = Checkbutton( self.frame_settings, text='高dpi屏幕显示缩放适配(重启应用后生效)', variable=self.dpi_adapt, onvalue=True, offvalue=False, bg='#FFF0F5', #lavenderblush activebackground='#FFF0F5', command=change_dpi_adapt) checkbox_dpi_adapt.pack(side='top', padx=self.window_width / 20, pady=self.window_height / 20, anchor='nw') def init_frame_about(self): '''关于页框架''' self.frame_about = Frame( self.window, bd=self.window_width / 120, relief='groove', width=self.window_width * 0.7, height=self.window_height, bg='#FFF0F5' #lavenderblush ) self.frame_about.pack(side='right') self.frame_about.pack_propagate(0) self.init_about() def init_about(self): '''关于页''' self.click_count = 0 #hidden触发计数器 text_about = Text( self.frame_about, width=45, height=15, bd=0, relief='flat', cursor='arrow', bg='#FFF0F5' #lavenderblush ) text_about.insert('end', '作者: HansenH\n\n') text_about.insert('end', '邮箱: [email protected]\n\n') text_about.insert('end', '源码(Python3): \n') text_about.insert('end', 'https://github.com/HansenH/PeriodCalculator\n\n') text_about.insert('end', '\n\nMIT License\nCopyright (c) 2021 HansenH') text_about.tag_add('link', '6.0', '6.43') #第六行超链接加tag text_about.tag_config('link', foreground='blue', underline=True) text_about.tag_add('hidden', '1.4', '1.11') #第一行HansenH加tag def show_hand_cursor(event): text_about.configure(cursor='hand2') def show_arrow_cursor(event): text_about.configure(cursor='arrow') def click_link(event): webbrowser.open_new_tab( 'https://github.com/HansenH/PeriodCalculator') def show_heart_cursor(event): text_about.configure(cursor='heart') self.click_count = 0 #鼠标进入或离开'HansenH'都会重置计数器self.self.click_count def show_arrow_cursor2(event): text_about.configure(cursor='arrow') self.click_count = 0 def click_hidden_5_times(event): self.click_count += 1 if self.click_count == 5: self.hidden() #触发hidden Easter Egg! text_about.tag_bind('link', '<Enter>', show_hand_cursor) #鼠标指向 text_about.tag_bind('link', '<Leave>', show_arrow_cursor) #鼠标离开 text_about.tag_bind('link', '<Button-1>', click_link) #左键点击 text_about.tag_bind('hidden', '<Enter>', show_heart_cursor) #鼠标指向 text_about.tag_bind('hidden', '<Leave>', show_arrow_cursor2) #鼠标离开 text_about.tag_bind('hidden', '<Button-1>', click_hidden_5_times) #触发hidden text_about.place(relx=0.5, rely=0.2, anchor='n') text_about.configure(state='disabled') def click_add(self): '''点击新增按钮,创建模态对话框''' dialog_add = Toplevel() #弹出对话框 dialog_add.wm_transient(self.window) #与父窗口关联,窗口管理器不会当成独立窗口 dialog_add.focus_set() #焦点切换到对话框 dialog_add.grab_set() #事件不会传入父窗口(父窗口无法点击) dialog_add.withdraw() #隐藏窗口(等到窗口宽高位置设定好后再显示) dialog_add.title('添加经期开始/结束') #窗口标题 frame_add = Frame( dialog_add, padx=self.window_width / 20, pady=self.window_width / 20, bg='#FFF0F5' #lavenderblush ) frame_add.pack() def add(): '''点击对话框中的添加记录按钮''' yyyy = int(box_yyyy.get()) #从下拉选项框获取数据 mm = int(box_mm.get()) dd = int(box_dd.get()) self.main.add(yyyy, mm, dd) #添加经期开始/结束 if self.main.add_error: #添加记录异常 messagebox.showinfo(message=self.main.error_msg, parent=dialog_add) else: #添加记录成功 dialog_add.destroy() #关闭对话框 self.refresh() #刷新页面相关信息 messagebox.showinfo(message='添加记录成功!') #添加记录的按钮 btn_add_enter = Button( frame_add, bd=2, relief='groove', bg='#FFFFFF', #white fg='#FF1493', #deeppink activebackground='#FFFFFF', activeforeground='#FF1493', command=add) btn_add_enter.pack(side='bottom', anchor='s') if self.main.ongoing_date is None: btn_add_enter.configure(text='添加经期开始日期') else: btn_add_enter.configure(text='添加经期结束日期') box_yyyy = Combobox(frame_add, width=4, state='readonly') #年选项框 box_yyyy['value'] = tuple(range(2000, date.today().year + 1)) box_yyyy.current(date.today().year - 2000) #默认值为今天 box_yyyy.pack(side='left', anchor='n') label_year = Label(frame_add, text='年 ', bg='#FFF0F5') label_year.pack(side='left', anchor='n') box_mm = Combobox(frame_add, width=2, state='readonly') #月选项框 box_mm['value'] = tuple(range(1, 13)) box_mm.current(date.today().month - 1) #默认值为今天 box_mm.pack(side='left', anchor='n') label_month = Label(frame_add, text='月 ', bg='#FFF0F5') label_month.pack(side='left', anchor='n') box_dd = Combobox(frame_add, width=2, state='readonly') #日选项框 box_dd['value'] = tuple(range(1, 32)) box_dd.current(date.today().day - 1) #默认值为今天 box_dd.pack(side='left', anchor='n') label_day = Label(frame_add, text='日\n\n', bg='#FFF0F5') label_day.pack(side='left', anchor='n') dialog_add.update_idletasks() #手动更新显示,以获得布局后的窗口宽高来设置窗口位置 dialog_add_x = int( (dialog_add.winfo_screenwidth() * self.scale_factor - dialog_add.winfo_width()) / 2) dialog_add_y = int( (dialog_add.winfo_screenheight() * self.scale_factor - dialog_add.winfo_height()) / 2) dialog_add.geometry('+{}+{}'.format(dialog_add_x, dialog_add_y)) #设置窗口位置 dialog_add.resizable(False, False) #锁定窗口大小 dialog_add.deiconify() #显示窗口 # dialog_add.wait_window() def click_calendar(self): '''点击日历按钮''' self.indicator.place(relx=0.9, rely=0.35, anchor='center') #移动爱心位置 self.current_frame.destroy() #关闭当前的右侧页面 self.init_frame_calendar() #打开新的右侧页面 self.current_frame = self.frame_calendar def click_stats(self): '''点击统计数据按钮''' self.indicator.place(relx=0.9, rely=0.48, anchor='center') #移动爱心位置 self.current_frame.destroy() #关闭当前的右侧页面 self.init_frame_stats() #打开新的右侧页面 self.current_frame = self.frame_stats def click_list(self): '''点击查看记录''' self.indicator.place(relx=0.9, rely=0.61, anchor='center') #移动爱心位置 self.current_frame.destroy() #关闭当前的右侧页面 self.init_frame_list() #打开新的右侧页面 self.current_frame = self.frame_list def click_settings(self): '''点击设置按钮''' self.indicator.place(relx=0.9, rely=0.74, anchor='center') #移动爱心位置 self.current_frame.destroy() #关闭当前的右侧页面 self.init_frame_settings() #打开新的右侧页面 self.current_frame = self.frame_settings def click_about(self): '''点击关于按钮''' self.indicator.place(relx=0.9, rely=0.87, anchor='center') #移动爱心位置 self.current_frame.destroy() #关闭当前的右侧页面 self.init_frame_about() #打开新的右侧页面 self.current_frame = self.frame_about def hidden(self): '''Easter Egg!''' self.current_frame.destroy() #销毁原右侧页面 self.frame_left.pack_forget() #暂时隐藏左边栏 heart_rain = Canvas( self.window, highlightthickness=0, width=self.window_width, height=self.window_height, cursor='heart', bg='#FFF0F5' #lavenderblush ) heart_rain.place(relx=0.5, rely=0.5, anchor='center') heart_rain.focus_set() #焦点切换到对话框 heart_rain.create_text( 0.5 * self.window_width, 0.35 * self.window_height, text='This app is made for my beloved girl Wang Ting.', font=('Times', 12, 'bold italic'), anchor='center') heart_rain.create_text(0.5 * self.window_width, 0.85 * self.window_height, text='<返回>', anchor='center', tag='back') def create_heart(size_factor, relx, rely): '''生成爱心(尺寸倍率, 相对x坐标, 相对y坐标),锚点=S''' heart = heart_rain.create_polygon( -5 * size_factor * self.window_width / 375 + relx * self.window_width, -14 * size_factor * self.window_width / 375 + rely * self.window_height, -2 * size_factor * self.window_width / 375 + relx * self.window_width, -14 * size_factor * self.window_width / 375 + rely * self.window_height, 0 * size_factor * self.window_width / 375 + relx * self.window_width, -12 * size_factor * self.window_width / 375 + rely * self.window_height, 2 * size_factor * self.window_width / 375 + relx * self.window_width, -14 * size_factor * self.window_width / 375 + rely * self.window_height, 5 * size_factor * self.window_width / 375 + relx * self.window_width, -14 * size_factor * self.window_width / 375 + rely * self.window_height, 6 * size_factor * self.window_width / 375 + relx * self.window_width, -13 * size_factor * self.window_width / 375 + rely * self.window_height, 7 * size_factor * self.window_width / 375 + relx * self.window_width, -11 * size_factor * self.window_width / 375 + rely * self.window_height, 7 * size_factor * self.window_width / 375 + relx * self.window_width, -8 * size_factor * self.window_width / 375 + rely * self.window_height, 6 * size_factor * self.window_width / 375 + relx * self.window_width, -6 * size_factor * self.window_width / 375 + rely * self.window_height, 0 * size_factor * self.window_width / 375 + relx * self.window_width, 0 * size_factor * self.window_width / 375 + rely * self.window_height, -6 * size_factor * self.window_width / 375 + relx * self.window_width, -6 * size_factor * self.window_width / 375 + rely * self.window_height, -7 * size_factor * self.window_width / 375 + relx * self.window_width, -8 * size_factor * self.window_width / 375 + rely * self.window_height, -7 * size_factor * self.window_width / 375 + relx * self.window_width, -11 * size_factor * self.window_width / 375 + rely * self.window_height, -6 * size_factor * self.window_width / 375 + relx * self.window_width, -13 * size_factor * self.window_width / 375 + rely * self.window_height, fill='#FF1493', #deeppink ) return heart # 尺寸--速度--出现概率 # 0.5--1--0.533 1--2--0.267 2--4--0.133 4--8--0.067 # 生成位置:relx范围 -0.1~1.1 rely=-0.1 hearts = [] #爱心队列 speed = [] #每个爱心的速度 PRODUCTION_RATE = 10 #每一帧生成新爱心的概率(%) SEPPD_FACTOR = 0.75 #下落速度系数 def heart_drop_loop(): '''实现爱心不断下落的循环''' #生成爱心 if random.randint(0, 99) < PRODUCTION_RATE: rand_num = random.randint(0, 999) #四种爱心按不同概率生成 if rand_num < 533: hearts.append( create_heart(0.5, random.randint(-100, 1100) / 1000, 0)) speed.append(1) elif 533 <= rand_num < 800: hearts.append( create_heart(1, random.randint(-100, 1100) / 1000, 0)) speed.append(2) elif 800 <= rand_num < 933: hearts.append( create_heart(2, random.randint(-100, 1100) / 1000, 0)) speed.append(4) else: hearts.append( create_heart(4, random.randint(-100, 1100) / 1000, 0)) speed.append(8) #下移爱心 for i in range(len(hearts) - 1, -1, -1): heart_rain.move(hearts[i], 0, speed[i] * SEPPD_FACTOR) #删除出界的爱心(注意应当在倒序循环中删除元素) if heart_rain.coords(hearts[i])[1] > self.window_height: heart_rain.delete(hearts.pop(i)) del speed[i] heart_rain.after(10, heart_drop_loop) #after实现一段时间后再次调用自己 #如果改用while和time.sleep()实现,会形成阻塞,无法在循环中监测事件! def back(event): '''返回''' heart_rain.destroy() self.frame_left.pack(side='left') self.frame_left.pack_propagate(0) self.init_frame_about() self.current_frame = self.frame_about heart_rain.tag_bind('back', '<Button-1>', back) heart_drop_loop() def refresh(self): '''(在记录改动后)刷新当前页面''' if self.current_frame == self.frame_stats: self.click_stats() elif self.current_frame == self.frame_list: self.click_list()
class QuantMonitor(object): # 背景色 bgColor = rgb_to_hex(245, 245, 245) bgColorW = "white" def __init__(self, frame, control, language): self.parentFrame = frame self._controller = control self._logger = self._controller.get_logger() self.language = language # Monitor不同标签的背景色 self.rColor = self.bgColorW self.lColor = self.bgColor self.eColor = self.bgColor self.pColor = self.bgColor # 日志不同标签背景色 self.yColor = self.bgColor # 系统日志标签颜色 self.sColor = self.bgColor self.uColor = self.bgColorW self.createButtonFrame() # 执行列表、监控日志、信号记录、错误 self.executeList = Frame(self.parentFrame) self.errRecord = Frame(self.parentFrame) self.posMonitor = Frame(self.parentFrame) self.logRecord = Frame(self.parentFrame) self.sysLog = Frame(self.logRecord) self.sigRecord = Frame(self.logRecord) self.usrLog = Frame(self.logRecord) self.executeList.pack(side=TOP, fill=BOTH, expand=YES) self.sysText = None self.sigText = None self.usrText = None self.errText = None # 日志功能区 self.createLogBtnFrame() self.usrLog.pack(side=TOP, fill=BOTH, expand=YES) def createButtonFrame(self): btnFrame = Frame(self.parentFrame, height=30, bg=self.bgColor) btnFrame.pack_propagate(0) btnFrame.pack(side=TOP, fill=X) self.runBtn = Button(btnFrame, text="策略运行", relief=FLAT, padx=14, pady=1.5, bg=self.rColor, bd=0, highlightthickness=1, command=self.toMonFrame) self.logBtn = Button(btnFrame, text="运行日志", relief=FLAT, padx=14, pady=1.5, bg=self.lColor, bd=0, highlightthickness=1, command=self.toLogFrame) self.errBtn = Button(btnFrame, text="错误信息", relief=FLAT, padx=14, pady=1.5, bg=self.eColor, bd=0, highlightthickness=1, command=self.toErrFrame) self.posBtn = Button(btnFrame, text="组合监控", relief=FLAT, padx=14, pady=1.5, bg=self.pColor, bd=0, highlightthickness=1, command=self.toPosFrame) self.runBtn.pack(side=LEFT, expand=NO) self.logBtn.pack(side=LEFT, expand=NO) self.errBtn.pack(side=LEFT, expand=NO) self.posBtn.pack(side=LEFT, expand=NO) for btn in (self.runBtn, self.logBtn, self.errBtn, self.posBtn): btn.bind("<Enter>", self.handlerAdaptor(self.onEnter, button=btn)) btn.bind("<Leave>", self.handlerAdaptor(self.onLeave, button=btn)) def createLogBtnFrame(self): """创建日志按钮Frame""" lBtnFrame = Frame(self.logRecord, height=30, bg=self.bgColor) lBtnFrame.pack_propagate(0) lBtnFrame.pack(side=BOTTOM, fill=X) self.usrBtn = Button(lBtnFrame, text="用户日志", relief=FLAT, padx=14, pady=1.5, bg=self.rColor, bd=0, highlightthickness=1, command=self.toUsrFrame) self.sigBtn = Button(lBtnFrame, text="信号记录", relief=FLAT, padx=14, pady=1.5, bg=self.lColor, bd=0, highlightthickness=1, command=self.toSigFrame) self.sysBtn = Button(lBtnFrame, text="系统日志", relief=FLAT, padx=14, pady=1.5, bg=self.sColor, bd=0, highlightthickness=1, command=self.toSysFrame) self.usrBtn.pack(side=LEFT, expand=NO) self.sigBtn.pack(side=LEFT, expand=NO) self.sysBtn.pack(side=LEFT, expand=NO) # for btn in (self.usrBtn, self.sigBtn, self.sysBtn): # btn.bind("<Enter>", self.handlerAdaptor(self.onEnter, button=btn)) # btn.bind("<Leave>", self.handlerAdaptor(self.onLeave, button=btn)) # pass def createLog(self): self.createSysLog() self.createSignal() self.createUsrLog() def createSysLog(self): """系统日志""" self.sysText = MonitorText(self.sysLog, height=20, bd=0) self.sysText.createScrollbar() self.sysText.pack(fill=BOTH, expand=YES) def createSignal(self): """信号记录""" self.sigText = LogText(self.sigRecord, height=20, bd=0) self.sigText.createScrollbar() self.sigText.pack(fill=BOTH, expand=YES) def createUsrLog(self): """用户日志""" self.usrText = LogText(self.usrLog, height=20, bd=0) self.usrText.createScrollbar() self.usrText.pack(fill=BOTH, expand=YES) def createPos(self): headList = ["账号", "合约", "账户仓", "策略仓", "仓差", "策略多", "策略空","策略今多", "策略今空", "账户多", "账户空", "账户今多", "账户今空"] widthList = [20, 20, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] funcFrame = Frame(self.posMonitor, relief=RAISED, bg=rgb_to_hex(245, 245, 245), height=25) funcFrame.pack(side=TOP, fill=X, expand=YES, padx=1, pady=2) treeFrame = Frame(self.posMonitor, relief=RAISED, bg=rgb_to_hex(245, 245, 245)) treeFrame.pack(side=TOP, fill=X, expand=YES, padx=1, pady=2) self.posTree = ttk.Treeview(treeFrame, show="headings", height=28, columns=headList) self.posTree.pack(fill=BOTH, expand=YES, padx=5) for key, w in zip(headList, widthList): self.posTree.column(key, width=w, anchor=W) self.posTree.heading(key, text=key, anchor=W) self.createPosFunc(funcFrame) def createPosFunc(self, frame): cbV = StringVar() sbV = IntVar() timeV = IntVar() cbV.set("对盘价") sbV.set(0) timeV.set(5000) # buttonborder = Frame(frame, highlightbackground="lightblue", highlightthickness=2, bd=0) # buttonborder.pack(side=LEFT, padx=2) synBtn = Button(frame, text="持仓一键同步", relief=FLAT, activebackground="lightblue", overrelief="groove", bg=rgb_to_hex(230, 230, 230)) synBtn.pack(side=LEFT, padx=2) Label(frame, text="同步设置:", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=8).pack(side=LEFT) cbValues = ["对盘价", "最新价", "市价"] cb = ttk.Combobox(frame, values=cbValues, width=11, textvariable=cbV, state="readonly") cb.pack(side=LEFT, padx=2) Label(frame, text="+", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=1).pack(side=LEFT) sb = ttk.Spinbox(frame, values=list(range(0, 101, 1)), width=4, textvariable=sbV) sb.pack(side=LEFT, padx=2) Label(frame, text="跳", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=2).pack(side=LEFT) disCheck = Checkbutton(frame, text="间隔", bg=rgb_to_hex(245, 245, 245), width=10, bd=1, anchor=E) disCheck.pack(side=LEFT, padx=2) timeEntry = Entry(frame, relief=GROOVE, bd=2, width=5, textvariable=timeV) timeEntry.pack(side=LEFT) Label(frame, text="毫秒自动同步", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=12)\ .pack(side=LEFT, padx=2) subCheck = Checkbutton(frame, text="仅自动减仓", bg=rgb_to_hex(245, 245, 245), bd=1, anchor=W) subCheck.pack(side=LEFT, padx=5) def createExecute(self): headList = ["编号", "账号", "策略名称", "基准合约", "频率", "运行状态", "实盘运行", "初始资金", "可用资金", "最大回撤", "累计收益", "胜率"] widthList = [5, 50, 50, 50, 5, 10, 5, 20, 10, 20, 20, 5] self.executeBar = ttk.Scrollbar(self.executeList, orient="vertical") self.executeBar.pack(side=RIGHT, fill=Y) self.executeListTree = ttk.Treeview(self.executeList, show="headings", height=28, columns=tuple(headList), yscrollcommand=self.executeBar.set, style="Filter.Treeview") self.executeBar.config(command=self.executeListTree.yview) self.executeListTree.pack(fill=BOTH, expand=YES) self.executeListTree.bind("<Button-3>", self.createMenu) for key, w in zip(headList, widthList): self.executeListTree.column(key, width=w, anchor=CENTER) self.executeListTree.heading(key, text=key) def createMenu(self, event): """创建运行策略右键菜单""" RunMenu(self._controller, self.executeListTree).popupmenu(event) def _formatMonitorInfo(self, dataDict): """ 格式化监控需要的信息 :param dataDict: 策略的所有信息 :return: 需要展示的信息 """ try: Id = dataDict['StrategyId'] UserNo = dataDict["Config"]["Money"]["UserNo"] StName = dataDict['StrategyName'] BenchCon = dataDict['ContractNo'] kLineType = dataDict['KLineType'] kLineSlice = dataDict['KLinceSlice'] Frequency = str(kLineSlice) + kLineType RunType = "是" if dataDict['IsActualRun'] else "否" Status = StrategyStatus[dataDict["StrategyState"]] InitFund = dataDict['InitialFund'] Available = "{:.2f}".format(InitFund) MaxRetrace = 0.0 TotalProfit = 0.0 WinRate = 0.0 return [ Id, UserNo, StName, BenchCon, Frequency, Status, RunType, InitFund, Available, MaxRetrace, TotalProfit, WinRate ] except KeyError: traceback.print_exc() return [] def addExecute(self, dataDict): values = self._formatMonitorInfo(dataDict) if not values: return strategyId = dataDict["StrategyId"] try: if self.executeListTree.exists(strategyId): self.updateStatus(strategyId, dataDict[5]) return except Exception as e: self._logger.warn("addExecute exception") else: self.executeListTree.insert("", END, iid=strategyId, values=tuple(values), tag=0) def createErr(self): # 错误信息展示 self.errText = ErrorText(self.errRecord, height=20, bd=0) self.errText.createScrollbar() self.errText.pack(fill=BOTH, expand=YES) def updateLogText(self): guiQueue = self._controller.get_logger().getGuiQ() data = "" flag = True try: # data = guiQueue.get_nowait() while flag: data += guiQueue.get_nowait()+"\n" if guiQueue.empty(): flag = False except: return else: self.sysText.setText(data) def updateSigText(self): """更新信号记录""" sigQueue = self._controller.get_logger().getSigQ() sigData = '' flag = True try: # sigData = sigQueue.get_nowait() while flag: sigData += sigQueue.get_nowait()+"\n" if sigQueue.empty(): flag = False except Exception as e: return else: # self.toSigFrame() self.sigText.setText(sigData) def updateUsrText(self): """更新用户日志""" usrQueue = self._controller.get_logger().getUsrQ() usrData = '' flag = True try: while flag: usrData += usrQueue.get_nowait()+"\n" if usrQueue.empty(): flag = False except Exception as e: return else: self.usrText.setText(usrData) def updateErrText(self): errQueue = self._controller.get_logger().getErrQ() try: errData = errQueue.get_nowait() except: return else: self.toErrFrame() self.errText.setText(errData) def clearErrorText(self): self.errText.setText("") def toMonFrame(self): self.runBtn.config(bg="white") self.rColor = self.runBtn['bg'] self.lColor = self.bgColor self.eColor = self.bgColor self.pColor = self.bgColor self.errBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.posBtn.config(bg=self.pColor) self.logRecord.pack_forget() self.errRecord.pack_forget() self.posMonitor.pack_forget() self.executeList.pack(side=TOP, fill=BOTH, expand=YES) # def toLogFrame(self, event, button): # buttons = [self.runBtn, self.logBtn, self.errBtn, self.posBtn] # colors = [self.rColor, self.lColor, self.eColor, self.pColor] # frames = [self.executeList, self.logRecord, self.errRecord, self.posMonitor] # # button.config(bg="white") # index = buttons.index(button) # colors[index] = button['bg'] # frames[index].pack(side=TOP, fill=BOTH, expand=YES) # buttons.remove(button) # colors.remove(colors[index]) # frames.remove(frames[index]) # #TODO:怎么pop呢? # # for btn in buttons: # i = buttons.index(btn) # colors[i] = self.bgColor # btn.config(bg=self.bgColor) # frames[i].pack_forget() def toLogFrame(self): self.logBtn.config(bg="white") self.lColor = self.logBtn['bg'] self.rColor = self.bgColor self.eColor = self.bgColor self.pColor = self.bgColor self.runBtn.config(bg=self.rColor) self.errBtn.config(bg=self.eColor) self.posBtn.config(bg=self.pColor) self.executeList.pack_forget() self.errRecord.pack_forget() self.posMonitor.pack_forget() self.logRecord.pack(side=TOP, fill=BOTH, expand=YES) def toSysFrame(self): self.sysBtn.config(bg="white") self.yColor = self.sysBtn['bg'] self.sColor = self.bgColor self.uColor = self.bgColor self.sigBtn.config(bg=self.sColor) self.usrBtn.config(bg=self.uColor) self.sigRecord.pack_forget() self.usrLog.pack_forget() self.sysLog.pack(side=TOP, fill=BOTH, expand=YES) def toSigFrame(self): self.sigBtn.config(bg="white") self.sColor = self.sigBtn['bg'] self.uColor = self.bgColor self.yColor = self.bgColor self.sysBtn.config(bg=self.yColor) self.usrBtn.config(bg=self.uColor) self.sysLog.pack_forget() self.usrLog.pack_forget() self.sigRecord.pack(side=TOP, fill=BOTH, expand=YES) def toUsrFrame(self): self.usrBtn.config(bg="white") self.uColor = self.sysBtn['bg'] self.sColor = self.bgColor self.yColor = self.bgColor self.sigBtn.config(bg=self.sColor) self.sysBtn.config(bg=self.yColor) self.sigRecord.pack_forget() self.sysLog.pack_forget() self.usrLog.pack(side=TOP, fill=BOTH, expand=YES) def toErrFrame(self): self.errBtn.config(bg="white") self.eColor = self.errBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.pColor = self.bgColor self.runBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.posBtn.config(bg=self.pColor) self.parentFrame.update() self.logRecord.pack_forget() self.executeList.pack_forget() self.posMonitor.pack_forget() self.errRecord.pack(side=TOP, fill=BOTH, expand=YES) def toPosFrame(self): self.posBtn.config(bg="white") self.pColor = self.posBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.eColor = self.bgColor self.runBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.errBtn.config(bg=self.eColor) self.parentFrame.update() self.logRecord.pack_forget() self.executeList.pack_forget() self.errRecord.pack_forget() self.posMonitor.pack(side=TOP, fill=BOTH, expand=YES) def handlerAdaptor(self, fun, **kwargs): return lambda event, fun=fun, kwargs=kwargs: fun(event, **kwargs) def onEnter(self, event, button): """鼠标进入事件""" buttons = [self.runBtn, self.logBtn, self.errBtn, self.posBtn] button.config(bg='white') buttons.remove(button) for btn in buttons: btn.config(bg=self.bgColor) def onLeave(self, event, button): """鼠标离开事件""" buttons = [self.runBtn, self.logBtn, self.errBtn, self.posBtn] #TODO: 类实例作为字典键值有问题! btnColorDict = { self.runBtn: self.rColor, self.logBtn: self.lColor, self.errBtn: self.eColor, self.posBtn: self.pColor } button.config(bg=rgb_to_hex(227, 230, 233)) button['bg'] = btnColorDict[button] buttons.remove(button) for btn in buttons: btn['bg'] = btnColorDict[btn] def deleteStrategy(self, strategyId): """删除策略""" if str(strategyId) in self.executeListTree.get_children(): self.executeListTree.delete(strategyId) self._logger.info(f"[UI][{strategyId}]: Delete strategy {strategyId} successfully!") def updateValue(self, strategyId, dataDict): """更新策略ID对应的运行数据""" colValues = { "#9": "{:.2f}".format(dataDict["Available"]), "#10": "{:.2f}".format(dataDict["MaxRetrace"]), "#11": "{:.2f}".format(dataDict["NetProfit"]), "#12": "{:.2f}".format(dataDict["WinRate"]) } if str(strategyId) in self.executeListTree.get_children(): for k, v in colValues.items(): self.executeListTree.set(strategyId, column=k, value=v) def updateStatus(self, strategyId, status): """更新策略状态""" if str(strategyId) in self.executeListTree.get_children(): self.executeListTree.set(strategyId, column="#6", value=StrategyStatus[status]) def updatePos(self, positions): for itemId in self.posTree.get_children(): self.posTree.delete(itemId) strategyPos = {} accountPos = {} strategyAccount = set() # 重组策略仓 for sid in positions["Strategy"]: for user in positions["Strategy"][sid]: strategyAccount.add(user) if user not in strategyPos: strategyPos.update( { #TODO:结构和下面的不一致 user: positions["Strategy"][sid][user] } ) else: for pCont, pInfo in positions["Strategy"][sid][user].items(): if pCont not in strategyPos[user]: strategyPos[user].update( { pCont: pInfo } ) else: strategyPos[user][pCont]["TotalBuy"] += pInfo["TotalBuy"] strategyPos[user][pCont]["TotalSell"] += pInfo["TotalSell"] strategyPos[user][pCont]["TodayBuy"] += pInfo["TodayBuy"] strategyPos[user][pCont]["TodaySell"] += pInfo["TodaySell"] #print("sssssss: ", strategyPos) # 重组账户仓 for user in positions["Account"]: if user not in strategyAccount: continue if user not in accountPos: accountPos[user] = {} for pCont, pInfo in positions["Account"][user].items(): if pCont[-1] == "T": # 只关注账户中的投机单的持仓 if pCont[:-2] not in accountPos[user]: if pCont[-2] == "S": accountPos[user][pCont[:-2]] = { "TotalSell": pInfo["PositionQty"], "TodaySell": pInfo["PositionQty"] - pInfo["PrePositionQty"], "TotalBuy" : 0, "TodayBuy" : 0 } else: accountPos[user][pCont[:-2]] = { "TotalBuy" : pInfo["PositionQty"], "TodayBuy" : pInfo["PositionQty"] - pInfo["PrePositionQty"], "TotalSell": 0, "TodaySell": 0 } else: if pCont[-2] == "S": accountPos[user][pCont[:-2]]["TotalSell"] += pInfo["PositionQty"] accountPos[user][pCont[:-2]]["TodaySell"] += pInfo["PositionQty"] - pInfo["PrePositionQty"] else: accountPos[user][pCont[:-2]]["TotalBuy"] += pInfo["PositionQty"] accountPos[user][pCont[:-2]]["TodayBuy"] += pInfo["PositionQty"] - pInfo["PrePositionQty"] #print("tttttttttt: ", accountPos) rlt = [] for user in strategyAccount: for c, p in strategyPos[user].items(): if user in accountPos: if c in accountPos[user]: aTPos = accountPos[user][c]["TotalBuy"] - (-accountPos[user][c]["TotalSell"]) # 账户仓 sTPos = p["TotalBuy"] - (-p["TotalSell"]) # 策略仓 posDif = sTPos - aTPos # 仓差 rlt.append([user, c, aTPos, sTPos, posDif, p["TotalBuy"], p["TotalSell"], p["TodayBuy"], p["TodaySell"], accountPos[user][c]["TotalBuy"], accountPos[user][c]["TotalSell"], accountPos[user][c]["TodayBuy"], accountPos[user][c]["TodaySell"]]) continue rlt.append([user, c, 0, p["TotalBuy"] - (-p["TotalSell"]), p["TotalBuy"] - (-p["TotalSell"]), p["TotalBuy"], p["TotalSell"], p["TodayBuy"], p["TodaySell"], 0, 0, 0, 0]) # print("BBBBBBBBBBB: ", rlt) for v in rlt: self.posTree.insert("", 'end', values=v)
class FullScreenWindow: def __init__(self): self.dbManager = DatabaseManager('DBSystem') self.btManager = BluetoothManager() self.initUi() def initUi(self): self.tk = Tk() self.tk.geometry("480x320") self.tk.title( "Sistema de Precisión Mixológica para la Preparación de Bebidas Alcohólicas" ) #~ self.tk.attributes("-zoomed", True)#PARA TRABAJAR EN LCD self.tk.attributes("-zoomed", False) #PARA TRABAJAR EN HDMI self.tk.attributes("-fullscreen", False) self.tk.configure(bg="#eaebf1") self.tk.protocol("WM_DELETE_WINDOW", self.btManager.Close) #FRAME PRINCIPAL self.labelBienvenida = Label(self.tk, text="Bienvenido") self.labelBienvenida.configure(bg="#eaebf1") self.labelBienvenida.pack() self.framePrincipal = Frame(self.tk) self.framePrincipal.configure(bg="#eaebf1") self.framePrincipal.pack(fill=BOTH, expand=1) self.btn1 = Button(self.framePrincipal, text="Admin", command=self.AdminVentana, height=5, width=10) self.btn2 = Button(self.framePrincipal, text="User", command=self.UserVentana, height=5, width=10) self.btn1.grid(column=0, row=0, padx=80, pady=40) self.btn2.grid(column=1, row=0, padx=10, pady=40) self.btn1.configure(bg="#f1f0ea") self.btn2.configure(bg="#f1f0ea") self.state = False self.tk.bind("<F11>", self.toggle_fullscreen) self.tk.bind("<Escape>", self.end_fullscreen) #FRAME USUARIO self.diccionarioPedido = { } # { "Nombre de bebida unico" : cantidad de bebida } self.frameUser = Frame(self.tk) self.frameUser.configure(bg="#eaebf1") self.labelUser = Label(self.tk, text="Realiza tu pedido") self.labelUser.configure(bg="#eaebf1") self.labelBebidasDisponibles = Label(self.frameUser, text="Bebidas Disponibles") self.labelBebidasDisponibles.grid(row=0, column=0) self.labelBebidasDisponibles.configure(bg="#eaebf1") self.listboxBebidasDisponibles = Listbox(self.frameUser, height=6, width=18) self.listboxBebidasDisponibles.grid(row=1, column=0) self.scrollList = Scrollbar( self.frameUser, command=self.listboxBebidasDisponibles.yview) self.scrollList.grid(row=1, column=1, sticky="nesw") self.listboxBebidasDisponibles.config( yscrollcommand=self.scrollList.set) self.labelIngredientes = Label(self.frameUser, text="Ingredientes") self.labelIngredientes.grid(row=0, column=2) self.labelIngredientes.configure(bg="#eaebf1") self.listboxIngredientes = Listbox(self.frameUser, height=6, width=15) self.listboxIngredientes.grid(row=1, column=2, padx=15) self.labelPedido = Label(self.frameUser, text="Pedido") self.labelPedido.grid(row=0, column=3, padx=10) self.labelPedido.configure(bg="#eaebf1") self.listboxPedido = Listbox(self.frameUser, height=6, width=18) self.listboxPedido.grid(row=1, column=3) self.scrollList = Scrollbar(self.frameUser, command=self.listboxPedido.yview) self.scrollList.grid(row=1, column=4, sticky="nesw") self.listboxPedido.config(yscrollcommand=self.scrollList.set) self.labelCantidad = Label(self.frameUser, text="Cantidad") self.labelCantidad.grid(row=2, column=0) self.labelCantidad.configure(bg="#eaebf1") self.txtCantidadBebidas = Entry(self.frameUser, width=16) self.txtCantidadBebidas.grid(row=3, column=0) self.btnAgregar = Button(self.frameUser, text="Agregar", height=5, width=10, command=self.AgregarBebidaPedido) self.btnVolverUser = Button( self.frameUser, text="Volver", height=5, width=10, command=lambda: self.PrincipalVolver(False)) self.btnVolverUser.grid(column=3, row=4, pady=10) self.btnRealizarPedido = Button(self.frameUser, text="Realizar Pedido", height=5, width=10, command=self.RealizarPedido) self.btnAgregar.grid(column=0, row=4, pady=10) self.btnRealizarPedido.grid(column=2, row=4, pady=10) self.listboxBebidasDisponibles.bind( "<<ListboxSelect>>", lambda y: self.VerBebida(self.listboxIngredientes)) self.listboxPedido.bind("<Double-Button-1>", lambda x: self.EliminarItemPedido()) #<<ListboxSelect>> #FRAME ADMIN self.frameAdmin = Frame(self.tk) self.labelAdmin = Label(self.tk, text="Admin") self.labelAdmin.configure(bg="#eaebf1") self.frameAdmin.configure(bg="#eaebf1") self.textoVaciadoContenedores = """Vaciado de Contenedores""" self.btnContenedores = Button(self.frameAdmin, text="Contenedores", command=self.ContenedorVentana, height=5, width=10) self.btnVaciadoContenedores = Button( self.frameAdmin, text=self.textoVaciadoContenedores, command=self.VaciadoContenedorVentana, height=5, width=10) self.btnRecetas = Button(self.frameAdmin, text="Recetas", command=self.RecetasVentana, height=5, width=10) self.btnContenedores.grid(column=0, row=0, padx=23, pady=40) self.btnRecetas.grid(column=1, row=0, padx=23, pady=40) self.btnVaciadoContenedores.grid(column=2, row=0, padx=23, pady=40) self.btnVolverPrincipal = Button( self.frameAdmin, text="Volver", command=lambda: self.PrincipalVolver(True)) self.btnVolverPrincipal.grid(column=2, row=1) #FRAME RECETA self.frameReceta = Frame(self.tk) self.listboxRecetasGeneral = Listbox(self.frameReceta) self.labelReceta = Label(self.tk, text="Recetas") self.labelReceta.configure(bg="#eaebf1") self.frameReceta.configure(bg="#eaebf1") self.textoBotonEliminarReceta = """Eliminar Receta """ self.textoBotonEditarReceta = """Editar Receta """ self.textoBotonVerReceta = """Ver Receta """ self.textoBotonCrearReceta = """Crear Receta """ self.btnVerReceta = Button( self.frameReceta, text=self.textoBotonVerReceta, command=lambda: self.VerReceta(self.diccionarioListaGeneral[ self.listboxRecetasGeneral.get(ACTIVE)]), height=5, width=5) self.btnEditarReceta = Button( self.frameReceta, text=self.textoBotonEditarReceta, command=lambda: self.RecetasEditarReceta( self.diccionarioListaGeneral[self.listboxRecetasGeneral.get( ACTIVE)]), height=5, width=5) self.btnEliminarReceta = Button(self.frameReceta, text=self.textoBotonEliminarReceta, command=self.EliminarReceta, height=5, width=5) self.btnCrearReceta = Button(self.frameReceta, text=self.textoBotonCrearReceta, command=self.RecetasCrearReceta, height=5, width=5) self.btnVolverAdmin = Button(self.frameReceta, text="Volver", command=self.AdminVolver) self.btnVerReceta.grid(column=0, row=0, padx=5) self.btnEditarReceta.grid(column=1, row=0, padx=5) self.btnEliminarReceta.grid(column=2, row=0, padx=5) self.btnVolverAdmin.grid(column=3, row=1, pady=10) self.btnCrearReceta.grid(column=0, row=1, padx=5) self.listboxRecetasGeneral.grid(column=3, row=0) self.scrollList = Scrollbar(self.frameReceta, command=self.listboxRecetasGeneral.yview) self.scrollList.grid(column=4, row=0, sticky="nesw") self.listboxRecetasGeneral.config(yscrollcommand=self.scrollList.set) #~ self.listBox.insert(END,'ELEMENTO1') #FRAME RECETA-CREAR #Array para llevar la logica para crear la receta que basicamente poseera ingrediente id.ingrediente y cantidad self.frameRecetaCrear = Frame(self.tk) self.diccionarioIngredientes = {} self.labelRecetaCrear = Label(self.tk, text="Crear Receta") self.labelRecetaCrear.configure(bg="#eaebf1") self.frameRecetaCrear.configure(bg="#eaebf1") self.labelIngredientesCrear = Label(self.frameRecetaCrear, text="Ingredientes") self.labelCantidadCrear = Label(self.frameRecetaCrear, text="Cantidad") self.labelRecetaActualCrear = Label(self.frameRecetaCrear, text="Receta Actual") self.labelRecetaNombreCrear = Label(self.frameRecetaCrear, text="Nombre de la Receta") self.labelIngredientesCrear.configure(bg="#eaebf1") self.labelCantidadCrear.configure(bg="#eaebf1") self.labelRecetaActualCrear.configure(bg="#eaebf1") self.labelRecetaNombreCrear.configure(bg="#eaebf1") self.labelIngredientesCrear.grid(row=0, column=0, padx=5) self.labelCantidadCrear.grid(row=0, column=1) self.labelRecetaActualCrear.grid(row=0, column=2) self.labelRecetaNombreCrear.grid(row=2, column=0) self.comboIngredientesCrear = ttk.Combobox(self.frameRecetaCrear, width=16, state="readonly") self.comboIngredientesCrear.grid(row=1, column=0, padx=2, sticky=N) self.vcmd = (self.tk.register(self.validate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') self.txtCantidadCrear = Entry(self.frameRecetaCrear, width=16, validate='key', validatecommand=self.vcmd) self.txtRecetaNombreCrear = Entry(self.frameRecetaCrear, width=16) self.txtCantidadCrear.grid(row=1, column=1, padx=2, sticky=N) self.txtRecetaNombreCrear.grid(row=3, column=0) self.txtCantidadCrear.bind("<FocusIn>", lambda x: self.AbrirTeclado()) self.txtRecetaNombreCrear.bind("<FocusIn>", lambda x: self.AbrirTeclado()) self.listBoxRecetaActualCrear = Listbox(self.frameRecetaCrear, height=6) self.listBoxRecetaActualCrear.grid(row=1, column=2) #~ self.listBoxRecetaActualCrear.bind("<Double-Button-1>", lambda: self.EliminarItemListbox(self.listBoxRecetaActualCrear)) self.listBoxRecetaActualCrear.bind( "<Double-Button-1>", lambda x: self.EliminarItemListbox(self.listBoxRecetaActualCrear)) #~ command=lambda:self.clicked('Eliminar \n' + 'Receta') self.btnVolverRecetaCrear = Button( self.frameRecetaCrear, text="Volver", command=lambda: self.RecetasVolver(1)) self.btnVolverRecetaCrear.grid(row=4, column=2) #BOTON AGREGAR ------------------------------------------------------------ self.btnAgregarRecetaCrear = Button( self.frameRecetaCrear, text="Agregar", command=lambda: self.AgregarIngrediente( self.comboIngredientesCrear.get(), self.txtCantidadCrear.get(), self.listBoxRecetaActualCrear)) self.btnAgregarRecetaCrear.grid(row=4, column=1) #BOTON CREAR ------------------------------------------------------------------- self.btnCrearRecetaCrear = Button(self.frameRecetaCrear, text="Crear Receta", command=self.CrearReceta, width=55) self.btnCrearRecetaCrear.grid(row=5, column=0, columnspan=3, pady=8) #FRAME RECETA-EDITAR #Array para llevar la logica para crear la receta que basicamente poseera ingrediente id.ingrediente y cantidad self.frameRecetaEditar = Frame(self.tk) self.labelRecetaEditar = Label(self.tk, text="Editar Receta") self.labelRecetaEditar.configure(bg="#eaebf1") self.frameRecetaEditar.configure(bg="#eaebf1") self.labelIngredientesEditar = Label(self.frameRecetaEditar, text="Ingredientes") self.labelCantidadEditar = Label(self.frameRecetaEditar, text="Cantidad") self.labelRecetaActualEditar = Label(self.frameRecetaEditar, text="Receta Actual") self.labelRecetaNombreEditar = Label(self.frameRecetaEditar, text="Nombre de la Receta") self.labelIngredientesEditar.configure(bg="#eaebf1") self.labelCantidadEditar.configure(bg="#eaebf1") self.labelRecetaActualEditar.configure(bg="#eaebf1") self.labelRecetaNombreEditar.configure(bg="#eaebf1") self.labelIngredientesEditar.grid(row=0, column=0, padx=5) self.labelCantidadEditar.grid(row=0, column=1) self.labelRecetaActualEditar.grid(row=0, column=2) self.labelRecetaNombreEditar.grid(row=2, column=0) self.comboIngredientesEditar = ttk.Combobox(self.frameRecetaEditar, width=16, state="readonly") self.comboIngredientesEditar.grid(row=1, column=0, padx=2, sticky=N) self.txtCantidadEditar = Entry(self.frameRecetaEditar, width=16, validate='key', validatecommand=self.vcmd) self.txtRecetaNombreEditar = Entry(self.frameRecetaEditar, width=16) self.txtCantidadEditar.grid(row=1, column=1, padx=2, sticky=N) self.txtRecetaNombreEditar.grid(row=3, column=0) self.listBoxRecetaActualEditar = Listbox(self.frameRecetaEditar, height=6) self.listBoxRecetaActualEditar.grid(row=1, column=2) self.btnVolverRecetaEditar = Button( self.frameRecetaEditar, text="Volver", command=lambda: self.RecetasVolver(2)) self.btnVolverRecetaEditar.grid(row=4, column=2) self.listBoxRecetaActualEditar.bind( "<Double-Button-1>", lambda x: self.EliminarItemListbox(self.listBoxRecetaActualEditar)) #BOTON AGREGAR ------------------------------------------------------------ self.btnAgregarRecetaEditar = Button( self.frameRecetaEditar, text="Agregar", command=lambda: self.AgregarIngrediente( self.comboIngredientesEditar.get(), self.txtCantidadEditar.get( ), self.listBoxRecetaActualEditar)) self.btnAgregarRecetaEditar.grid(row=4, column=1) #BOTON CREAR ------------------------------------------------------------------- self.btnEditarRecetaEditar = Button(self.frameRecetaEditar, text="Editar Receta", command=self.EditarReceta, width=55) self.btnEditarRecetaEditar.grid(row=5, column=0, columnspan=3, pady=8) #FRAME RECETA-VER self.textoLabelVer = StringVar() self.frameRecetaVer = Frame(self.tk) self.labelRecetaVer = Label(self.tk, text="Ver Receta") self.labelRecetaVer.configure(bg="#eaebf1") self.frameRecetaVer.configure(bg="#eaebf1") self.labelNombreReceta = Label(self.frameRecetaVer, text="Nombre de la Receta:", anchor="center") self.labelNombreReceta.grid(row=0, column=0, padx=30) self.labelNombreRecetaReal = Label(self.frameRecetaVer, text="aqui se ve el nombre", textvariable=self.textoLabelVer, height=15, wraplength=150, padx=20) self.labelNombreRecetaReal.grid(row=1, column=0, padx=30) self.labelIngredientesVer = Label(self.frameRecetaVer, text="Ingredientes") self.labelIngredientesVer.grid(row=0, column=3, padx=55, columnspan=2) self.listBoxRecetaVer = Listbox(self.frameRecetaVer, height=6) self.listBoxRecetaVer.grid(row=1, column=3, sticky="e", columnspan=2, padx=55) self.labelNombreReceta.configure(bg="#eaebf1") self.labelNombreRecetaReal.configure(bg="#eaebf1") self.labelIngredientesVer.configure(bg="#eaebf1") self.btnVolverRecetaVer = Button(self.frameRecetaVer, text="Volver", command=lambda: self.RecetasVolver(3)) self.btnVolverRecetaVer.grid(row=4, column=4) #FRAME CONTENEDOR self.contenedor1Nombre = StringVar() self.contenedor2Nombre = StringVar() self.contenedor3Nombre = StringVar() self.contenedor4Nombre = StringVar() self.contenedor5Nombre = StringVar() self.contenedor6Nombre = StringVar() self.frameContenedor = Frame(self.tk) self.labelContenedor1 = Label(self.frameContenedor, text="Contenedor 1") self.labelContenedor1.grid(column=0, row=1) self.labelContenedor2 = Label(self.frameContenedor, text="Contenedor 2") self.labelContenedor2.grid(column=0, row=2) self.labelContenedor3 = Label(self.frameContenedor, text="Contenedor 3") self.labelContenedor3.grid(column=0, row=3) self.labelContenedor4 = Label(self.frameContenedor, text="Contenedor 4") self.labelContenedor4.grid(column=0, row=4) self.labelContenedor5 = Label(self.frameContenedor, text="Contenedor 5") self.labelContenedor5.grid(column=0, row=5) self.labelContenedor6 = Label(self.frameContenedor, text="Contenedor 6") self.labelContenedor6.grid(column=0, row=6) self.TextBoxContenedor1 = Entry(self.frameContenedor, textvariable=self.contenedor1Nombre) self.TextBoxContenedor1.grid(column=1, row=1) self.TextBoxContenedor2 = Entry(self.frameContenedor, textvariable=self.contenedor2Nombre) self.TextBoxContenedor2.grid(column=1, row=2) self.TextBoxContenedor3 = Entry(self.frameContenedor, textvariable=self.contenedor3Nombre) self.TextBoxContenedor3.grid(column=1, row=3) self.TextBoxContenedor4 = Entry(self.frameContenedor, textvariable=self.contenedor4Nombre) self.TextBoxContenedor4.grid(column=1, row=4) self.TextBoxContenedor5 = Entry(self.frameContenedor, textvariable=self.contenedor5Nombre) self.TextBoxContenedor5.grid(column=1, row=5) self.TextBoxContenedor6 = Entry(self.frameContenedor, textvariable=self.contenedor6Nombre) self.TextBoxContenedor6.grid(column=1, row=6) self.btn4 = Button(self.frameContenedor, text="Guardar Cambios", command=self.ActualizarContenedores) self.btn4.grid(column=2, row=7) self.btn3 = Button(self.frameContenedor, text="Volver", command=self.AdminVolver) self.btn3.grid(column=2, row=0) self.TextBoxContenedor1.bind("<FocusIn>", lambda x: self.AbrirTeclado()) self.TextBoxContenedor2.bind("<FocusIn>", lambda x: self.AbrirTeclado()) self.TextBoxContenedor3.bind("<FocusIn>", lambda x: self.AbrirTeclado()) self.TextBoxContenedor4.bind("<FocusIn>", lambda x: self.AbrirTeclado()) self.TextBoxContenedor5.bind("<FocusIn>", lambda x: self.AbrirTeclado()) self.TextBoxContenedor6.bind("<FocusIn>", lambda x: self.AbrirTeclado()) #~ self.hilo1.terminate() #FRAME VACIADO CONTENEDOR self.frameVaciadoContenedor = Frame(self.tk) self.labelVaciadoContenedor1 = Label(self.frameVaciadoContenedor, text="Contenedor 1") self.labelVaciadoContenedor1.grid(column=0, row=1) self.labelVaciadoContenedor2 = Label(self.frameVaciadoContenedor, text="Contenedor 2") self.labelVaciadoContenedor2.grid(column=0, row=2) self.labelVaciadoContenedor3 = Label(self.frameVaciadoContenedor, text="Contenedor 3") self.labelVaciadoContenedor3.grid(column=0, row=3) self.labelVaciadoContenedor4 = Label(self.frameVaciadoContenedor, text="Contenedor 4") self.labelVaciadoContenedor4.grid(column=0, row=4) self.labelVaciadoContenedor5 = Label(self.frameVaciadoContenedor, text="Contenedor 5") self.labelVaciadoContenedor5.grid(column=0, row=5) self.labelVaciadoContenedor6 = Label(self.frameVaciadoContenedor, text="Contenedor 6") self.labelVaciadoContenedor6.grid(column=0, row=6) self.btnVolverVaciado = Button(self.frameVaciadoContenedor, text="Volver", command=self.AdminVolver) self.btnVolverVaciado.grid(column=2, row=0) self.TextBoxVaciadoContenedor1 = Entry(self.frameVaciadoContenedor) self.TextBoxVaciadoContenedor1.grid(column=1, row=1) self.TextBoxVaciadoContenedor2 = Entry(self.frameVaciadoContenedor) self.TextBoxVaciadoContenedor2.grid(column=1, row=2) self.TextBoxVaciadoContenedor3 = Entry(self.frameVaciadoContenedor) self.TextBoxVaciadoContenedor3.grid(column=1, row=3) self.TextBoxVaciadoContenedor4 = Entry(self.frameVaciadoContenedor) self.TextBoxVaciadoContenedor4.grid(column=1, row=4) self.TextBoxVaciadoContenedor5 = Entry(self.frameVaciadoContenedor) self.TextBoxVaciadoContenedor5.grid(column=1, row=5) self.TextBoxVaciadoContenedor6 = Entry(self.frameVaciadoContenedor) self.TextBoxVaciadoContenedor6.grid(column=1, row=6) self.rbOpcionVaciado = IntVar() self.rbContenedor1 = Radiobutton(self.frameVaciadoContenedor, text=" ", variable=self.rbOpcionVaciado, value=1, command=self.MostarV, indicatoron=False) self.rbContenedor2 = Radiobutton(self.frameVaciadoContenedor, text=" ", variable=self.rbOpcionVaciado, value=2, command=self.MostarV, indicatoron=False) self.rbContenedor3 = Radiobutton(self.frameVaciadoContenedor, text=" ", variable=self.rbOpcionVaciado, value=3, command=self.MostarV, indicatoron=False) self.rbContenedor4 = Radiobutton(self.frameVaciadoContenedor, text=" ", variable=self.rbOpcionVaciado, value=4, command=self.MostarV, indicatoron=False) self.rbContenedor5 = Radiobutton(self.frameVaciadoContenedor, text=" ", variable=self.rbOpcionVaciado, value=5, command=self.MostarV, indicatoron=False) self.rbContenedor6 = Radiobutton(self.frameVaciadoContenedor, text=" ", variable=self.rbOpcionVaciado, value=6, command=self.MostarV, indicatoron=False) self.rbContenedor1.grid(column=2, row=1) self.rbContenedor2.grid(column=2, row=2) self.rbContenedor3.grid(column=2, row=3) self.rbContenedor4.grid(column=2, row=4) self.rbContenedor5.grid(column=2, row=5) self.rbContenedor6.grid(column=2, row=6) self.btnVaciado = Button(self.frameVaciadoContenedor, text="Vaciar", command=self.AdminVolver, height=5, width=10) self.btnVaciado.grid(column=3, row=7) self.labelContenedor1ml = Label(self.frameVaciadoContenedor, text="1200 ml") self.labelContenedor1ml.grid(column=3, row=1) self.labelContenedor2ml = Label(self.frameVaciadoContenedor, text="1200 ml") self.labelContenedor2ml.grid(column=3, row=2) self.labelContenedor3ml = Label(self.frameVaciadoContenedor, text="1200 ml") self.labelContenedor3ml.grid(column=3, row=3) self.labelContenedor4ml = Label(self.frameVaciadoContenedor, text="1200 ml") self.labelContenedor4ml.grid(column=3, row=4) self.labelContenedor5ml = Label(self.frameVaciadoContenedor, text="1200 ml") self.labelContenedor5ml.grid(column=3, row=5) self.labelContenedor6ml = Label(self.frameVaciadoContenedor, text="1200 ml") self.labelContenedor6ml.grid(column=3, row=6) def TecladoVirtual(self): self.hiloVentana = subprocess.call("/usr/bin/matchbox-keyboard", shell=False) def MostrarXs(self, segs=5): while True: sleep(segs) print("Han pasado %d segundos" % segs) def AbrirTeclado(self, event=None): self.hilo1 = threading.Thread(target=self.TecladoVirtual) self.hilo1.start() def clicked(self, t): self.admin = Toplevel(self.tk) self.admin.title(t) print(t) def AdminVentana(self): self.labelBienvenida.pack_forget() self.framePrincipal.pack_forget() self.labelAdmin.pack() self.frameAdmin.pack(fill=BOTH, expand=1) def UserVentana(self): self.LogicaListaGeneral(self.listboxBebidasDisponibles) self.labelBienvenida.pack_forget() self.framePrincipal.pack_forget() self.labelUser.pack() self.frameUser.pack(fill=BOTH, expand=1) self.listboxIngredientes.delete(0, END) receta = self.listboxBebidasDisponibles.get(ACTIVE) id = self.diccionarioListaGeneral[receta] temp = self.dbManager.VerReceta(id) for nombre, cantidad, caracterEspecial in temp["Ingredientes"]: self.diccionarioIngredientes[nombre] = cantidad self.MostrarIngredientes(self.listboxIngredientes) self.diccionarioIngredientes = {} def LogicaListaGeneral(self, lista): self.listboxRecetasGeneral.delete(0, 'end') self.diccionarioListaGeneral = self.dbManager.ObtenerRecetas() print(self.diccionarioListaGeneral) for i in self.diccionarioListaGeneral: lista.insert(END, i) def RecetasVentana(self): self.LogicaListaGeneral(self.listboxRecetasGeneral) self.labelAdmin.pack_forget() self.frameAdmin.pack_forget() self.labelReceta.pack() self.frameReceta.pack() #Se nos paso colocar fill=BOTH,expand=1 #por lo tanto este frame no sigue los estandares de diseño del resto def RecetasCrearReceta(self): self.labelReceta.pack_forget() self.frameReceta.pack_forget() self.labelRecetaCrear.pack() self.frameRecetaCrear.pack(fill=BOTH, expand=1) ingredientes = self.dbManager.ObtenerIngredientes() self.diccionarioIngredientesCrear = { ingredientes[0][1]: ingredientes[0][0], ingredientes[1][1]: ingredientes[1][0], ingredientes[2][1]: ingredientes[2][0], ingredientes[3][1]: ingredientes[3][0], ingredientes[4][1]: ingredientes[4][0], ingredientes[5][1]: ingredientes[5][0] } print(self.diccionarioIngredientesCrear) print("##### Arriba self.diccionarioIngredientesCrear #####") self.comboIngredientesCrear['values'] = (ingredientes[0][1], ingredientes[1][1], ingredientes[2][1], ingredientes[3][1], ingredientes[4][1], ingredientes[5][1]) self.comboIngredientesCrear.current(0) def RecetasEditarReceta(self, id): self.RecetaId = id temp = self.dbManager.VerReceta(id) #~ self.diccionarioIngredientes self.txtRecetaNombreEditar.delete(0, END) self.txtRecetaNombreEditar.insert(0, temp["Receta"]) for nombre, cantidad, caracter in temp["Ingredientes"]: self.diccionarioIngredientes[nombre] = cantidad self.MostrarIngredientes(self.listBoxRecetaActualEditar) print(self.diccionarioIngredientes) self.labelReceta.pack_forget() self.frameReceta.pack_forget() self.labelRecetaEditar.pack() self.frameRecetaEditar.pack(fill=BOTH, expand=1) ingredientes = self.dbManager.ObtenerIngredientes() self.diccionarioIngredientesCrear = { ingredientes[0][1]: ingredientes[0][0], ingredientes[1][1]: ingredientes[1][0], ingredientes[2][1]: ingredientes[2][0], ingredientes[3][1]: ingredientes[3][0], ingredientes[4][1]: ingredientes[4][0], ingredientes[5][1]: ingredientes[5][0] } self.comboIngredientesEditar['values'] = (ingredientes[0][1], ingredientes[1][1], ingredientes[2][1], ingredientes[3][1], ingredientes[4][1], ingredientes[5][1]) self.comboIngredientesEditar.current(0) def VaciadoContenedorVentana(self): self.labelBienvenida.pack_forget() self.frameAdmin.pack_forget() self.labelAdmin.pack_forget() self.frameVaciadoContenedor.pack(fill=BOTH, expand=1) ingredientes = self.dbManager.ObtenerIngredientes() #~ self.comboIngredientesCrear['values'] = (ingredientes[0][1],ingredientes[1][1],ingredientes[2][1],ingredientes[3][1],ingredientes[4][1],ingredientes[5][1]) self.labelVaciadoContenedor1['text'] = ingredientes[0][1] self.labelVaciadoContenedor2['text'] = ingredientes[1][1] self.labelVaciadoContenedor3['text'] = ingredientes[2][1] self.labelVaciadoContenedor4['text'] = ingredientes[3][1] self.labelVaciadoContenedor5['text'] = ingredientes[4][1] self.labelVaciadoContenedor6['text'] = ingredientes[5][1] def ContenedorVentana(self): self.labelBienvenida.pack_forget() contenedores = self.dbManager.Select('Contenedores') print(contenedores) self.contenedor1Nombre.set(contenedores[0][1]) self.contenedor2Nombre.set(contenedores[1][1]) self.contenedor3Nombre.set(contenedores[2][1]) self.contenedor4Nombre.set(contenedores[3][1]) self.contenedor5Nombre.set(contenedores[4][1]) self.contenedor6Nombre.set(contenedores[5][1]) self.frameAdmin.pack_forget() self.labelAdmin.pack_forget() self.frameContenedor.pack(fill=BOTH, expand=1) def VerReceta(self, id): temp = self.dbManager.VerReceta(id) for nombre, cantidad, caracter in temp["Ingredientes"]: self.diccionarioIngredientes[nombre] = cantidad self.MostrarIngredientes(self.listBoxRecetaVer) self.textoLabelVer.set(temp["Receta"]) self.labelReceta.pack_forget() self.frameReceta.pack_forget() self.labelRecetaVer.pack() self.frameRecetaVer.pack(fill=BOTH, expand=1) #CRUD RECETAS def EliminarItemListbox(self, lista): texto = lista.get(ACTIVE) busqueda = texto.find(" " + chr(0), 0, len(texto)) key = texto[:busqueda] del self.diccionarioIngredientes[key] print(self.diccionarioIngredientes) lista.delete(ACTIVE) def EliminarReceta(self): receta = self.listboxRecetasGeneral.get(ACTIVE) id = self.diccionarioListaGeneral[receta] self.dbManager.EliminarReceta(id) self.diccionarioListaGeneral = {} self.LogicaListaGeneral(self.listboxRecetasGeneral) def VerBebida(self, lista): lista.delete(0, END) receta = self.listboxBebidasDisponibles.get(ACTIVE) id = self.diccionarioListaGeneral[receta] temp = self.dbManager.VerReceta(id) for nombre, cantidad, k in temp["Ingredientes"]: self.diccionarioIngredientes[nombre] = cantidad self.MostrarIngredientes(lista) self.diccionarioIngredientes = {} return def MostrarIngredientes(self, lista): lista.delete(0, 'end') for i in self.diccionarioIngredientes: ingredientecantidad = i + " " + chr(0) + " " + str( self.diccionarioIngredientes[i]) print(ingredientecantidad) lista.insert('end', ingredientecantidad) def AgregarIngrediente(self, ingrediente, cantidad, lista): if len(cantidad) == 0: return self.diccionarioIngredientes[ingrediente] = cantidad print(self.diccionarioIngredientes) print("Arriba se mostro diccionarioIngredientes") self.MostrarIngredientes(lista) def EditarReceta(self): if len(self.diccionarioIngredientes) == 0: messagebox.showerror( "Error", "No se puede crear una receta sin ingredientes.") return False if len(self.txtRecetaNombreEditar.get()) == 0: messagebox.showerror( "Error", "Debe ingresar el nombre de la receta antes de continuar.") return False if self.dbManager.VerificarNombreEditar( self.RecetaId, self.txtRecetaNombreEditar.get()) == False: messagebox.showerror("Error", "Ya existe una receta con ese nombre.") return False self.dbManager.ActualizarNombreReceta(self.txtRecetaNombreEditar.get(), self.RecetaId) self.dbManager.EliminarTodosIngredientes(self.RecetaId) dicc = {} #DICCIONARIO PARA AGREGAR LOS INGREDIENTES DE LA RECETA print(self.diccionarioIngredientesCrear) print("##############################") for i in self.diccionarioIngredientes: #CICLO PARA RELLENAR DICCIONARIO print(i) print("########################") dicc[self.diccionarioIngredientesCrear[ i]] = self.diccionarioIngredientes[i] print(dicc) print("Arriba impreso dicc") self.dbManager.AgregarIngrediente(dicc, self.RecetaId) messagebox.showinfo( "Tarea Realizada", "La receta %s ha sido actualizada correctamente." % self.txtRecetaNombreEditar.get()) self.diccionarioIngredientes = {} self.txtCantidadEditar.config(validate="none") self.txtCantidadEditar.delete(0, END) self.txtRecetaNombreEditar.delete(0, END) self.listBoxRecetaActualEditar.delete(0, 'end') self.txtCantidadEditar.config(validate='key') self.RecetasVolver(2) return def CrearReceta(self): if len(self.diccionarioIngredientes) == 0: messagebox.showerror( "Error", "No se puede crear una receta sin ingredientes.") return False if len(self.txtRecetaNombreCrear.get()) == 0: messagebox.showerror( "Error", "Debe ingresar el nombre de la receta antes de continuar.") return False recetaId = self.dbManager.CrearReceta( self.txtRecetaNombreCrear.get()) #CREAMOS LA RECETA if recetaId == False: messagebox.showerror("Error", "Ya existe una receta con ese nombre.") return False dic = {} #DICCIONARIO PARA AGREGAR LOS INGREDIENTES DE LA RECETA for i in self.diccionarioIngredientes: #CICLO PARA RELLENAR DICCIONARIO dic[self.diccionarioIngredientesCrear[ i]] = self.diccionarioIngredientes[i] print(dic) print("Arriba impreso dic") self.dbManager.AgregarIngrediente(dic, recetaId) #~ self.diccionarioIngredientesCrear messagebox.showinfo( "Tarea Realizada", "La receta %s ha sido creada correctamente." % self.txtRecetaNombreCrear.get()) self.diccionarioIngredientes = {} self.txtCantidadCrear.config(validate="none") self.txtCantidadCrear.delete(0, END) self.txtRecetaNombreCrear.delete(0, END) self.listBoxRecetaActualCrear.delete(0, 'end') self.txtCantidadCrear.config(validate='key') self.RecetasVolver(True) def RecetasVolver(self, i): self.LogicaListaGeneral(self.listboxRecetasGeneral) self.diccionarioIngredientes = {} if i == 1: self.labelRecetaCrear.pack_forget() self.frameRecetaCrear.pack_forget() elif i == 2: self.labelRecetaEditar.pack_forget() self.frameRecetaEditar.pack_forget() else: self.labelRecetaVer.pack_forget() self.frameRecetaVer.pack_forget() self.labelReceta.pack() self.frameReceta.pack(fill=BOTH, expand=1) def AdminVolver(self): self.frameContenedor.pack_forget() self.frameReceta.pack_forget() self.frameVaciadoContenedor.pack_forget() #~ self.frameVaciadoContenedor.pack_forget() self.labelReceta.pack_forget() self.labelAdmin.pack() self.frameAdmin.pack(fill=BOTH, expand=1) #~ def AdminVolverVaciado(self): #~ self.frameContenedor.pack_forget() #~ self.frameReceta.pack_forget() #~ self.labelReceta.pack_forget() #~ self.labelAdmin.pack() #~ self.frameAdmin.pack(fill=BOTH,expand=1) def PrincipalVolver(self, isAdmin): if isAdmin: self.frameAdmin.pack_forget() self.labelAdmin.pack_forget() else: self.frameUser.pack_forget() self.labelUser.pack_forget() self.labelBienvenida.pack() self.framePrincipal.pack(fill=BOTH, expand=1) def ActualizarContenedores(self): contenedores = [ self.contenedor1Nombre.get(), self.contenedor2Nombre.get(), self.contenedor3Nombre.get(), self.contenedor4Nombre.get(), self.contenedor5Nombre.get(), self.contenedor6Nombre.get() ] print(len(contenedores)) print(len(set(contenedores))) if (len(contenedores) == len(set(contenedores))): self.dbManager.ActualizarContenedores(contenedores) else: print("iguales") messagebox.showerror( "Error", "NO pueden existir dos ingredientes con el mismo nombre") return def MostarV(self): print(self.rbOpcionVaciado.get()) def RealizarPedido(self): print("Entramos en REALIZAR PEDIDO") trama = "" + chr(1) #Inicio de trama 3 print(self.diccionarioPedido) for NombreReceta in self.diccionarioPedido.keys(): print("Iniciamos primer for") id = self.diccionarioListaGeneral[NombreReceta] receta = self.dbManager.VerReceta(id) for contenedor, cant, caracter in receta["Ingredientes"]: #~ el separador entre contenedor y cantidad viene siendo donde esta chr(0) print("Muestro caracter") print(caracter) trama += caracter + chr(29) + str(cant) + chr(29) trama += chr(7) + str(self.diccionarioPedido[NombreReceta]) + chr( 8) #Aqui agregamos final de receta 1 trama += chr(4) # fin de transmision 2 print(trama) self.btManager.Send(trama) #~ self.diccionarioPedido {Nombre receta : cantidad} #~ self.diccionarioListaGeneral {Nombre receta : id} def AgregarBebidaPedido(self): self.diccionarioPedido[self.listboxBebidasDisponibles.get( ACTIVE)] = self.txtCantidadBebidas.get() print(self.diccionarioPedido) print(self.txtCantidadBebidas.get()) #~ self.listboxPedido.delete(0,'end') self.listboxPedido.delete(0, END) for i in self.diccionarioPedido: print(i) self.listboxPedido.insert( END, i + " " + chr(0) + " " + self.diccionarioPedido[i]) return def EliminarItemPedido(self): texto = self.listboxPedido.get(ACTIVE) busqueda = texto.find(" " + chr(0), 0, len(texto)) key = texto[:busqueda] del self.diccionarioPedido[key] self.listboxPedido.delete(ACTIVE) return def validate(self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name): if text in '0123456789.-+': try: float(value_if_allowed) return True except ValueError: return False else: return False def toggle_fullscreen(self, event=None): self.state = not self.state self.tk.attributes("-fullscreen", self.state) return "break" def end_fullscreen(self, event=None): self.state = False self.tk.attributes("-fullscreen", False) return "break"
class ipGUI: def __init__(self, master): self.master = master self.master.minsize(width=800, height=600) menu = Menu(self.master) master.config(menu=menu) # ***** Main Menu ***** # *** file menu *** fileMenu = Menu(menu) menu.add_cascade(label='File', menu=fileMenu) fileMenu.add_command(label="Open", command=self.openImage) fileMenu.add_command(label="Load Blur Kernel", command=self.loadKernel) fileMenu.add_command(label="Save", command=self.saveImage) fileMenu.add_command(label="Exit", command=master.destroy) # *** edit menu *** editMenu = Menu(menu) menu.add_cascade(label='Space', menu=editMenu) editMenu.add_command(label="Histogram Equalization", command=self.histWrap) editMenu.add_command(label="Gamma Correction", command=self.gammaCorWrap) editMenu.add_command(label="Log Transform", command=self.logTranWrap) editMenu.add_command(label="Sharpen", command=self.sharpWrap) editMenu.add_command(label="Cartoonify", command=self.cartoonifyWrap) # *** blur menu *** blurMenu = Menu(editMenu) editMenu.add_cascade(label='Blur', menu=blurMenu) blurMenu.add_command(label="Box", command=self.boxBlurWrap) blurMenu.add_command(label="Gaussian", command=self.gaussianBlurWrap) blurMenu.add_command(label="Median", command=self.medianBlurWrap) # *** frequency filtering *** freqMenu = Menu(menu) menu.add_cascade(label='Frequency', menu=freqMenu) freqMenu.add_command(label="DFT", command=self.dftWrap) freqMenu.add_command(label="Load Mask", command=self.freqMaskWrap) # *** Mask Menu *** maskMenu = Menu(freqMenu) freqMenu.add_cascade(label='Create Mask', menu=maskMenu) maskMenu.add_command(label='Low Pass', command=self.lpmWrap) maskMenu.add_command(label='High Pass', command=self.hpmWrap) maskMenu.add_command(label='Band Pass', command=self.bppmWrap) maskMenu.add_command(label='Band Stop', command=self.bspmWrap) # *** frequency filtering *** restorationMenu = Menu(menu) menu.add_cascade(label='Restoration', menu=restorationMenu) restorationMenu.add_command(label="Full Inverse", command=self.fullInverseWrap) restorationMenu.add_command(label="Radially Limited Inverse", command=self.truncatedInverseWrap) restorationMenu.add_command(label="Approximate Weiner", command=self.approximateWeinerWrap) restorationMenu.add_command(label="Constrained LS", command=self.contrainedLSWrap) # ***** Toolbar ***** toolbar = Frame(master, bg="grey") undoButton = Button(toolbar, text="Undo", command=self.undoFunc) undoButton.pack(side=LEFT) origButton = Button(toolbar, text="Original", command=self.origFunc) origButton.pack(side=LEFT) toolbar.pack(side=TOP, fill=X) # ***** Image Display Area ***** self.frame = Frame(self.master) self.frame.pack() self.panel = Label(self.frame) self.panel.pack(padx=10, pady=10) self.img = None self.origImg = None self.prevImg = None # ***** Gamma Controls ***** self.gammaFrame = Frame(self.master) self.gammaSlider = Scale(self.gammaFrame, from_=0.1, to=2, orient=HORIZONTAL, resolution=0.1) self.gammaSlider.pack(side=TOP) self.gammaExitButton = Button(self.gammaFrame, text="Exit", command=self.gammaFrame.pack_forget) self.gammaExitButton.pack(side=TOP) # ***** Box Blur Controls ***** self.boxFrame = Frame(self.master) self.boxSlider = Scale(self.boxFrame, from_=1, to=5, orient=HORIZONTAL) self.boxSlider.pack(side=TOP) self.boxExitButton = Button(self.boxFrame, text="Exit", command=self.boxFrame.pack_forget) self.boxExitButton.pack(side=TOP) # ***** Truncated Inverse Controls ***** self.truncatedInverseFrame = Frame(self.master) self.truncatedInverseSlider = Scale(self.truncatedInverseFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.truncatedInverseSlider.pack(side=TOP) self.truncatedInverseExitButton = Button( self.truncatedInverseFrame, text="Exit", command=self.truncatedInverseFrame.pack_forget) self.truncatedInverseExitButton.pack(side=TOP) # ***** Weiner Controls ***** self.weinerFrame = Frame(self.master) self.weinerSlider = Scale(self.weinerFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.weinerSlider.pack(side=TOP) self.weinerExitButton = Button(self.weinerFrame, text="Exit", command=self.weinerFrame.pack_forget) self.weinerExitButton.pack(side=TOP) # ***** CLS Controls ***** self.clsFrame = Frame(self.master) self.clsSlider = Scale(self.clsFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.clsSlider.pack(side=TOP) self.clsExitButton = Button(self.clsFrame, text="Exit", command=self.clsFrame.pack_forget) self.clsExitButton.pack(side=TOP) # ***** DFT Display Area ****** self.dftFrame = Frame(self.master) self.magPanel = Label(self.dftFrame) self.magPanel.pack(padx=10, pady=10, side=TOP) self.freqPanel = Label(self.dftFrame) self.freqPanel.pack(padx=10, pady=10, side=TOP) self.dftExitButton = Button( self.dftFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.dftExitButton.pack(side=TOP, fill=X) # ***** Low Pass Mask Creation ***** self.lpmFrame = Frame(self.master) self.lpmPanel = Label(self.lpmFrame) self.lpmPanel.pack(padx=10, pady=10, side=TOP) self.lpmSubButton = Button(self.lpmFrame, text="submit") self.lpmSubButton.pack(side=TOP) self.lpmExitButton = Button( self.lpmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.lpmExitButton.pack(side=TOP) self.lpmSlider = Scale(self.lpmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** High Pass Mask Creation ***** self.hpmFrame = Frame(self.master) self.hpmPanel = Label(self.hpmFrame) self.hpmPanel.pack(padx=10, pady=10, side=TOP) self.hpmSubButton = Button(self.hpmFrame, text="submit") self.hpmSubButton.pack(side=TOP) self.hpmExitButton = Button( self.hpmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.hpmExitButton.pack(side=TOP) self.hpmSlider = Scale(self.hpmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** Band Pass Mask Creation ***** self.bppmFrame = Frame(self.master) self.bppmPanel = Label(self.bppmFrame) self.bppmPanel.pack(padx=10, pady=10, side=TOP) self.bppmSubButton = Button(self.bppmFrame, text="submit") self.bppmSubButton.pack(side=TOP) self.bppmExitButton = Button( self.bppmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.bppmExitButton.pack(side=TOP) self.bppmSliderLow = Scale(self.bppmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) self.bppmSliderHigh = Scale(self.bppmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** Band Pass Mask Creation ***** self.bspmFrame = Frame(self.master) self.bspmPanel = Label(self.bspmFrame) self.bspmPanel.pack(padx=10, pady=10, side=TOP) self.bspmSubButton = Button(self.bspmFrame, text="submit") self.bspmSubButton.pack(side=TOP) self.bspmExitButton = Button( self.bspmFrame, text="exit", command=lambda: self.displayImg(np.array(self.img))) self.bspmExitButton.pack(side=TOP) self.bspmSliderLow = Scale(self.bspmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) self.bspmSliderHigh = Scale(self.bspmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) def displayImg(self, img): # input image in RGB self.frame.pack() self.dftFrame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.img = Image.fromarray(img) imgtk = ImageTk.PhotoImage(self.img) self.panel.configure(image=imgtk) self.panel.image = imgtk def openImage(self): # can change the image path = filedialog.askopenfilename() if len(path) > 0: imgRead = cv2.imread(path) if imgRead is not None: imgRead = cv2.cvtColor(imgRead, cv2.COLOR_BGR2RGB) self.origImg = Image.fromarray(imgRead) self.prevImg = Image.fromarray(imgRead) self.displayImg(imgRead) else: raise ValueError("Not a valid image") else: raise ValueError("Not a valid path") def loadKernel(self): path = filedialog.askopenfilename() if len(path) > 0: self.filter_kernel = np.mean(cv2.imread(path), axis=-1) self.filter_kernel = self.filter_kernel / np.sum( self.filter_kernel) else: raise ValueError("Not a valid path") def saveImage(self): if self.img is not None: toSave = filedialog.asksaveasfilename() self.img.save(toSave) else: messagebox.showerror(title="Save Error", message="No image to be saved!") def histWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.histEqlFunc(img) self.displayImg(imgNew) # Gamma Correction def gammaCallback(self, event, img): gamma = self.gammaSlider.get() self.prevImg = self.img imgNew = image_utils.gammaCorFunc(img, 255.0 / (255.0**gamma), gamma) self.displayImg(imgNew) def truncatedInverseCallback(self, event, img): th = 10**self.truncatedInverseSlider.get() imgNew = self.truncatedInverseFilter(th) self.displayImg(imgNew) def weinerCallback(self, event, img): gamma = 10**self.weinerSlider.get() imgNew = self.weinerFilter(gamma) self.displayImg(imgNew) def clsCallback(self, event, img): K = 10**self.clsSlider.get() imgNew = self.clsFilter(K) self.displayImg(imgNew) def gammaCorWrap(self): img = np.array(self.img) self.gammaFrame.pack() self.gammaSlider.set(1.0) self.gammaSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.gammaCallback(event, img)) def logTranWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.logTranFunc(img, 255.0 / np.log10(256)) self.displayImg(imgNew) def sharpWrap(self): # Sharpen Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.sharpFunc(img) self.displayImg(imgNew) def boxBlurWrap(self): # Box Blur Wrapper img = np.array(self.img) self.prevImg = self.img self.boxFrame.pack() self.boxSlider.set(1) self.boxSlider.bind("<ButtonRelease-1>", lambda event, img=img: self.displayImg( image_utils.boxBlurFunc( event, img, 2 * self.boxSlider.get() + 1))) def gaussianBlurWrap(self): # Gaussian Blur Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.gaussianBlurFunc(img) self.displayImg(imgNew) def medianBlurWrap(self): # Median Blur Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.medianBlurFunc(img) self.displayImg(imgNew) def cartoonifyWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.cartoonifyFunc(img) self.displayImg(imgNew) def undoFunc(self): self.img = self.prevImg self.displayImg(np.array(self.img)) def origFunc(self): self.prevImg = self.img self.img = self.origImg self.displayImg(np.array(self.img)) def displayDFT(self, x_fft): m, n = x_fft.shape[:] self.frame.pack_forget() self.dftFrame.pack() x_mag = np.log10(np.absolute(x_fft)) * 255 / np.log10(m * n * 255) x_mag = Image.fromarray(x_mag) x_mag = x_mag.resize((min(256, m), min(int(256 * n / m), n)), Image.ANTIALIAS) x_mag = ImageTk.PhotoImage(x_mag) x_freq = (np.angle(x_fft) % 360) * 255 / 360 x_freq = Image.fromarray(x_freq) x_freq = x_freq.resize((min(256, m), min(int(256 * n / m), n)), Image.ANTIALIAS) x_freq = ImageTk.PhotoImage(x_freq) self.magPanel.configure(image=x_mag) self.magPanel.image = x_mag self.freqPanel.configure(image=x_freq) self.freqPanel.image = x_freq def dftWrap(self): img = np.array(self.img) x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) x_outp_img = fft.fft2d_img(x) self.displayDFT(x_outp_img) def freqMaskWrap(self): m, n = np.array(self.img).shape[:2] lm, ln = np.log2(m), np.log2(m) dm, dn = int(2**np.ceil(lm)) + 1, int(2**np.ceil(ln)) + 1 messagebox.showinfo( "Mask Size", "Mask Size should be (" + str(dm) + "," + str(dn) + ")") path = filedialog.askopenfilename() if len(path) > 0: maskRead = cv2.imread(path, 0) if (maskRead.shape != (dm, dn)): messagebox.showerror( title="Shape Error", message="Shape of mask and image don't match") else: self.prevImg = self.img self.display(image_utils.freqMask(np.array(self.img), maskRead)) else: raise ValueError("Not a valid path") def maskWrap(self): img = np.array(self.img) x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) x_outp_img = fft.fft2d_img(x) x_mag = image_utils.xMagCreate(x_outp_img) return x_outp_img, x_mag def maskFinal(self, x_outp_img): self.prevImg = self.img img = np.array(self.img) img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) m = len(img) res = fft.ifft2d_img(x_outp_img) res = np.array(res * 255 / np.max(res), dtype=np.uint8) res = np.array([[[img[i][j][0], img[i][j][1], res[i][j]] for j in range(m)] for i in range(m)]) res = cv2.cvtColor(res, cv2.COLOR_HSV2RGB) self.displayImg(res) def lpmCallBack(self, event, slider, x_outp_img): m = len(x_outp_img) m2 = int((m - 1) / 2) r = slider.get() x_outp_copy = np.copy(x_outp_img) nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(m)] for i in range(m)]) nCircle = np.where(nCircle > r**2) x_outp_copy[nCircle] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.lpmPanel.configure(image=x_mag) self.lpmPanel.image = x_mag def lpmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = self.lpmSlider.get() nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nCircle = np.where(nCircle > r**2) x_outp_img[nCircle] = 0 self.maskFinal(x_outp_img) def lpmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.lpmPanel.configure(image=x_mag) self.lpmPanel.image = x_mag self.lpmSlider.configure(to=int(np.ceil(m / 2))) self.lpmSlider.set(1) self.lpmSlider.pack(side=TOP) self.lpmSlider.bind( "<ButtonRelease-1>", lambda event, slider=self.lpmSlider, x_outp_img=x_outp_img: self. lpmCallBack(event, slider, x_outp_img)) self.lpmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.lpmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.lpmFrame.pack() def hpmCallBack(self, event, slider, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = slider.get() x_outp_copy = np.copy(x_outp_img) circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) circle = np.where(circle <= r**2) x_outp_copy[circle] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.hpmPanel.configure(image=x_mag) self.hpmPanel.image = x_mag def hpmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = self.hpmSlider.get() circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) circle = np.where(circle <= r**2) x_outp_img[circle] = 0 self.maskFinal(x_outp_img) def hpmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.hpmPanel.configure(image=x_mag) self.hpmPanel.image = x_mag self.hpmSlider.configure(to=m // 2) self.hpmSlider.set(1) self.hpmSlider.pack(side=TOP) self.hpmSlider.bind( "<ButtonRelease-1>", lambda event, slider=self.hpmSlider, x_outp_img=x_outp_img: self. hpmCallBack(event, slider, x_outp_img)) self.hpmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.hpmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.hpmFrame.pack() def bppmCallBack(self, event, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bppmSliderLow.get() r2 = self.bppmSliderHigh.get() assert (r1 <= r2) self.bppmSliderLow.configure(to=r2) self.bppmSliderHigh.configure(from_=r1) x_outp_copy = np.copy(x_outp_img) allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where(allVals < r1**2) x_outp_copy[nullVals] = 1 nullVals = np.where(allVals > r2**2) x_outp_copy[nullVals] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.bppmPanel.configure(image=x_mag) self.bppmPanel.image = x_mag def bppmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bppmSliderLow.get() r2 = self.bppmSliderHigh.get() allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where(allVals < r1**2) x_outp_img[nullVals] = 0 nullVals = np.where(allVals > r2**2) x_outp_img[nullVals] = 0 self.maskFinal(x_outp_img) def bppmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.bppmPanel.configure(image=x_mag) self.bppmPanel.image = x_mag self.bppmSliderHigh.configure(from_=1) self.bppmSliderHigh.configure(to=m // 2) self.bppmSliderHigh.set(m // 2) self.bppmSliderHigh.pack(side=TOP) self.bppmSliderHigh.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bppmCallBack(event, x_outp_img)) self.bppmSliderLow.configure(from_=1) self.bppmSliderLow.configure(to=m // 2) self.bppmSliderLow.set(1) self.bppmSliderLow.pack(side=TOP) self.bppmSliderLow.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bppmCallBack(event, x_outp_img)) self.bppmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.bppmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bspmFrame.pack_forget() self.bppmFrame.pack() def bspmCallBack(self, event, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bspmSliderLow.get() r2 = self.bspmSliderHigh.get() assert (r1 <= r2) self.bspmSliderLow.configure(to=r2) self.bspmSliderHigh.configure(from_=r1) x_outp_copy = np.copy(x_outp_img) allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0) x_outp_copy[nullVals] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.bspmPanel.configure(image=x_mag) self.bspmPanel.image = x_mag def bspmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bspmSliderLow.get() r2 = self.bspmSliderHigh.get() allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0) x_outp_img[nullVals] = 0 self.maskFinal(x_outp_img) def bspmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.bspmPanel.configure(image=x_mag) self.bspmPanel.image = x_mag self.bspmSliderHigh.configure(from_=1) self.bspmSliderHigh.configure(to=m // 2) self.bspmSliderHigh.set(m // 2) self.bspmSliderHigh.pack(side=TOP) self.bspmSliderHigh.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bspmCallBack(event, x_outp_img)) self.bspmSliderLow.configure(from_=1) self.bspmSliderLow.configure(to=m // 2) self.bspmSliderLow.set(1) self.bspmSliderLow.pack(side=TOP) self.bspmSliderLow.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bspmCallBack(event, x_outp_img)) self.bspmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.bspmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack() def fullInverseWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = filtering.inverseFilter2D(img, self.filter_kernel) self.displayImg(imgNew) def truncatedInverseWrap(self): img = np.array(self.img) self.prevImg = self.img self.truncatedInverseFilter = filtering.getTruncatedInverseFilter2D( img, self.filter_kernel) self.truncatedInverseFrame.pack() self.truncatedInverseSlider.set(1.0) self.truncatedInverseSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.truncatedInverseCallback(event, img)) def approximateWeinerWrap(self): img = np.array(self.img) self.prevImg = self.img self.weinerFilter = filtering.getApproximateWeinerFilter2D( img, self.filter_kernel) self.weinerFrame.pack() self.weinerSlider.set(1.0) self.weinerSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.weinerCallback(event, img)) def contrainedLSWrap(self): # TODO: implement img = np.array(self.img) self.prevImg = self.img self.clsFilter = filtering.getConstrainedLSFilter2D( img, self.filter_kernel) self.clsFrame.pack() self.clsSlider.set(1.0) self.clsSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.clsCallback(event, img))
class ShopEngine: def __init__(self, window): self.window = window self.normalShop = True self.f = Frame(self.window.root, bg="blue", width=self.window.width, height=self.window.height) self.f.pack_propagate(0) self.backgroundImage = ImageTk.PhotoImage(file="Backgrounds/shop.png") self.backgroundLabel = Label(self.f, image=self.backgroundImage) self.shopScale = self.window.width / 1280 self.save = self.window.save barScale = self.shopScale / 5 buttonScale = self.shopScale / 2 self.barImageList = [] self.barImageList.append( self.openTkImage("Images/Shop/levelBar1.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar2.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar3.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar4.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar5.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar6.png", barScale)) self.buttonList = [] self.sideBar = Label(self.window.root, bg="#%02x%02x%02x" % (121, 202, 249), width=self.window.width // 5, height=self.window.height) self.sideBar.pack(in_=self.f, side=LEFT, pady=25, padx=25) self.buttonGrid = Label(self.window.root, bg="#%02x%02x%02x" % (121, 202, 249), width=self.window.width // 5 * 3, height=self.window.height) self.buttonGrid.pack(in_=self.f, side=TOP) self.moneyL = Label(self.window.root, text="Mass: " + str(self.save.mass), bg="#%02x%02x%02x" % (121, 202, 249), font="Helvetica 15 bold", width=self.window.width // 5) self.moneyL.pack(side=TOP, in_=self.sideBar, pady=25) self.achievementB = Button(self.window.root, text="Star Shop", command=self.achievement, bg="#%02x%02x%02x" % (255, 165, 0), width=self.window.width // 5, font="Helvetica 15 bold") self.achievementB.pack(side=BOTTOM, in_=self.sideBar, pady=25) self.accept = Button(self.window.root, text="Accept", command=self.accept, bg="#%02x%02x%02x" % (255, 0, 0), width=self.window.width // 5, font="Helvetica 15 bold") self.accept.pack(side=BOTTOM, in_=self.sideBar) self.shieldButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/shieldButton.png"), buttonScale)) ShopButton(self.window, self.window.save.shieldLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 0, 0, """Shield Capacity: Increases the amount of sheilds you are able to hold""", self.window.root, image=self.shieldButtonImage) self.airResistButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/airResistButton.png"), buttonScale)) ShopButton(self.window, self.window.save.airResistLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 1, 0, """Aerodynamics: Reduces air resistance, allowing you to fly farther and faster""", self.window.root, image=self.airResistButtonImage) self.antiGravButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/antiGravButton.png"), buttonScale)) ShopButton(self.window, self.window.save.antiGravLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 2, 0, """Anit-gravity: Reduces the effect of gravity, causing increased time between bounces""", self.window.root, image=self.antiGravButtonImage) self.frictionButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/frictionButton.png"), buttonScale)) ShopButton(self.window, self.window.save.frictionLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 0, 1, """Oil: Reduces the friction between you and the ground, allowing you to bounce farther""", self.window.root, image=self.frictionButtonImage) self.launchSpeedButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/launchSpeedButton.png"), buttonScale)) ShopButton(self.window, self.window.save.launchLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 1, 1, """Launch Speed: Increases the speed at which you launch, greatly increasing your trip length""", self.window.root, image=self.launchSpeedButtonImage) self.maxMassButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/maxMassButton.png"), buttonScale)) ShopButton(self.window, self.window.save.maxMassLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 2, 1, """Maximum Size: Increases the size that you start your launch with, causing increased visibility and accelerated growth""", self.window.root, image=self.maxMassButtonImage) self.growthRateButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/growthRateButton.png"), buttonScale)) ShopButton(self.window, self.window.save.growthRateLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 0, 2, """Growth rate: Increases the rate at which you grow, allowing you to make more money faster""", self.window.root, image=self.growthRateButtonImage) self.maxFuelButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/maxFuelButton.png"), buttonScale)) ShopButton(self.window, self.window.save.maxFuelLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 1, 2, """Max Fuel: Increases the amount of fuel you start with, and the maximum amount you can hold""", self.window.root, image=self.maxFuelButtonImage) self.propulsionButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/propulsionButton.png"), buttonScale)) ShopButton(self.window, self.window.save.propulsionLevel, self.buttonGrid, self.sideBar, self.save, self.buttonList, self.barImageList, self.backgroundImage, 2, 2, """Rocket speed: Increases the propulsion from your rocket, allowing you to maneuver more easily and go farther""", self.window.root, image=self.propulsionButtonImage) def update(self): self.f.config(width=self.window.width, height=self.window.width) self.shopScale = self.window.width / 1280 self.save = self.window.save barScale = self.shopScale / 5 self.sideBar.config(width=self.window.width // 5, heigh=self.window.height) self.buttonGrid.config(width=self.window.width // 5 * 3, height=self.window.height) buttonScale = self.shopScale / 2 self.barImageList.clear() self.barImageList.append( self.openTkImage("Images/Shop/levelBar1.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar2.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar3.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar4.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar5.png", barScale)) self.barImageList.append( self.openTkImage("Images/Shop/levelBar6.png", barScale)) try: self.buttonGrid.config(width=self.window.width // 5 * 3, height=self.window.height) self.shieldButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/shieldButton.png"), buttonScale)) self.buttonList[0].config(image=self.shieldButtonImage) self.airResistButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/airResistButton.png"), buttonScale)) self.buttonList[1].config(image=self.airResistButtonImage) self.antiGravButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/antiGravButton.png"), buttonScale)) self.buttonList[2].config(image=self.antiGravButtonImage) self.frictionButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/frictionButton.png"), buttonScale)) self.buttonList[3].config(image=self.frictionButtonImage) self.launchSpeedButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/launchSpeedButton.png"), buttonScale)) self.buttonList[4].config(image=self.launchSpeedButtonImage) self.maxMassButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/maxMassButton.png"), buttonScale)) self.buttonList[5].config(image=self.maxMassButtonImage) self.growthRateButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/growthRateButton.png"), buttonScale)) self.buttonList[6].config(image=self.growthRateButtonImage) self.maxFuelButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/maxFuelButton.png"), buttonScale)) self.buttonList[7].config(image=self.maxFuelButtonImage) self.propulsionButtonImage = ImageTk.PhotoImage( self.scale(Image.open("Images/Shop/propulsionButton.png"), buttonScale)) self.buttonList[8].config(image=self.propulsionButtonImage) except: pass def accept(self): self.window.rMenu = "charScreen" def achievement(self): self.window.rMenu = "starShop" def run(self): self.moneyL.config(text="Mass: " + str(int(self.save.mass))) self.save = self.window.save for button in self.buttonList: button.save = self.window.save button.run() self.window.save.shieldLevel = self.buttonList[0].level self.window.save.airResistLevel = self.buttonList[1].level self.window.save.antiGravLevel = self.buttonList[2].level self.window.save.frictionLevel = self.buttonList[3].level self.window.save.launchLevel = self.buttonList[4].level self.window.save.maxMassLevel = self.buttonList[5].level self.window.save.growthRateLevel = self.buttonList[6].level self.window.save.maxFuelLevel = self.buttonList[7].level self.window.save.propulsionLevel = self.buttonList[8].level def scale(self, image, scale): newWidth = image.size[0] * scale wPercent = (newWidth / float(image.size[0])) hSize = int((float(image.size[1]) * float(wPercent))) scaledImage = image.resize((int(newWidth), int(hSize)), PIL.Image.ANTIALIAS) return scaledImage def hide(self): self.backgroundLabel.place(x=10000, y=10000, relwidth=1, relheight=1) self.sideBar.place(x=10000, y=10000, relwidth=.15, relheight=1) self.f.pack_forget() def setUp(self): self.backgroundLabel.place(x=0, y=0, relwidth=1, relheight=1) self.sideBar.place(x=0, y=0, relwidth=.15, relheight=1) self.shopScale = self.window.width / 1280 self.buttonList[0].level = self.window.save.shieldLevel self.buttonList[1].level = self.window.save.airResistLevel self.buttonList[2].level = self.window.save.antiGravLevel self.buttonList[3].level = self.window.save.frictionLevel self.buttonList[4].level = self.window.save.launchLevel self.buttonList[5].level = self.window.save.maxMassLevel self.buttonList[6].level = self.window.save.growthRateLevel self.buttonList[7].level = self.window.save.maxFuelLevel self.buttonList[8].level = self.window.save.propulsionLevel self.f.pack() def openTkImage(self, path, scale): return ImageTk.PhotoImage( self.scale(Image.open(path), scale).convert("RGB"))
class QuantMonitor(object): # 背景色 bgColor = rgb_to_hex(245, 245, 245) bgColorW = "white" def __init__(self, frame, control, language): self.parentFrame = frame self._controller = control self._logger = self._controller.get_logger() self.language = language # Monitor不同标签的背景色 self.rColor = self.bgColorW self.lColor = self.bgColor self.eColor = self.bgColor self.pColor = self.bgColor # 日志不同标签背景色 self.yColor = self.bgColor # 系统日志标签颜色 self.sColor = self.bgColor self.uColor = self.bgColorW self.createButtonFrame() # 执行列表、监控日志、信号记录、错误 self.executeList = Frame(self.parentFrame) self.errRecord = Frame(self.parentFrame) self.posMonitor = Frame(self.parentFrame) self.logRecord = Frame(self.parentFrame) self.sysLog = Frame(self.logRecord) self.sigRecord = Frame(self.logRecord) self.usrLog = Frame(self.logRecord) self.executeList.pack(side=TOP, fill=BOTH, expand=YES) self.sysText = None self.sigText = None self.usrText = None self.errText = None self._regUpdateCallback() # 日志功能区 self.createLogBtnFrame() self.usrLog.pack(side=TOP, fill=BOTH, expand=YES) def createButtonFrame(self): btnFrame = Frame(self.parentFrame, height=30, bg=self.bgColor) btnFrame.pack_propagate(0) btnFrame.pack(side=TOP, fill=X) self.runBtn = Button(btnFrame, text="策略运行", relief=FLAT, padx=14, pady=1.5, bg=self.rColor, bd=0, highlightthickness=1, command=self.toMonFrame) self.logBtn = Button(btnFrame, text="运行日志", relief=FLAT, padx=14, pady=1.5, bg=self.lColor, bd=0, highlightthickness=1, command=self.toLogFrame) self.errBtn = Button(btnFrame, text="错误信息", relief=FLAT, padx=14, pady=1.5, bg=self.eColor, bd=0, highlightthickness=1, command=self.toErrFrame) self.posBtn = Button(btnFrame, text="组合监控", relief=FLAT, padx=14, pady=1.5, bg=self.pColor, bd=0, highlightthickness=1, command=self.toPosFrame) self.runBtn.pack(side=LEFT, expand=NO) self.logBtn.pack(side=LEFT, expand=NO) self.errBtn.pack(side=LEFT, expand=NO) self.posBtn.pack(side=LEFT, expand=NO) for btn in (self.runBtn, self.logBtn, self.errBtn, self.posBtn): btn.bind("<Enter>", self.handlerAdaptor(self.onEnter, button=btn)) btn.bind("<Leave>", self.handlerAdaptor(self.onLeave, button=btn)) def createLogBtnFrame(self): """创建日志按钮Frame""" lBtnFrame = Frame(self.logRecord, height=30, bg=self.bgColor) lBtnFrame.pack_propagate(0) lBtnFrame.pack(side=BOTTOM, fill=X) self.usrBtn = Button(lBtnFrame, text="用户日志", relief=FLAT, padx=14, pady=1.5, bg=self.rColor, bd=0, highlightthickness=1, command=self.toUsrFrame) self.sigBtn = Button(lBtnFrame, text="信号记录", relief=FLAT, padx=14, pady=1.5, bg=self.lColor, bd=0, highlightthickness=1, command=self.toSigFrame) self.sysBtn = Button(lBtnFrame, text="系统日志", relief=FLAT, padx=14, pady=1.5, bg=self.sColor, bd=0, highlightthickness=1, command=self.toSysFrame) self.usrBtn.pack(side=LEFT, expand=NO) self.sigBtn.pack(side=LEFT, expand=NO) self.sysBtn.pack(side=LEFT, expand=NO) # for btn in (self.usrBtn, self.sigBtn, self.sysBtn): # btn.bind("<Enter>", self.handlerAdaptor(self.onEnter, button=btn)) # btn.bind("<Leave>", self.handlerAdaptor(self.onLeave, button=btn)) # pass def createLog(self): self.createSysLog() self.createSignal() self.createUsrLog() def createSysLog(self): """系统日志""" self.sysText = MonitorText(self.sysLog, self, height=20, bd=0) self.sysText.createScrollbar() self.sysText.pack(fill=BOTH, expand=YES) def createSignal(self): """信号记录""" self.sigText = SigText(self.sigRecord, self, height=20, bd=0) self.sigText.createScrollbar() self.sigText.pack(fill=BOTH, expand=YES) def createUsrLog(self): """用户日志""" self.usrText = UsrLogText(self.usrLog, height=20, bd=0) self.usrText.createScrollbar() self.usrText.pack(fill=BOTH, expand=YES) def createPos(self): headList = ["账号", "合约", "账户仓", "策略仓", "仓差", "策略多", "策略空","策略今多", "策略今空", "账户多", "账户空", "账户今多", "账户今空"] widthList = [20, 20, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] funcFrame = Frame(self.posMonitor, relief=RAISED, bg=rgb_to_hex(245, 245, 245), height=25) funcFrame.pack(side=TOP, fill=X, expand=YES, padx=1, pady=2) treeFrame = Frame(self.posMonitor, relief=RAISED, bg=rgb_to_hex(245, 245, 245)) treeFrame.pack(side=TOP, fill=X, expand=YES, padx=1, pady=2) self.posTree = ttk.Treeview(treeFrame, show="headings", height=28, columns=headList) self.posTree.pack(fill=BOTH, expand=YES, padx=5) for key, w in zip(headList, widthList): self.posTree.column(key, width=w, anchor=W) self.posTree.heading(key, text=key, anchor=W) self.createPosFunc(funcFrame) def createPosFunc(self, frame): cbV = StringVar() sbV = IntVar() timeV = IntVar() cbV.set("对盘价") sbV.set(0) timeV.set(5000) # buttonborder = Frame(frame, highlightbackground="lightblue", highlightthickness=2, bd=0) # buttonborder.pack(side=LEFT, padx=2) synBtn = Button(frame, text="持仓一键同步", relief=FLAT, activebackground="lightblue", overrelief="groove", bg=rgb_to_hex(230, 230, 230)) synBtn.pack(side=LEFT, padx=2) Label(frame, text="同步设置:", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=8).pack(side=LEFT) cbValues = ["对盘价", "最新价", "市价"] cb = ttk.Combobox(frame, values=cbValues, width=11, textvariable=cbV, state="readonly") cb.pack(side=LEFT, padx=2) Label(frame, text="+", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=1).pack(side=LEFT) sb = ttk.Spinbox(frame, values=list(range(0, 101, 1)), width=4, textvariable=sbV) sb.pack(side=LEFT, padx=2) Label(frame, text="跳", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=2).pack(side=LEFT) disCheck = Checkbutton(frame, text="间隔", bg=rgb_to_hex(245, 245, 245), width=10, bd=1, anchor=E) disCheck.pack(side=LEFT, padx=2) timeEntry = Entry(frame, relief=GROOVE, bd=2, width=5, textvariable=timeV) timeEntry.pack(side=LEFT) Label(frame, text="毫秒自动同步", bg=rgb_to_hex(245, 245, 245), justify=LEFT, anchor=W, width=12)\ .pack(side=LEFT, padx=2) subCheck = Checkbutton(frame, text="仅自动减仓", bg=rgb_to_hex(245, 245, 245), bd=1, anchor=W) subCheck.pack(side=LEFT, padx=5) def createExecute(self): headList = ["编号", "账号", "策略名称", "基准合约", "频率", "运行阶段", "运行模式", "初始资金", "可用资金", "最大回撤", "累计收益", "胜率"] widthList = [5, 50, 50, 50, 5, 10, 5, 20, 10, 20, 20, 5] self.executeBar = ttk.Scrollbar(self.executeList, orient="vertical") self.executeBar.pack(side=RIGHT, fill=Y) self.executeListTree = ttk.Treeview(self.executeList, show="headings", height=28, columns=tuple(headList), yscrollcommand=self.executeBar.set, style="Filter.Treeview") self.executeBar.config(command=self.executeListTree.yview) self.executeListTree.pack(fill=BOTH, expand=YES) self.executeListTree.bind("<Button-3>", self.createMenu) for key, w in zip(headList, widthList): self.executeListTree.column(key, width=w, anchor=CENTER) self.executeListTree.heading(key, text=key) def createMenu(self, event): """创建运行策略右键菜单""" RunMenu(self._controller, self.executeListTree).popupmenu(event) def _formatMonitorInfo(self, dataDict): """ 格式化监控需要的信息 :param dataDict: 策略的所有信息 :return: 需要展示的信息 """ try: Id = dataDict['StrategyId'] UserNo = dataDict["Config"]["Money"]["UserNo"] StName = dataDict['StrategyName'] BenchCon = dataDict['ContractNo'] kLineType = dataDict['KLineType'] kLineSlice = dataDict['KLinceSlice'] Frequency = str(kLineSlice) + kLineType # RunType = "是" if dataDict['IsActualRun'] else "否" RunType = RunMode[dataDict["IsActualRun"]] Status = StrategyStatus[dataDict["StrategyState"]] InitFund = dataDict['InitialFund'] Available = "{:.2f}".format(InitFund) MaxRetrace = 0.0 TotalProfit = 0.0 WinRate = 0.0 return [ Id, UserNo, StName, BenchCon, Frequency, Status, RunType, InitFund, Available, MaxRetrace, TotalProfit, WinRate ] except KeyError: traceback.print_exc() return [] def addExecute(self, dataDict): values = self._formatMonitorInfo(dataDict) if not values: return strategyId = dataDict["StrategyId"] try: if self.executeListTree.exists(strategyId): self.updateRunStage(strategyId, dataDict[5]) return except Exception as e: self._logger.warn("addExecute exception") else: self.executeListTree.insert("", END, iid=strategyId, values=tuple(values), tag=0) def createErr(self): # 错误信息展示 self.errText = ErrorText(self.errRecord, height=20, bd=0) self.errText.createScrollbar() self.errText.pack(fill=BOTH, expand=YES) def _regUpdateCallback(self): self._logUpdateDict = { "U": self._updateUsrText, "E": self._updateErrText, "s": self._updateSysText, } def _updateSigText(self, text): """更新下单信号日志""" # 先清空信号记录 self.sigText.delText() self.sigText.setText(text) def _updateErrText(self, text): """更新调试信息日志""" self.errText.setText(text) self.toErrFrame() def _updateUsrText(self, text): """更新用户日志""" self.usrText.setText(text) def _updateSysText(self, text): """更新系统日志""" self.sysText.delText() self.sysText.setText(text) def loadSysLogFile(self): """读取本地系统日志""" sysLogPath = r"./log/equant.log" # with open(sysLogPath, "r", encoding="utf-8") as f: with open(sysLogPath, "r") as f: data = f.read() self._updateSysText(data) def loadSigLogFile(self): """读取本地信号日志并写入界面""" sigLogPath = r"./log/trade.dat" with open(sigLogPath, "r", encoding="utf-8") as f: data = f.read() self._updateSigText(data) # TODO: 函数名改为updateLogText def updateLogText(self): guiQueue = self._controller.get_logger().getGuiQ() errData, usrData = "", "" flag = True try: while flag: logData = guiQueue.get_nowait() if logData[0] == "U": usrData += logData[1] + "\n" elif logData[0] == "E": errData += logData[1] + "\n" if guiQueue.empty(): flag = False except: return else: if usrData: self._updateUsrText(usrData) if errData: self._updateErrText(errData) def clearErrorText(self): self.errText.setText("") def toMonFrame(self): self.runBtn.config(bg="white") self.rColor = self.runBtn['bg'] self.lColor = self.bgColor self.eColor = self.bgColor self.pColor = self.bgColor self.errBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.posBtn.config(bg=self.pColor) self.logRecord.pack_forget() self.errRecord.pack_forget() self.posMonitor.pack_forget() self.executeList.pack(side=TOP, fill=BOTH, expand=YES) # def toLogFrame(self, event, button): # buttons = [self.runBtn, self.logBtn, self.errBtn, self.posBtn] # colors = [self.rColor, self.lColor, self.eColor, self.pColor] # frames = [self.executeList, self.logRecord, self.errRecord, self.posMonitor] # # button.config(bg="white") # index = buttons.index(button) # colors[index] = button['bg'] # frames[index].pack(side=TOP, fill=BOTH, expand=YES) # buttons.remove(button) # colors.remove(colors[index]) # frames.remove(frames[index]) # #TODO:怎么pop呢? # # for btn in buttons: # i = buttons.index(btn) # colors[i] = self.bgColor # btn.config(bg=self.bgColor) # frames[i].pack_forget() def toLogFrame(self): self.logBtn.config(bg="white") self.lColor = self.logBtn['bg'] self.rColor = self.bgColor self.eColor = self.bgColor self.pColor = self.bgColor self.runBtn.config(bg=self.rColor) self.errBtn.config(bg=self.eColor) self.posBtn.config(bg=self.pColor) self.executeList.pack_forget() self.errRecord.pack_forget() self.posMonitor.pack_forget() self.logRecord.pack(side=TOP, fill=BOTH, expand=YES) def toSysFrame(self): self.sysBtn.config(bg="white") self.yColor = self.sysBtn['bg'] self.sColor = self.bgColor self.uColor = self.bgColor self.sigBtn.config(bg=self.sColor) self.usrBtn.config(bg=self.uColor) self.sigRecord.pack_forget() self.usrLog.pack_forget() self.sysLog.pack(side=TOP, fill=BOTH, expand=YES) # 写入系统日志 self.loadSysLogFile() def toSigFrame(self): self.sigBtn.config(bg="white") self.sColor = self.sigBtn['bg'] self.uColor = self.bgColor self.yColor = self.bgColor self.sysBtn.config(bg=self.yColor) self.usrBtn.config(bg=self.uColor) self.sysLog.pack_forget() self.usrLog.pack_forget() self.sigRecord.pack(side=TOP, fill=BOTH, expand=YES) # 写入信号记录 self.loadSigLogFile() def toUsrFrame(self): self.usrBtn.config(bg="white") self.uColor = self.sysBtn['bg'] self.sColor = self.bgColor self.yColor = self.bgColor self.sigBtn.config(bg=self.sColor) self.sysBtn.config(bg=self.yColor) self.sigRecord.pack_forget() self.sysLog.pack_forget() self.usrLog.pack(side=TOP, fill=BOTH, expand=YES) def toErrFrame(self): self.errBtn.config(bg="white") self.eColor = self.errBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.pColor = self.bgColor self.runBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.posBtn.config(bg=self.pColor) self.parentFrame.update() self.logRecord.pack_forget() self.executeList.pack_forget() self.posMonitor.pack_forget() self.errRecord.pack(side=TOP, fill=BOTH, expand=YES) def toPosFrame(self): self.posBtn.config(bg="white") self.pColor = self.posBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.eColor = self.bgColor self.runBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.errBtn.config(bg=self.eColor) self.parentFrame.update() self.logRecord.pack_forget() self.executeList.pack_forget() self.errRecord.pack_forget() self.posMonitor.pack(side=TOP, fill=BOTH, expand=YES) def handlerAdaptor(self, fun, **kwargs): return lambda event, fun=fun, kwargs=kwargs: fun(event, **kwargs) def onEnter(self, event, button): """鼠标进入事件""" buttons = [self.runBtn, self.logBtn, self.errBtn, self.posBtn] button.config(bg='white') buttons.remove(button) for btn in buttons: btn.config(bg=self.bgColor) def onLeave(self, event, button): """鼠标离开事件""" buttons = [self.runBtn, self.logBtn, self.errBtn, self.posBtn] #TODO: 类实例作为字典键值有问题! btnColorDict = { self.runBtn: self.rColor, self.logBtn: self.lColor, self.errBtn: self.eColor, self.posBtn: self.pColor } button.config(bg=rgb_to_hex(227, 230, 233)) button['bg'] = btnColorDict[button] buttons.remove(button) for btn in buttons: btn['bg'] = btnColorDict[btn] def deleteStrategy(self, strategyId): """删除策略""" if str(strategyId) in self.executeListTree.get_children(): self.executeListTree.delete(strategyId) self._logger.info(f"[UI][{strategyId}]: Delete strategy {strategyId} successfully!") def updateValue(self, strategyId, dataDict): """更新策略ID对应的运行数据""" colValues = { "#9": "{:.2f}".format(dataDict["Available"]), "#10": "{:.2f}".format(dataDict["MaxRetrace"]), "#11": "{:.2f}".format(dataDict["NetProfit"]), "#12": "{:.2f}".format(dataDict["WinRate"]) } if str(strategyId) in self.executeListTree.get_children(): for k, v in colValues.items(): try: self.executeListTree.set(strategyId, column=k, value=v) except TclError as e: self._logger.error(f"[UI][{strategyId}]: 更新策略执行数据时出错,执行列表中该策略已删除!") def updateRunStage(self, strategyId, status): """更新策略运行阶段""" if str(strategyId) in self.executeListTree.get_children(): self.executeListTree.set(strategyId, column="#6", value=StrategyStatus[status]) def updateRunMode(self, strategyId, status): """更新策略运行模式""" if str(strategyId) in self.executeListTree.get_children(): self.executeListTree.set(strategyId, column="#7", value=RunMode[status]) def updatePos(self, positions): for itemId in self.posTree.get_children(): self.posTree.delete(itemId) for v in positions: self.posTree.insert("", 'end', values=v)
class MyRoot(Tk): def __init__(self, master=None): Tk.__init__(self, master) self.last_time_count = DEFAULT_TIME_COUNT self.hour_str = StringVar() self.minute_str = StringVar() self.second_str = StringVar() self.time_str = StringVar() self.status_str = StringVar() self.edit_str = StringVar() self.time_str.set('60:00') self.status_str.set('开始') self.edit_str.set('保存') self.timer_frame = Frame(self) self.timer_frame.pack(side='top', fill='both') self.input_hour = Entry(self.timer_frame, width=3, textvariable=self.hour_str) self.input_hour.pack(side='left', fill='both') self.input_hour.insert(INSERT, "1") self.sign_one = Label(self.timer_frame, text=':', width=1) self.sign_one.pack(side='left', fill='both') self.input_minute = Entry(self.timer_frame, width=3, textvariable=self.minute_str) self.input_minute.pack(side='left', fill='both') self.input_minute.insert(INSERT, "00") self.sign_two = Label(self.timer_frame, text=':', width=1) self.sign_two.pack(side='left', fill='both') self.input_second = Entry(self.timer_frame, width=3, textvariable=self.second_str) self.input_second.pack(side='left', fill='both') self.input_second.insert(INSERT, "00") self.label = Label(self, textvariable=self.time_str, width=10) self.label.pack(side='top', fill='both') self.start_button = Button(self, textvariable=self.status_str, command=self.toggle, state='disabled') self.start_button.pack(side='top', fill='both') self.edit_button = Button(self, textvariable=self.edit_str, command=self.edit) self.edit_button.pack(side='top', fill='both') self.time_count = DEFAULT_TIME_COUNT self.current_status = False # False 代表 暂停 True 代表 播放 self.edit_status = False self.is_first = False self.show_edit() def toggle(self): self.current_status = not self.current_status if self.current_status: self.play() else: self.pause() def play(self): if self.time_count == 0: showwarning('请注意!', '起来喝水了!! 回来以后!') self.reset() return self.status_str.set('暂停') self.run_time() self.timer = self.after(1000, self.play) def pause(self): self.status_str.set('运行') self.after_cancel(self.timer) def reset(self): self.time_count = self.last_time_count self.current_status = False self.run_time() self.pause() def set_label_time(self): time_format_dict = self.format_time() hour = time_format_dict['hour'] minute = time_format_dict['minute'] second = time_format_dict['second'] self.time_str.set('%d:%02d:%02d' % (hour, minute, second)) def run_time(self): self.set_label_time() self.time_count -= 1 def format_time(self): hour = self.time_count // 3600 hour_mod = self.time_count % 3600 minute = hour_mod // 60 minute_mod = hour_mod % 60 second = minute_mod % 60 return {'hour': hour, 'minute': minute, 'second': second} def set_time(self, time_dict): self.time_count = time_dict['hour'] * 3600 + time_dict[ 'minute'] * 60 + time_dict['second'] self.last_time_count = self.time_count def get_time(self): hour_text = self.input_hour.get() minute_text = self.input_minute.get() second_text = self.input_second.get() time_dict = {} time_dict['hour'] = int(hour_text) time_dict['minute'] = int(minute_text) time_dict['second'] = int(second_text) return time_dict def validate_time(self): result_dict = self.validate_hour() if not result_dict['accept']: showwarning('warning', result_dict['msg']) return False result_dict = self.validate_minute() if not result_dict['accept']: showwarning('warning', result_dict['msg']) return False result_dict = self.validate_second() if not result_dict['accept']: showwarning('warning', result_dict['msg']) return False return True def validate_hour(self): hour_str = self.input_hour.get() result_dict = {'accept': True, 'msg': None} if not hour_str.isdigit(): result_dict['accept'] = False result_dict['msg'] = '小时数不为整数' return result_dict return result_dict def validate_minute(self): minute_str = self.input_minute.get() result_dict = {'accept': True, 'msg': None} if not minute_str.isdigit(): result_dict['accept'] = False result_dict['msg'] = '分钟数不为整数' return result_dict minute_num = int(minute_str) if minute_num >= 60: result_dict['accept'] = False result_dict['msg'] = '分钟数不能大于等于60' return result_dict return result_dict def validate_second(self): second_str = self.input_second.get() result_dict = {'accept': True, 'msg': None} if not second_str.isdigit(): result_dict['accept'] = False result_dict['msg'] = '秒数不为整数' return result_dict second_num = int(second_str) if second_num >= 60: result_dict['accept'] = False result_dict['msg'] = '秒数不能大于60' return result_dict return result_dict def edit(self): self.toggle_edit() def toggle_edit(self): if self.edit_status: self.switch_to_edit() else: self.completed_edit() self.edit_status = not self.edit_status def switch_to_edit(self): self.show_edit() self.start_button.config({'state': 'disabled'}) self.force_pause() self.edit_str.set('保存') self.set_current_time_to_input() def force_pause(self): if self.current_status: self.toggle() def set_current_time_to_input(self): time_format_dict = self.format_time() hour = time_format_dict['hour'] minute = time_format_dict['minute'] second = time_format_dict['second'] self.hour_str.set(hour) self.minute_str.set(minute) self.second_str.set(second) def completed_edit(self): if self.validate_time(): self.set_time(self.get_time()) self.edit_str.set('编辑') self.set_label_time() self.hide_edit() self.start_button.config({'state': 'normal'}) else: self.edit_status = not self.edit_status def hide_edit(self): self.timer_frame.pack_forget() self.label.pack(side='top', fill='both', before=self.start_button) def show_edit(self): self.timer_frame.pack(side='top', fill='both', before=self.start_button) self.label.pack_forget()
class Interface(Tk): def __init__(self,parent): Tk.__init__(self,parent) self.parent = parent self.attributes('-fullscreen',True) self.currentScreem = "" self.titulos_treeview = ["Id", "Descricao", "Data"] self.menu() self.Home() def menu(self): topo = self.winfo_toplevel() self.menuBar = Menu(topo) mnuOpcoes = Menu(self.menuBar, tearoff=0) mnuOpcoes.add_command(label="Sair", command=self.processaSair) self.menuBar.add_cascade(label="Opções", menu=mnuOpcoes) topo.config(menu=self.menuBar) # Posiciona o menu no topo da janela def toobar(self,screem): self.toobarFrame = Frame(self) self.toobarFrame.pack(side="top",pady=5,fill="x") # Button de home self.homeB=Button(self.toobarFrame,justify = "left", command=self.Home) self.photoHome=PhotoImage(file="img/home.png") self.homeB.config(image=self.photoHome,width="20",height="20") self.homeB.pack(side="left", padx=5) if screem == "home": self.homeB.config(state="disabled") # Button de recarregar self.refreshB=Button(self.toobarFrame,justify = "left",command=self.atualizaTabela) self.photoRefresh=PhotoImage(file="img/refresh.png") self.refreshB.config(image=self.photoRefresh,width="20",height="20") self.refreshB.pack(side="left") if screem != "home": self.refreshB.config(state="disabled") # Entry de busca self.searchE = Entry(self.toobarFrame) self.searchE.pack(side="left",padx=5) self.searchE.bind("<Return>",lambda x: self.buscaComFiltro()) if screem != "home": self.searchE.config(state="disabled") # Button de busca self.searchB=Button(self.toobarFrame,justify = "left",command=self.buscaComFiltro) self.photoSearch=PhotoImage(file="img/search.png") self.searchB.config(image=self.photoSearch,width="20",height="20") self.searchB.pack(side="left") if screem != "home": self.searchB.config(state="disabled") self.addB=Button(self.toobarFrame,justify = "left",command=self.Formulario) self.photoAdd=PhotoImage(file="img/add.png") self.addB.config(image=self.photoAdd,width="20",height="20") self.addB.pack(side="left", padx=5) if screem == "formulario": self.addB.config(state="disabled") def Home(self): if self.currentScreem == "formulario": self.toobarFrame.pack_forget() self.telaFormulario.pack_forget() self.toobar("home") self.telaHome = Frame(None) self.telaHome.pack(fill="both") self.tabela = ttk.Treeview( self.telaHome,columns=self.titulos_treeview,show="headings") self.scbar = Scrollbar(self.telaHome,orient="vertical",command=self.tabela.yview) self.tabela.configure(yscrollcommand=self.scbar.set) self.scbar.pack(side="right", fill="y") self.tabela.pack(side="top", fill='both') self.atualizaTabela() self.currentScreem = "home" def Formulario(self,tarefa=[]): self.toobarFrame.pack_forget() self.telaHome.pack_forget() self.toobar("formulario") self.telaFormulario = Frame(None) self.telaFormulario.pack() self.btnAcao = Button( self.telaFormulario,text="Cadastrar",command=self.cadastroTarefa) descricao = "" data = "" if tarefa != []: self.btnAcao = Button( self.telaFormulario,text="Atualizar",command=self.cadastroTarefa) descricao = tarefa[1] data = tarefa[2] self.lblDescricao = Label(self.telaFormulario, text="Descrição") self.lblDescricao.pack() self.entryDescricao = Entry(self.telaFormulario) self.entryDescricao.insert(0,descricao) self.entryDescricao.pack() self.lblData= Label(self.telaFormulario,text="Data") self.lblData.pack() self.entryData = Entry(self.telaFormulario) self.entryData.insert(0,data) self.entryData.pack() if tarefa != []: self.tarefa_id = tarefa[0] self.btnAcao = Button( self.telaFormulario,text="Atualizar",command=self.atualizarTarefa) self.btnExcluir = Button( self.telaFormulario,text="Excluir",command=self.excluirTarefa) self.btnExcluir.pack(pady=10,side="bottom") self.btnAcao.pack(pady=10,side="bottom") self.lblres= Label(self.telaFormulario, text="") self.lblres.pack() self.currentScreem = "formulario" def clicarLinha(self, event): item = self.tabela.selection() for i in item: self.Formulario(self.tabela.item(i, "values")) def buscaSemFiltro(self): banco = Banco() try: c = banco.conexao.cursor() c.execute("select * from tarefas;") self.tarefas = [] for linha in c: obj = {} obj["id"] = linha[0] obj["descricao"] = linha[1] obj["data"] = linha[2] self.tarefas.append(obj) c.close() print("Busca sem filtro feita com sucesso!") except: print("Ocorreu um erro na busca do usuário") def atualizaTabela(self): self.buscaSemFiltro() self.mostrarTarefas(self.tarefas) def buscaComFiltro(self): busca = self.searchE.get() self.searchE.delete("0", "end") filmes_busca = [] banco = Banco() try: c = banco.conexao.cursor() query = "select * from tarefas where id like '%{0}%' or descricao like '%{0}%' or data like '%{0}%';".format(busca) c.execute(query) for linha in c: obj = {} obj["id"] = linha[0] obj["descricao"] = linha[1] obj["data"] = linha[2] filmes_busca.append(obj) c.close() print("Busca com filtro feita com sucesso!") except: print("Ocorreu um erro na busca do usuário") self.mostrarTarefas(filmes_busca) def mostrarTarefas(self, tarefas): for i in self.tabela.get_children(): self.tabela.delete(i) for col in self.titulos_treeview: self.tabela.heading(col, text=col.title()) for tarefa in tarefas: item = (tarefa['id'], tarefa['descricao'], tarefa['data']) self.tabela.insert('', 'end', values=item) self.tabela.pack(side="top", fill='both') self.tabela.bind("<Double-1>", self.clicarLinha) def cadastroTarefa(self): descricao = self.entryDescricao.get() data = self.entryData.get() if len(descricao)<1 or len(data)<1: self.changeMSG("Todos os campos devem ser preenchidos",'red') else: banco = Banco() try: c = banco.conexao.cursor() query = "insert into tarefas (descricao,data) values ('{0}','{1}');".format(descricao,data) c.execute(query) banco.conexao.commit() if c.lastrowid > 0: self.changeMSG("Tarefa cadastrado com sucesso","green") self.entryDescricao.delete("0","end") self.entryData.delete("0","end") print("sucesso") else: print("erro") self.changeMSG("Ocorreu um erro no cadastro da tarefa","red") c.close() except: print("exceção") self.changeMSG("Ocorreu um erro no cadastro da tarefa","red") def atualizarTarefa(self): descricao = self.entryDescricao.get() data = self.entryData.get() if len(descricao)<1 or len(data)<1: self.changeMSG("Todos os campos devem ser preenchidos",'red') else: banco = Banco() try: c = banco.conexao.cursor() query = "update tarefas set descricao = '{0}',data = '{1}' where id = {2};".format(descricao,data,self.tarefa_id) c.execute(query) banco.conexao.commit() self.changeMSG("Tarefa atualizada com sucesso","green") self.entryDescricao.delete("0","end") self.entryData.delete("0","end") print("sucesso") c.close() except: print("exceção") self.changeMSG("Ocorreu um erro no cadastro da tarefa","red") self.tarefa_id = 0 def excluirTarefa(self): banco = Banco() try: c = banco.conexao.cursor() query = "delete from tarefas where id ={0};".format(self.tarefa_id) c.execute(query) banco.conexao.commit() self.changeMSG("Tarefa excluida com sucesso","green") self.entryDescricao.delete("0","end") self.entryData.delete("0","end") print("sucesso") c.close() except: print("exceção") self.changeMSG("Ocorreu um erro no cadastro da tarefa","red") self.tarefa_id = 0 def changeMSG(self,texto,color): self.lblres.destroy() self.lblres= Label(self.telaFormulario, text=texto,bg='{}'.format(color)) self.lblres.pack(pady=5, side="bottom") def processaSair(self): self.destroy()
class TrailBlazerGUI: ''' Defines the graphical user interface, which displays and allows users to interact with various modules. ''' def __init__(self, master): ''' Initializes the GUI. ''' self.master = master self.bg = "#90EE90" self.fg = "#654321" self.e_page = "empty" master.title("Trail Blazer") master.geometry("1920x1080") master.configure(bg=self.bg) master.bind("<Escape>", self.close) self.start = Frame(master, height=1080, width=1920, bg=self.bg) self.start.pack() self.start.focus_set() self.start.bind("<Return>", self.login_page) self.greet = Label(self.start, text="Welcome to our Route Suggestion GUI!", font=("sans serif", 50), fg=self.fg, bg=self.bg, pady=10) self.greet.pack() self.intro = Message(self.start, text="We are writing software to help generate and visualize new routes for runners, walkers, and bikers. \nWe are creating this for our Software Design final project.", font=("sans serif", 20), width=1900, justify=CENTER, fg=self.fg, bg=self.bg, pady=10) self.intro.pack() self.buttons1 = Frame(self.start, width=500, bg=self.bg) self.buttons1.pack() self.proceed = Button(self.buttons1, text="Proceed", bg="#64e764", fg="#654321", pady=5, activebackground="#bcf5bc", activeforeground="#8b5d2e", command=self.login_page) self.proceed.grid(row=0, column=0) self.cancel = Button(self.buttons1, text="Cancel", bg="#64e764", fg="#654321", pady=5, activebackground="#bcf5bc", activeforeground="#8b5d2e", command=master.quit) self.cancel.grid(row=0, column=1) self.logo = PhotoImage(file="images/trail_blazer_logo.gif") self.logo_disp = Label(self.start, image=self.logo, fg=self.fg, bg=self.bg) self.logo_disp.pack(side=BOTTOM) def login_page(self, event=None): ''' Displays a page where the user can login to find a route. ''' if self.e_page != "empty": self.e_page.pack_forget() self.e_page.destroy() else: self.start.pack_forget() self.start.destroy() self.l_page = Frame(self.master, height=1080, width=1920, bg=self.bg) self.l_page.pack() self.l_page.focus_set() self.l_page.bind("<Return>", self.valid_login) self.l_page.bind("<Escape>", self.close) self.request = Label(self.l_page, text="Please log in to continue.", font=("sans serif", 20), fg=self.fg, bg=self.bg, pady=20) self.request.pack() self.login = Frame(self.l_page, width=1000, bg=self.bg) self.login.pack() self.login.bind("<Return>", self.valid_login) self.first = Label(self.login, text="First Name = ", font=("sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.first.grid(row=0, sticky=E) self.first_in = Entry(self.login, font=("sans serif", 15), exportselection=0, cursor="xterm") self.first_in.bind("<Return>", self.valid_login) self.first_in.grid(row=0, column=1, columnspan=3) self.last = Label(self.login, text="Last Name = ", font=("sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.last.grid(row=1, sticky=E) self.last_in = Entry(self.login, font=("sans serif", 15), exportselection=0, cursor="xterm") self.last_in.bind("<Return>", self.valid_login) self.last_in.grid(row=1, column=1, columnspan=3) self.user = Label(self.login, text="Username = "******"sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.user.grid(row=2, sticky=E) self.user_in = Entry(self.login, font=("sans serif", 15), exportselection=0, cursor="xterm") self.user_in.bind("<Return>", self.valid_login) self.user_in.grid(row=2, column=1, columnspan=3) self.pss = Label(self.login, text="Password = "******"sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.pss.grid(row=3, sticky=E) self.pss_in = Entry(self.login, font=("sans serif", 15), exportselection=0, cursor="xterm", show="*") self.pss_in.bind("<Return>", self.valid_login) self.pss_in.grid(row=3, column=1, columnspan=3) self.buttons2 = Frame(self.l_page, width=500, bg=self.bg) self.buttons2.pack() self.submit = Button(self.buttons2, text="Submit", bg="#64e764", fg="#654321", pady=5, activebackground="#bcf5bc", activeforeground="#8b5d2e", command=self.valid_login) self.submit.bind("<Return>", self.valid_login) self.submit.grid(row=0, column=0) self.cancel = Button(self.buttons2, text="Cancel", bg="#64e764", fg="#654321", pady=5, activebackground="#bcf5bc", activeforeground="#8b5d2e", command=self.master.quit) self.cancel.bind("<Return>", self.valid_login) self.cancel.grid(row=0, column=1) def home_page(self, event=None): ''' Displays the GUI home page, where user can find the weather of a given location and request a route. ''' first_name = self.first_in.get() last_name = self.last_in.get() self.l_page.pack_forget() self.l_page.destroy() self.h_page = Frame(self.master, height=1080, width=1920, bg=self.bg) self.h_page.pack() self.h_page.focus_set() self.h_page.bind("<Return>", self.find_route) self.h_page.bind("<Escape>", self.close) self.hello = Label(self.h_page, text="Hello! Welcome to your profile page!", font=("sans serif", 50), bg=self.bg, fg=self.fg, pady=20) self.hello.pack() self.weather_init = Frame(self.h_page, width=1000, bg=self.bg) self.weather_init.pack() self.weather_init.bind("<Return>", self.get_forecast) self.location = Label(self.weather_init, text="Current Location = ", font=("sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.location.grid(row=0, sticky=E) self.location_in = Entry(self.weather_init, font=("sans serif", 15), exportselection=0, cursor="xterm") self.location_in.bind("<Return>", self.get_forecast) self.location_in.grid(row=0, column=1) self.buttons5 = Frame(self.h_page, width=500, bg=self.bg) self.buttons5.pack() self.buttons5.bind("<Return>", self.get_forecast) self.weatherby = Button(self.buttons5, text="Find Weather", bg="#64e764", fg="#654321", activebackground="#bcf5bc", activeforeground="#8b5d2e", pady=5, command=self.get_forecast) self.weatherby.grid(row=0, column=0) self.name_is = Label(self.h_page, text="Where would you like to go, %s %s?" % (first_name, last_name), font=("sans serif", 15), fg=self.fg, bg=self.bg, pady=10) self.name_is.pack() self.profile = Frame(self.h_page, width=1000, bg=self.bg) self.profile.pack() self.profile.bind("<Return>", self.find_route) self.loc = Label(self.profile, text="Starting Location:", font=("sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.loc.grid(row=0, sticky=E) self.lat = Label(self.profile, text="Latitiude = ", font=("sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.lat.grid(row=1, column=0) self.lat_in = Entry(self.profile, font=("sans serif", 15), exportselection=0, cursor="xterm") self.lat_in.bind("<Return>", self.find_route) self.lat_in.insert(0, "42.292922") if self.profile.focus_get() == self.lat_in: self.lat_in.delete() self.lat_in.grid(row=1, column=1) self.lng = Label(self.profile, text="Longitude = ", font=("sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.lng.grid(row=1, column=2) self.lng_in = Entry(self.profile, font=("sans serif", 15), exportselection=0, cursor="xterm") self.lng_in.bind("<Return>", self.find_route) self.lng_in.insert(0, "-71.263073") if self.profile.focus_get() == self.lat_in: self.lat_in.delete() self.lng_in.grid(row=1, column=3) self.dist = Label(self.profile, text="Distance(km) = ", font=("sans serif", 15), anchor=W, bg=self.bg, fg=self.fg, pady=10) self.dist.grid(row=2, sticky=E) self.dist_in = Entry(self.profile, font=("sans serif", 15), exportselection=0, cursor="xterm") self.dist_in.bind("<Return>", self.find_route) self.dist_in.grid(row=2, column=1) self.dist_max = Label(self.profile, text="Maximum distance = 2", font=("sans serif", 10), anchor=W, bg=self.bg, fg=self.fg, pady=10, padx=10) self.dist_max.grid(row=2, column=2, sticky=E) self.buttons3 = Frame(self.h_page, width=500, bg=self.bg) self.buttons3.pack() self.enter = Button(self.buttons3, text="Find Route", bg="#64e764", fg="#654321", activebackground="#bcf5bc", activeforeground="#8b5d2e", pady=5, command=self.find_route) self.enter.bind("<Return>", self.find_route) self.enter.grid(row=0, column=0) self.elev = Button(self.buttons3, text="View Elevation", bg="#64e764", fg="#654321", activebackground="#bcf5bc", activeforeground="#8b5d2e", pady=5, command=self.find_elevation) self.elev.bind("<Return>", self.find_elevation) self.elev.grid(row=0, column=1) self.cancel = Button(self.buttons3, text="Cancel", bg="#64e764", fg="#654321", activebackground="#bcf5bc", activeforeground="#8b5d2e", pady=5, command=self.master.quit) self.cancel.grid(row=0, column=2) def error(self, event=None): ''' Displays an error page if a user did not provide all of the required information. ''' self.l_page.pack_forget() self.l_page.destroy() self.e_page = Frame(self.master, height=1080, width=1920, bg=self.bg) self.e_page.pack() self.e_page.focus_set() self.e_page.bind("<Return>", self.login_page) self.e_page.bind("<Escape>", self.close) self.err_title = Label(self.e_page, text="Error: Missing Information", font=("sans serif", 50), bg=self.bg, fg=self.fg, pady=10) self.err_title.pack() self.err_mss = Message(self.e_page, text="Your submission was missing some data. All fields are rquired.\nPlease return to fill out all fields.", font=("sans serif", 20), width=1900, justify=CENTER, fg=self.fg, bg=self.bg, pady=10) self.err_mss.pack() self.buttons4 = Frame(self.e_page, width=500, bg=self.bg) self.buttons4.pack() self.ret = Button(self.buttons4, text="Return", bg="#64e764", fg="#654321", pady=5, activebackground="#bcf5bc", activeforeground="#8b5d2e", command=self.login_page) self.ret.grid(row=0, column=0) self.cancel = Button(self.buttons4, text="Cancel", bg="#64e764", fg="#654321", pady=5, activebackground="#bcf5bc", activeforeground="#8b5d2e", command=self.master.quit) self.cancel.grid(row=0, column=1) def valid_login(self, event=None): ''' Checks if a user provided all of the necessary information to login. ''' firstname = self.first_in.get() lastname = self.last_in.get() username = self.user_in.get() password = self.pss_in.get() if not firstname and not lastname and not username and not password: return self.error() else: return self.home_page() def get_forecast(self, event=None): ''' Gets and displays a weather forecast for a given location. ''' from weather import Weather, Unit self.weather = Weather(unit=Unit.FAHRENHEIT) self.local = self.weather.lookup_by_location(self.location_in.get()) self.condition = self.local.condition self.forecasts = self.local.forecast self.forecast = self.forecasts[1] self.location.destroy() self.location_in.destroy() self.buttons5.destroy() self.weather_1 = Label(self.weather_init, text="Today's weather will be %s and %s F" % (self.condition.text, self.condition.temp), font=("sans serif", 17), justify=CENTER, fg=self.fg, bg=self.bg) self.weather_1.pack() self.weather_2 = Label(self.weather_init, text="with a high of %s F and a low of %s F." % (self.forecast.high, self.forecast.low), font=("sans serif", 15), justify=CENTER, fg=self.fg, bg=self.bg) self.weather_2.pack() self.weather_3 = Label(self.weather_init, text="According to Yahoo weather on %s." % (self.condition.date), font=("sans serif", 10), justify=CENTER, fg=self.fg, bg=self.bg, pady=5) self.weather_3.pack() def find_route(self, event=None): ''' Finds and plots a route. ''' api = overpy.Overpass() lat = float(self.lat_in.get()) lng = float(self.lng_in.get()) radius = 0.01 distance = float(self.dist_in.get()) self.route = intersections.graph_it(api, lat, lng, radius, distance) intersections.plot_graph(self.route) def find_elevation(self, event=None): ''' Finds and graphs the elevations of points along a route. ''' distance = float(self.dist_in.get()) route_coords = intersections.find_route_coords(self.route) unzipped = list(zip(*route_coords)) get_elevations.plot_elevation(get_elevations.get_elevation_list(unzipped[0], unzipped[1]), distance) def close(self, event=None): self.master.quit()
class QuantMonitor(object): # 背景色 bgColor = rgb_to_hex(245, 245, 245) bgColorW = "white" def __init__(self, frame, control, language): self.parentFrame = frame self._controller = control self.language = language # 初始化策略状态字典 self._initStrategyStatus() # 策略编号初始值 self._strategyNum = 1 # Monitor不同标签的背景色 self.rColor = self.bgColorW self.lColor = self.bgColor self.sColor = self.bgColor self.eColor = self.bgColor self.createButtonFrame() # 执行列表、监控日志、信号记录、错误 self.executeList = Frame(self.parentFrame) self.monitorLog = Frame(self.parentFrame) self.sigRecord = Frame(self.parentFrame) self.errRecord = Frame(self.parentFrame) self.executeList.pack(side=TOP, fill=BOTH, expand=YES) self.monText = None self.sigText = None self.errText = None def createButtonFrame(self): btnFrame = Frame(self.parentFrame, height=30, bg=self.bgColor) btnFrame.pack_propagate(0) btnFrame.pack(side=TOP, fill=X) # 利用frame做出button的黑色边框 # f1 = Frame(btnFrame, highlightbackground="black", highlightthickness=1, bd=0) # f1.pack(side=LEFT) self.runBtn = Button(btnFrame, text="策略运行", relief=FLAT, padx=14, pady=1.5, bg=self.rColor, bd=0, highlightthickness=1, command=self.toMonFrame) self.logBtn = Button(btnFrame, text="运行日志", relief=FLAT, padx=14, pady=1.5, bg=self.lColor, bd=0, highlightthickness=1, command=self.toLogFrame) self.sigBtn = Button(btnFrame, text="信号记录", relief=FLAT, padx=14, pady=1.5, bg=self.sColor, bd=0, highlightthickness=1, command=self.toSigFrame) self.errBtn = Button(btnFrame, text="错误信息", relief=FLAT, padx=14, pady=1.5, bg=self.eColor, bd=0, highlightthickness=1, command=self.toErrFrame) self.runBtn.pack(side=LEFT, expand=NO) self.logBtn.pack(side=LEFT, expand=NO) self.sigBtn.pack(side=LEFT, expand=NO) self.errBtn.pack(side=LEFT, expand=NO) for btn in (self.runBtn, self.logBtn, self.sigBtn, self.errBtn): btn.bind("<Enter>", self.handlerAdaptor(self.onEnter, button=btn)) btn.bind("<Leave>", self.handlerAdaptor(self.onLeave, button=btn)) def createMonitor(self): # monitorRightBar = Scrollbar(self.monitorLog) # monitorRightBar.pack(side=RIGHT, fill=Y), yscrollcommand=monitorRightBar.set self.monText = MonitorText(self.monitorLog, height=20, bd=0) self.monText.createScrollbar() self.monText.pack(fill=BOTH, expand=YES) def createSignal(self): self.sigText = SignalText(self.sigRecord, height=20, bd=0) self.sigText.createScrollbar() self.sigText.pack(fill=BOTH, expand=YES) def createExecute(self): # headList = ["编号", "策略名称", "策略状态", "最终权益", "胜率", "净利润", "总盈利", "总亏损", "可用资金", # "夏普比率", "风险率", "手续费", "最大资产回撤", "最大资产回撤时间", "资产最大值", "资产最小值", # "最大连续盈利次数", "最大连续亏损次数"] # headList = ["编号", "策略名称", "策略状态", "频率","保证金比例", "手续费", # "初始资金", "总盈利", "总亏损", "可用资金"] # headList = ["编号", "策略名称", "策略状态", "运行类型", "初始资金", "合约", "开始时间", "结束时间", "权益"] headList = ["编号", "策略名称", "合约", "运行状态", "实盘运行"] self.executeBar = ttk.Scrollbar(self.executeList, orient="vertical") self.executeBar.pack(side=RIGHT, fill=Y) self.executeListTree = ttk.Treeview(self.executeList, show="headings", height=28, columns=tuple(headList), yscrollcommand=self.executeBar.set, style="Filter.Treeview") self.executeBar.config(command=self.executeListTree.yview) self.executeListTree.pack(fill=BOTH, expand=YES) self.executeListTree.bind("<Button-3>", self.createMenu) for key in tuple(headList): self.executeListTree.column(key, minwidth=20, width=55, anchor=CENTER) self.executeListTree.heading(key, text=key) def createMenu(self, event): """创建运行策略右键菜单""" RunMenu(self._controller, self.executeListTree).popupmenu(event) def _initStrategyStatus(self): self.statusDict = { ST_STATUS_NONE: "初始状态", ST_STATUS_HISTORY: "历史回测", ST_STATUS_CONTINUES: "实时触发", ST_STATUS_PAUSE: "暂停", ST_STATUS_QUIT: "停止" } def _getStrategyStatus(self, key): return self.statusDict[key] def _formatMonitorInfo(self, dataDict): """ 格式化监控需要的信息 :param dataDict: 策略的所有信息 :return: 需要展示的信息 """ status = self._getStrategyStatus(dataDict["StrategyState"]) runType = "是" if dataDict['Config']['RunMode']['Actual']['SendOrder2Actual'] else "否" values = [ dataDict['StrategyId'], dataDict['StrategyName'], dataDict['Config']['Contract'], status, runType, ] return values def updateSingleExecute(self, dataDict): values = self._formatMonitorInfo(dataDict) self.executeListTree.insert("", END, iid=dataDict['StrategyId'], values=tuple(values), tag=0) def createErr(self): # 错误信息展示 self.errText = ErrorText(self.errRecord, height=20, bd=0) self.errText.createScrollbar() self.errText.pack(fill=BOTH, expand=YES) def updateRun(self): pass def updateLogText(self): guiQueue = self._controller.get_logger().getGuiQ() try: data = guiQueue.get_nowait() except: return else: self.monText.setText(data) def updateSigText(self): sigQueue = self._controller.get_logger().getSigQ() try: sigData = sigQueue.get_nowait() except: return else: # self.toSigFrame() self.sigText.setText(sigData) def updateErrText(self): errQueue = self._controller.get_logger().getErrQ() try: errData = errQueue.get_nowait() except: return else: self.toErrFrame() self.errText.setText(errData) def toMonFrame(self): self.runBtn.config(bg="white") self.rColor = self.runBtn['bg'] self.lColor = self.bgColor self.sColor = self.bgColor self.eColor = self.bgColor self.errBtn.config(bg=self.rColor) self.sigBtn.config(bg=self.sColor) self.logBtn.config(bg=self.lColor) self.monitorLog.pack_forget() self.sigRecord.pack_forget() self.errRecord.pack_forget() self.executeList.pack(side=TOP, fill=BOTH, expand=YES) def toLogFrame(self): self.logBtn.config(bg="white") self.lColor = self.logBtn['bg'] self.rColor = self.bgColor self.sColor = self.bgColor self.eColor = self.bgColor self.runBtn.config(bg=self.rColor) self.sigBtn.config(bg=self.sColor) self.errBtn.config(bg=self.eColor) self.sigRecord.pack_forget() self.executeList.pack_forget() self.errRecord.pack_forget() self.monitorLog.pack(side=TOP, fill=BOTH, expand=YES) def toSigFrame(self): self.sigBtn.config(bg="white") self.sColor = self.sigBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.eColor = self.bgColor self.runBtn.config(bg=self.rColor) self.logBtn.config(bg=self.lColor) self.errBtn.config(bg=self.eColor) self.monitorLog.pack_forget() self.executeList.pack_forget() self.errRecord.pack_forget() self.sigRecord.pack(side=TOP, fill=BOTH, expand=YES) def toErrFrame(self): self.errBtn.config(bg="white") self.eColor = self.errBtn['bg'] self.lColor = self.bgColor self.rColor = self.bgColor self.sColor = self.bgColor self.runBtn.config(bg=self.rColor) self.sigBtn.config(bg=self.sColor) self.logBtn.config(bg=self.lColor) self.parentFrame.update() self.monitorLog.pack_forget() self.executeList.pack_forget() self.sigRecord.pack_forget() self.errRecord.pack(side=TOP, fill=BOTH, expand=YES) def handlerAdaptor(self, fun, **kwargs): return lambda event, fun=fun, kwargs=kwargs: fun(event, **kwargs) def onEnter(self, event, button): if button == self.runBtn: button.config(bg='white') self.logBtn.config(bg=self.bgColor) self.sigBtn.config(bg=self.bgColor) self.errBtn.config(bg=self.bgColor) elif button == self.logBtn: button.config(bg='white') self.runBtn.config(bg=self.bgColor) self.sigBtn.config(bg=self.bgColor) self.errBtn.config(bg=self.bgColor) elif button == self.sigBtn: button.config(bg='white') self.runBtn.config(bg=self.bgColor) self.logBtn.config(bg=self.bgColor) self.errBtn.config(bg=self.bgColor) else: button.config(bg='white') self.runBtn.config(bg=self.bgColor) self.logBtn.config(bg=self.bgColor) self.sigBtn.config(bg=self.bgColor) def onLeave(self, event, button): button.config(bg=rgb_to_hex(227, 230, 233)) if button == self.runBtn: button['bg'] = self.rColor self.logBtn['bg'] = self.lColor self.sigBtn['bg'] = self.sColor self.errBtn['bg'] = self.eColor elif button == self.logBtn: button['bg'] = self.lColor self.runBtn['bg'] = self.rColor self.sigBtn['bg'] = self.sColor self.errBtn['bg'] = self.eColor elif button == self.sigBtn: button['bg'] = self.sColor self.runBtn['bg'] = self.rColor self.logBtn['bg'] = self.lColor self.errBtn['bg'] = self.eColor else: button['bg'] = self.eColor self.runBtn['bg'] = self.rColor self.logBtn['bg'] = self.lColor self.sigBtn['bg'] = self.sColor def deleteStrategy(self, strategyId): """删除策略""" self.executeListTree.delete(strategyId) def updateStatus(self, strategyId, dataDict): """更新策略ID对应的策略状态""" values = self._formatMonitorInfo(dataDict) self.executeListTree.item(strategyId, values=values) # self.executeListTree.update()
class Application(Frame): def __init__(self, master=None): super().__init__(master) self.pack() # First row f1 = LabelFrame(self, text='NAND file with No$GBA footer', padx=10, pady=10) # NAND Button self.nand_mode = False nand_icon = PhotoImage( data=('R0lGODlhEAAQAIMAAAAAADMzM2ZmZpmZmczMzP///wAAAAAAAAA' 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAMAAAYALAAAAAAQAB' 'AAAARG0MhJaxU4Y2sECAEgikE1CAFRhGMwSMJwBsU6frIgnR/bv' 'hTPrWUSDnGw3JGU2xmHrsvyU5xGO8ql6+S0AifPW8kCKpcpEQA7')) self.nand_button = Button(f1, image=nand_icon, command=self.change_mode, state=DISABLED) self.nand_button.image = nand_icon self.nand_button.pack(side='left') self.nand_file = StringVar() Entry(f1, textvariable=self.nand_file, state='readonly', width=40).pack(side='left') Button(f1, text='...', command=self.choose_nand).pack(side='left') f1.pack(padx=10, pady=10, fill=X) # Second row f2 = Frame(self) # Check boxes self.checks_frame = Frame(f2) # Install TWiLight check self.twilight = IntVar() self.twilight.set(1) twl_chk = Checkbutton( self.checks_frame, text='Install latest TWiLight Menu++ on custom firmware', variable=self.twilight) twl_chk.pack(padx=10, anchor=W) # Clean files check self.clean_downloaded = IntVar() self.clean_downloaded.set(1) clean_chk = Checkbutton(self.checks_frame, text='Clean downloaded files after completion', variable=self.clean_downloaded) clean_chk.pack(padx=10, anchor=W) self.checks_frame.pack(fill=X) # NAND operation frame self.nand_frame = LabelFrame(f2, text='NAND operation', padx=10, pady=10) self.nand_operation = IntVar() self.nand_operation.set(0) Radiobutton(self.nand_frame, text='Remove No$GBA footer', variable=self.nand_operation, value=0, command=lambda: self.enable_entries(False)).pack(anchor=W) Radiobutton(self.nand_frame, text='Add No$GBA footer', variable=self.nand_operation, value=1, command=lambda: self.enable_entries(True)).pack(anchor=W) fl = Frame(self.nand_frame) self.cid_label = Label(fl, text='eMMC CID', state=DISABLED) self.cid_label.pack(anchor=W, padx=(24, 0)) self.cid = StringVar() self.cid_entry = Entry(fl, textvariable=self.cid, width=20, state=DISABLED) self.cid_entry.pack(anchor=W, padx=(24, 0)) fl.pack(side='left') fr = Frame(self.nand_frame) self.console_id_label = Label(fr, text='Console ID', state=DISABLED) self.console_id_label.pack(anchor=W) self.console_id = StringVar() self.console_id_entry = Entry(fr, textvariable=self.console_id, width=20, state=DISABLED) self.console_id_entry.pack(anchor=W) fr.pack(side='right') f2.pack(fill=X) # Third row f3 = Frame(self) self.start_button = Button(f3, text='Start', width=16, command=self.hiya, state=DISABLED) self.start_button.pack(side='left', padx=(0, 5)) Button(f3, text='Quit', command=root.destroy, width=16).pack(side='left', padx=(5, 0)) f3.pack(pady=(10, 20)) self.folders = [] self.files = [] ################################################################################################ def change_mode(self): if (self.nand_mode): self.nand_frame.pack_forget() self.checks_frame.pack(padx=10, anchor=W) self.nand_mode = False else: if askokcancel( 'Warning', ('You are about to enter NAND mode. Do it only if you know ' 'what you are doing. Proceed?'), icon=WARNING): self.checks_frame.pack_forget() self.nand_frame.pack(padx=10, pady=(0, 10), fill=X) self.nand_mode = True ################################################################################################ def enable_entries(self, status): self.cid_label['state'] = (NORMAL if status else DISABLED) self.cid_entry['state'] = (NORMAL if status else DISABLED) self.console_id_label['state'] = (NORMAL if status else DISABLED) self.console_id_entry['state'] = (NORMAL if status else DISABLED) ################################################################################################ def choose_nand(self): name = askopenfilename(filetypes=(('nand.bin', '*.bin'), ('DSi-1.mmc', '*.mmc'))) self.nand_file.set(name) self.nand_button['state'] = (NORMAL if name != '' else DISABLED) self.start_button['state'] = (NORMAL if name != '' else DISABLED) ################################################################################################ def hiya(self): if not self.nand_mode: showinfo( 'Info', 'Now you will be asked to choose the SD card path that will be used ' 'for installing the custom firmware (or an output folder).\n\nIn order to avoid ' 'boot errors please assure it is empty before continuing.') self.sd_path = askdirectory() # Exit if no path was selected if self.sd_path == '': return # If adding a No$GBA footer, check if CID and ConsoleID values are OK elif self.nand_operation.get() == 1: cid = self.cid.get() console_id = self.console_id.get() # Check lengths if len(cid) != 32: showerror('Error', 'Bad eMMC CID') return elif len(console_id) != 16: showerror('Error', 'Bad Console ID') return # Parse strings to hex try: cid = bytearray.fromhex(cid) except ValueError: showerror('Error', 'Bad eMMC CID') return try: console_id = bytearray(reversed(bytearray.fromhex(console_id))) except ValueError: showerror('Error', 'Bad Console ID') return dialog = Toplevel(self) # Open as dialog (parent disabled) dialog.grab_set() dialog.title('Status') # Disable maximizing dialog.resizable(0, 0) frame = Frame(dialog, bd=2, relief=SUNKEN) scrollbar = Scrollbar(frame) scrollbar.pack(side=RIGHT, fill=Y) self.log = ThreadSafeText(frame, bd=0, width=52, height=20, yscrollcommand=scrollbar.set) self.log.pack() scrollbar.config(command=self.log.yview) frame.pack() Button(dialog, text='Close', command=dialog.destroy, width=16).pack(pady=10) # Center in window dialog.update_idletasks() width = dialog.winfo_width() height = dialog.winfo_height() dialog.geometry( '%dx%d+%d+%d' % (width, height, root.winfo_x() + (root.winfo_width() / 2) - (width / 2), root.winfo_y() + (root.winfo_height() / 2) - (height / 2))) # Check if we'll be adding a No$GBA footer if self.nand_mode and self.nand_operation.get() == 1: Thread(target=self.add_footer, args=(cid, console_id)).start() else: Thread(target=self.check_nand).start() ################################################################################################ def check_nand(self): self.log.write('Checking NAND file...') # Read the NAND file try: with open(self.nand_file.get(), 'rb') as f: # Go to the No$GBA footer offset f.seek(-64, 2) # Read the footer's header :-) bstr = f.read(0x10) if bstr == b'DSi eMMC CID/CPU': # Read the CID bstr = f.read(0x10) self.cid.set(bstr.hex().upper()) self.log.write('- eMMC CID: ' + self.cid.get()) # Read the console ID bstr = f.read(8) self.console_id.set( bytearray(reversed(bstr)).hex().upper()) self.log.write('- Console ID: ' + self.console_id.get()) # Check we are removing the No$GBA footer if self.nand_mode: Thread(target=self.remove_footer).start() else: Thread(target=self.get_latest_hiyacfw).start() else: self.log.write('ERROR: No$GBA footer not found') except IOError as e: print(e) self.log.write('ERROR: Could not open the file ' + path.basename(self.nand_file.get())) ################################################################################################ def get_latest_hiyacfw(self): # Try to use already downloaded hiyaCFW archive filename = 'hiyaCFW.7z' try: if path.isfile(filename): self.log.write('\nPreparing hiyaCFW...') else: self.log.write('\nDownloading latest hiyaCFW release...') with urlopen( 'https://github.com/RocketRobz/hiyaCFW/releases/latest/download/' + filename) as src, open(filename, 'wb') as dst: copyfileobj(src, dst) self.log.write('- Extracting hiyaCFW archive...') proc = Popen([ _7za, 'x', '-bso0', '-y', filename, 'for PC', 'for SDNAND SD card' ]) ret_val = proc.wait() if ret_val == 0: if self.clean_downloaded.get() == 1: self.files.append(filename) self.folders.append('for PC') self.folders.append('for SDNAND SD card') # Got to decrypt NAND if bootloader.nds is present Thread(target=self.decrypt_nand if path.isfile( 'bootloader.nds') else self.extract_bios).start() else: self.log.write('ERROR: Extractor failed') except (URLError, IOError) as e: print(e) self.log.write('ERROR: Could not get hiyaCFW') except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) ################################################################################################ def extract_bios(self): self.log.write('\nExtracting ARM7/ARM9 BIOS from NAND...') try: proc = Popen([twltool, 'boot2', '--in', self.nand_file.get()]) ret_val = proc.wait() if ret_val == 0: # Hash arm7.bin sha1_hash = sha1() with open('arm7.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- arm7.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) # Hash arm9.bin sha1_hash = sha1() with open('arm9.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- arm9.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) self.files.append('arm7.bin') self.files.append('arm9.bin') Thread(target=self.patch_bios).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def patch_bios(self): self.log.write('\nPatching ARM7/ARM9 BIOS...') try: self.patcher( path.join('for PC', 'bootloader files', 'bootloader arm7 patch.ips'), 'arm7.bin') self.patcher( path.join('for PC', 'bootloader files', 'bootloader arm9 patch.ips'), 'arm9.bin') # Hash arm7.bin sha1_hash = sha1() with open('arm7.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Patched arm7.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) # Hash arm9.bin sha1_hash = sha1() with open('arm9.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Patched arm9.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.arm9_prepend).start() except IOError as e: print(e) self.log.write('ERROR: Could not patch BIOS') Thread(target=self.clean, args=(True, )).start() except Exception as e: print(e) self.log.write('ERROR: Invalid patch header') Thread(target=self.clean, args=(True, )).start() ################################################################################################ def arm9_prepend(self): self.log.write('\nPrepending data to ARM9 BIOS...') try: with open('arm9.bin', 'rb') as f: data = f.read() with open('arm9.bin', 'wb') as f: with open( path.join('for PC', 'bootloader files', 'bootloader arm9 append to start.bin'), 'rb') as pre: f.write(pre.read()) f.write(data) # Hash arm9.bin sha1_hash = sha1() with open('arm9.bin', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Prepended arm9.bin SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.make_bootloader).start() except IOError as e: print(e) self.log.write('ERROR: Could not prepend data to ARM9 BIOS') Thread(target=self.clean, args=(True, )).start() ################################################################################################ def make_bootloader(self): self.log.write('\nGenerating new bootloader...') exe = (path.join('for PC', 'bootloader files', 'ndstool.exe') if sysname == 'Windows' else path.join(sysname, 'ndsblc')) try: proc = Popen([ exe, '-c', 'bootloader.nds', '-9', 'arm9.bin', '-7', 'arm7.bin', '-t', path.join('for PC', 'bootloader files', 'banner.bin'), '-h', path.join('for PC', 'bootloader files', 'header.bin') ]) ret_val = proc.wait() if ret_val == 0: self.files.append('bootloader.nds') # Hash bootloader.nds sha1_hash = sha1() with open('bootloader.nds', 'rb') as f: sha1_hash.update(f.read()) self.log.write('- bootloader.nds SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.decrypt_nand).start() else: self.log.write('ERROR: Generator failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def decrypt_nand(self): self.log.write('\nDecrypting NAND...') try: proc = Popen([ twltool, 'nandcrypt', '--in', self.nand_file.get(), '--out', self.console_id.get() + '.img' ]) ret_val = proc.wait() print("\n") if ret_val == 0: self.files.append(self.console_id.get() + '.img') Thread(target=self.win_extract_nand if ( sysname == 'Windows' and _7z is not None ) else self.extract_nand).start() else: self.log.write('ERROR: Decryptor failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def win_extract_nand(self): self.log.write('\nExtracting files from NAND...') try: proc = Popen([ _7z, 'x', '-bso0', '-y', self.console_id.get() + '.img', '0.fat' ]) ret_val = proc.wait() if ret_val == 0: self.files.append('0.fat') proc = Popen( [_7z, 'x', '-bso0', '-y', '-o' + self.sd_path, '0.fat']) ret_val = proc.wait() if ret_val == 0: Thread(target=self.get_launcher).start() else: self.log.write( 'ERROR: Extractor failed, please update 7-Zip') if path.exists(fatcat): self.log.write('\nTrying with fatcat...') Thread(target=self.extract_nand).start() else: Thread(target=self.clean, args=(True, )).start() else: self.log.write('ERROR: Extractor failed') if path.exists(fatcat): self.log.write('\nTrying with fatcat...') Thread(target=self.extract_nand).start() else: Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) if path.exists(fatcat): self.log.write('\nTrying with fatcat...') Thread(target=self.extract_nand).start() else: Thread(target=self.clean, args=(True, )).start() ################################################################################################ def extract_nand(self): self.log.write('\nExtracting files from NAND...') try: # DSi first partition offset: 0010EE00h proc = Popen([ fatcat, '-O', '1109504', '-x', self.sd_path, self.console_id.get() + '.img' ]) ret_val = proc.wait() if ret_val == 0: Thread(target=self.get_launcher).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def get_launcher(self): app = self.detect_region() # Stop if no supported region was found if not app: Thread(target=self.clean, args=(True, )).start() return # Delete contents of the launcher folder as it will be replaced by the one from hiyaCFW launcher_folder = path.join(self.sd_path, 'title', '00030017', app, 'content') # Walk through all files in the launcher content folder for file in listdir(launcher_folder): file = path.join(launcher_folder, file) # Set current file as read/write in case we extracted with 7-Zip and unlaunch was # installed in the NAND. Fatcat doesn't keep file attributes if _7z is not None: chmod(file, 438) # Delete current file remove(file) # Try to use already downloaded launcher try: if path.isfile(self.launcher_region): self.log.write('\nPreparing ' + self.launcher_region + ' launcher...') else: self.log.write('\nDownloading ' + self.launcher_region + ' launcher...') with urlopen('https://raw.githubusercontent.com' '/mondul/HiyaCFW-Helper/master/launchers/' + self.launcher_region) as src, open( self.launcher_region, 'wb') as dst: copyfileobj(src, dst) self.log.write('- Decrypting launcher...') # Set launcher filename according to the region launcher_app = ('00000000.app' if self.launcher_region in ('CHN', 'KOR') else '00000002.app') # Prepare decryption params params = [ _7za, 'x', '-bso0', '-y', '-p' + app.lower(), self.launcher_region, launcher_app ] if launcher_app == '00000000.app': params.append('title.tmd') proc = Popen(params) ret_val = proc.wait() if ret_val == 0: if self.clean_downloaded.get() == 1: self.files.append(self.launcher_region) self.files.append(launcher_app) if launcher_app == '00000000.app': self.files.append('title.tmd') # Hash launcher app sha1_hash = sha1() with open(launcher_app, 'rb') as f: sha1_hash.update(f.read()) self.log.write('- Patched launcher SHA1:\n ' + sha1_hash.digest().hex().upper()) Thread(target=self.install_hiyacfw, args=(launcher_app, launcher_folder)).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except IOError as e: print(e) self.log.write('ERROR: Could not download ' + self.launcher_region + ' launcher') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def install_hiyacfw(self, launcher_app, launcher_folder): self.log.write('\nCopying HiyaCFW files...') # Reset copied files cache _path_created.clear() copy_tree('for SDNAND SD card', self.sd_path, update=1) copyfile('bootloader.nds', path.join(self.sd_path, 'hiya', 'bootloader.nds')) copyfile(launcher_app, path.join(launcher_folder, launcher_app)) if launcher_app == '00000000.app': copyfile('title.tmd', path.join(launcher_folder, 'title.tmd')) Thread(target=self.get_latest_twilight if self.twilight.get() == 1 else self.clean).start() ################################################################################################ def get_latest_twilight(self): # Try to use already downloaded TWiLight Menu++ archive filename = 'TWiLightMenu.7z' try: if path.isfile(filename): self.log.write('\nPreparing TWiLight Menu++...') else: self.log.write( '\nDownloading latest TWiLight Menu++ release...') with urlopen( 'https://github.com/DS-Homebrew/TWiLightMenu/releases/latest/download/' + filename) as src, open(filename, 'wb') as dst: copyfileobj(src, dst) self.log.write('- Extracting ' + filename[:-3] + ' archive...') proc = Popen([ _7za, 'x', '-bso0', '-y', filename, '_nds', 'DSi - CFW users', 'DSi&3DS - SD card users', 'roms' ]) ret_val = proc.wait() if ret_val == 0: if self.clean_downloaded.get() == 1: self.files.append(filename) self.folders.append('DSi - CFW users') self.folders.append('_nds') self.folders.append('DSi&3DS - SD card users') self.folders.append('roms') Thread(target=self.install_twilight, args=(filename[:-3], )).start() else: self.log.write('ERROR: Extractor failed') Thread(target=self.clean, args=(True, )).start() except (URLError, IOError) as e: print(e) self.log.write('ERROR: Could not get TWiLight Menu++') Thread(target=self.clean, args=(True, )).start() except OSError as e: print(e) self.log.write('ERROR: Could not execute ' + exe) Thread(target=self.clean, args=(True, )).start() ################################################################################################ def install_twilight(self, name): self.log.write('\nCopying ' + name + ' files...') copy_tree(path.join('DSi - CFW users', 'SDNAND root'), self.sd_path, update=1) copy_tree('_nds', path.join(self.sd_path, '_nds')) copy_tree('DSi&3DS - SD card users', self.sd_path, update=1) copy_tree('roms', path.join(self.sd_path, 'roms')) Thread(target=self.clean).start() ################################################################################################ def clean(self, err=False): self.log.write('\nCleaning...') while len(self.folders) > 0: rmtree(self.folders.pop(), ignore_errors=True) while len(self.files) > 0: try: remove(self.files.pop()) except: pass if err: self.log.write('Done') return self.log.write('Done!\nEject your SD card and insert it into your DSi') ################################################################################################ def patcher(self, patchpath, filepath): patch_size = path.getsize(patchpath) patchfile = open(patchpath, 'rb') if patchfile.read(5) != b'PATCH': patchfile.close() raise Exception() target = open(filepath, 'r+b') # Read First Record r = patchfile.read(3) while patchfile.tell() not in [patch_size, patch_size - 3]: # Unpack 3-byte pointers. offset = self.unpack_int(r) # Read size of data chunk r = patchfile.read(2) size = self.unpack_int(r) if size == 0: # RLE Record r = patchfile.read(2) rle_size = self.unpack_int(r) data = patchfile.read(1) * rle_size else: data = patchfile.read(size) # Write to file target.seek(offset) target.write(data) # Read Next Record r = patchfile.read(3) if patch_size - 3 == patchfile.tell(): trim_size = self.unpack_int(patchfile.read(3)) target.truncate(trim_size) # Cleanup target.close() patchfile.close() ################################################################################################ def unpack_int(self, bstr): # Read an n-byte big-endian integer from a byte string (ret_val, ) = unpack_from('>I', b'\x00' * (4 - len(bstr)) + bstr) return ret_val ################################################################################################ def detect_region(self): REGION_CODES = { '484e4143': 'CHN', '484e4145': 'USA', '484e414a': 'JAP', #'484e414b': 'KOR', '484e4150': 'EUR', '484e4155': 'AUS' } # Autodetect console region try: for app in listdir(path.join(self.sd_path, 'title', '00030017')): for file in listdir( path.join(self.sd_path, 'title', '00030017', app, 'content')): if file.endswith('.app'): try: self.log.write('- Detected ' + REGION_CODES[app.lower()] + ' console NAND dump') self.launcher_region = REGION_CODES[app.lower()] return app except KeyError: self.log.write('ERROR: Unsupported console region') return False self.log.write('ERROR: Could not detect console region') except OSError as e: self.log.write('ERROR: ' + e.strerror + ': ' + e.filename) return False ################################################################################################ def remove_footer(self): self.log.write('\nRemoving No$GBA footer...') file = self.console_id.get() + '-no-footer.bin' try: copyfile(self.nand_file.get(), file) # Back-up footer info with open(self.console_id.get() + '-info.txt', 'w') as f: f.write('eMMC CID: ' + self.cid.get() + '\r\n') f.write('Console ID: ' + self.console_id.get() + '\r\n') with open(file, 'r+b') as f: # Go to the No$GBA footer offset f.seek(-64, 2) # Remove footer f.truncate() self.log.write('\nDone!\nModified NAND stored as\n' + file + '\nStored footer info in ' + self.console_id.get() + '-info.txt') except IOError as e: print(e) self.log.write('ERROR: Could not open the file ' + path.basename(self.nand_file.get())) ################################################################################################ def add_footer(self, cid, console_id): self.log.write('Adding No$GBA footer...') file = self.console_id.get() + '-footer.bin' try: copyfile(self.nand_file.get(), file) with open(file, 'r+b') as f: # Go to the No$GBA footer offset f.seek(-64, 2) # Read the footer's header :-) bstr = f.read(0x10) # Check if it already has a footer if bstr == b'DSi eMMC CID/CPU': self.log.write('ERROR: File already has a No$GBA footer') f.close() remove(file) return # Go to the end of file f.seek(0, 2) # Write footer f.write(b'DSi eMMC CID/CPU') f.write(cid) f.write(console_id) f.write(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') self.log.write('\nDone!\nModified NAND stored as\n' + file) except IOError as e: print(e) self.log.write('ERROR: Could not open the file ' + path.basename(self.nand_file.get()))