def init_details(self, window): # Create details button def details(): if helper_frame.hidden: helper_frame.grid() helper_frame.hidden = False self.run_button.grid(row=17) else: helper_frame.grid_remove() helper_frame.hidden = True self.run_button.grid(row=16) details_button = Button(window, text="Details", command=details) details_button.grid(row=15, column=0, sticky="W", padx=PAD_X) # Details Menu helper_frame = Frame(window, width=window.winfo_width() - PAD_X * 2, height=100) helper_frame.pack_propagate(False) self.details_text = Text(helper_frame, width=0, height=0) details_scroll = Scrollbar(helper_frame, command=self.details_text.yview) details_scroll.pack(side=RIGHT, fill="y") self.details_text.configure(yscrollcommand=details_scroll.set) self.details_text.pack(fill="both", expand=True) helper_frame.grid(row=16, column=0, padx=PAD_X, pady=10) helper_frame.grid_remove() helper_frame.hidden = True
class WaitingBar: def __init__(self, frame, field_width, field_height): self.val = True self.waiting_frame = Frame(frame, width=70, height=30) self.waiting_frame.grid(row=field_height + 1, column=4, columnspan=3) self.waiting_frame.grid_remove() self.waiting_frame.pack_propagate(True) self.waiting_message = Label(self.waiting_frame, text='Подождите...', font=8) self.waiting_message.pack() def show(self, flag): if flag: self.waiting_frame.grid() else: self.waiting_frame.grid_remove()
class PantallaEsperaView(View): def __init__(self, controller): super().__init__(Toplevel(), controller) self.construir_main_frame() self.construir_progressbar_frame() self.ocultar_vista() def configurar_root(self): super(PantallaEsperaView, self).configurar_root() self.root.geometry("250x150") def construir_main_frame(self): self.main_frame = Frame(self.root) self.main_frame.pack() def construir_progressbar_frame(self): self.label = Label(self.main_frame) self.label.config(pady=20, padx=20, font=("Helvetica", 10)) self.label.grid(row=0, column=0) self.pb_frame = Frame(self.main_frame) self.pb_frame.config(padx=20, pady=20) # self.pb_frame.grid(row=1, column=0) self.progressbar = Progressbar(self.pb_frame) self.progressbar.config(mode="indeterminate", length=150) self.progressbar.pack() def ocultar_vista(self): self.progressbar.stop() super(PantallaEsperaView, self).ocultar_vista() self.pb_frame.grid_remove() def mostrar_vista(self): self.pb_frame.grid(row=1, column=0) super(PantallaEsperaView, self).mostrar_vista() self.progressbar.start(10)
def load(self): self.accounts = [] for pdata in read_data(): self.accounts.append(Pohhop(pdata)) self.accounts.sort(key=lambda x: (x.compet, x.wingman), reverse=True) x = 0 y = 0 position = 0 delta = 0 last_account = self.accounts[-1] for player in self.accounts: player.download_avatar() if not player.visible: continue if player.compet != last_account.compet: position += 1 position += delta delta = 0 elif player.wingman != last_account.wingman: position += 1 position += delta delta = 0 else: delta += 1 last_account = player frame = Frame(self.root, background='Black') self.add_position(frame, position) self.add_avatar(frame, player) self.add_rank(frame, player) frame.grid(column=x, row=y, padx=20, pady=5) if y >= 7 * 2: pass frame.grid_remove() x += 1 if x == 5: x = 0 y += 2
class PianoTutor: def __init__(self, root): self.root = root self.root.resizable(False, False) self.root.title('Piano Tutor') self.keys = [] self.build_mode_selector_frame() self.build_score_sheet_frame() self.build_controls_frame() self.build_keyboard_frame() self.build_chords_frame() self.build_progressions_frame() self.build_scales_frame() def build_mode_selector_frame(self): self.mode_selector_frame = Frame(self.root, width=WINDOW_WIDTH, height=MODE_SELECTOR_HEIGHT, background='mint cream') self.mode_selector_frame.grid_propagate(False) self.mode_selector = ttk.Combobox(self.mode_selector_frame, values=CHOICES) self.mode_selector.bind('<<ComboboxSelected>>', self.on_mode_changed) self.mode_selector.current(0) self.mode_selector.grid( row=0, column=1, columnspan=3, padx=10, pady=10, sticky='nsew', ) self.mode_selector_frame.grid(row=0, column=0) def build_score_sheet_frame(self): self.score_sheet_frame = Frame(self.root, width=WINDOW_WIDTH, height=SCORE_DISPLAY_HEIGHT, background='SteelBlue1') self.score_sheet_frame.grid_propagate(False) Label(self.score_sheet_frame, text='placeholder for score sheet', background='SteelBlue1').grid(row=1, column=1) self.score_sheet_frame.grid(row=1, column=0) def build_controls_frame(self): self.controls_frame = Frame(self.root, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, background='cornsilk3') self.controls_frame.grid_propagate(False) self.controls_frame.grid(row=2, column=0) def build_keyboard_frame(self): self.keyboard_frame = Frame(self.root, width=WINDOW_WIDTH, height=KEYBOARD_HEIGHT, background='LavenderBlush2') self.keyboard_frame.grid_propagate(False) self.keyboard_frame.grid(row=4, column=0, sticky='nsew') for (index, key) in enumerate(WHITE_KEY_NAMES): x = WHITE_KEY_X_COORDINATES[index] self.create_key(WHITE_KEY_IMAGE, key, x) for (index, key) in enumerate(BLACK_KEY_NAMES): x = BLACK_KEY_X_COORDINATES[index] self.create_key(BLACK_KEY_IMAGE, key, x) def build_scales_frame(self): self.scales_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, bg='SlateBlue3') Label(self.scales_frame, text='placeholder for scales frame').grid(row=1, column=1) self.scales_frame.grid(row=1, column=0, sticky='nsew') def build_chords_frame(self): self.chords_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, bg='cornsilk4') self.chords_frame.grid_propagate(False) Label(self.chords_frame, text='placeholder for chords frame').grid(row=1, column=1) self.chords_frame.grid(row=1, column=0, sticky='nsew') def build_progressions_frame(self): self.progressions_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, bg='plum2') self.progressions_frame.grid_propagate(False) Label(self.progressions_frame, text='placeholder for progression frame').grid(row=1, column=1) self.progressions_frame.grid(row=1, column=0, sticky='nsew') def on_mode_changed(self, event): selected_mode = self.mode_selector.get() if selected_mode == 'Scales': self.show_scales_frame() elif selected_mode == 'Chords': self.show_chords_frame() elif selected_mode == 'Chord Progressions': self.show_progressions_frame() def show_scales_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid_remove() self.scales_frame.grid() def show_chords_frame(self): self.chords_frame.grid() self.progressions_frame.grid_remove() self.scales_frame.grid_remove() def show_progressions_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid() self.scales_frame.grid_remove() def create_key(self, img, key_name, x_coordinate): key_image = PhotoImage(file=img) label = Label(self.keyboard_frame, image=key_image, border=0) label.image = key_image label.place(x=x_coordinate, y=0) label.name = key_name label.bind('<Button-1>', self.on_key_pressed) label.bind('<ButtonRelease-1>', self.on_key_released) self.keys.append(label) return label def change_image_to_pressed(self, event): if len(event.widget.name) == 2: img = WHITE_KEY_PRESSED_IMAGE elif len(event.widget.name) == 3: img = BLACK_KEY_PRESSED_IMAGE key_img = PhotoImage(file=img) event.widget.configure(image=key_img) event.widget.image = key_img def change_image_to_unpressed(self, event): if len(event.widget.name) == 2: img = WHITE_KEY_IMAGE elif len(event.widget.name) == 3: img = BLACK_KEY_IMAGE key_img = PhotoImage(file=img) event.widget.configure(image=key_img) event.widget.image = key_img def on_key_pressed(self, event): play_note(event.widget.name) self.change_image_to_pressed(event) def on_key_released(self, event): print(event.widget.name + ' released') self.change_image_to_unpressed(event)
class MessageComponentFrame: def __init__(self, parent): self.parent = parent self.frame = Frame(parent.master, bd=2, relief=GROOVE) self.textValue = StringVar() self.imageValue = StringVar() self.imagePath = StringVar() self.fileValue = StringVar() self.filePath = StringVar() self.gapValue = StringVar() self.componentType = StringVar() self.componentTypes = ["Text", "Image", "Text From File", "Pixel Gap"] labelMessageSettings = Label(self.frame, text="Component Settings") labelMessageSettings.grid(row=0, column=0, sticky=W, columnspan=3, padx=1, pady=1) labelComponentType = Label(self.frame, text="Component Type:") labelComponentType.grid(row=1, column=0, sticky=E, padx=4, pady=4) self.comboboxComponentType = Combobox(self.frame, values=self.componentTypes, textvariable=self.componentType, state="readonly") self.comboboxComponentType.grid(row=1, column=1, columnspan=2, sticky=W, padx=4, pady=4) self.labelTextToDisplay = Label(self.frame, text="Text to Display:") self.labelTextToDisplay.grid(row=2, column=0, sticky=E, padx=4, pady=4) self.inputTextToDisplay = Entry(self.frame, textvariable=self.textValue, width=40) self.inputTextToDisplay.grid(row=2, column=1, columnspan=2, sticky=W, padx=4, pady=4) self.labelImage = Label(self.frame, textvariable=self.imagePath, anchor=W) self.buttonImage = HoverButton(self.frame, text='Select File', command=lambda: self.selectImageFile(), width=12) self.buttonImage.grid(row=3, column=0, sticky=E, padx=4, pady=4) self.labelImage.grid(row=3, column=1, columnspan=2, sticky=W) self.labelFile = Label(self.frame, textvariable=self.filePath, anchor=W) self.buttonFile = HoverButton(self.frame, text='Select File', command=lambda: self.selectTextFile(), width=12) self.buttonFile.grid(row=4, column=0, sticky=E, padx=4, pady=4) self.labelFile.grid(row=4, column=1, columnspan=2, sticky=W) self.labelGap = Label(self.frame, text="Width of Gap:") self.labelGap.grid(row=5, column=0, sticky=E, padx=4, pady=(4, 0)) self.gapFrame = Frame(self.frame) self.inputGap = Entry(self.gapFrame, textvariable=self.gapValue, width=4) self.inputGap.grid(row=0, column=0, sticky=W, pady=4) self.labelGapPixels = Label(self.gapFrame, text="pixels") self.labelGapPixels.grid(row=0, column=1, padx=2, sticky=W) self.gapFrame.grid(row=5, column=1, columnspan=2, sticky=W, padx=4, pady=4) self.comboboxComponentType.bind("<<ComboboxSelected>>", self.updateGrid) self.setFields() self.updateGrid(None) def setFields(self): mp = self.parent.messagePart if mp: self.comboboxComponentType.set(mp.partType) if mp.partType == "Text": self.textValue.set(mp.value) elif mp.partType == "Image": self.imagePath.set(helperMethods.getFileNameFromPath(mp.value)) self.imageValue.set(mp.value) elif mp.partType == "Text From File": self.filePath.set(helperMethods.getFileNameFromPath(mp.value)) self.fileValue.set(mp.value) elif mp.partType == "Pixel Gap": self.gapValue.set(mp.value) else: self.comboboxComponentType.set("Text") def hideAllDropdownDependentFields(self): self.labelTextToDisplay.grid_remove() self.inputTextToDisplay.grid_remove() self.labelImage.grid_remove() self.buttonImage.grid_remove() self.labelFile.grid_remove() self.buttonFile.grid_remove() self.labelGap.grid_remove() self.gapFrame.grid_remove() def displayCurrentComponentTypeDependencies(self): if self.componentType.get() == "Text": self.labelTextToDisplay.grid() self.inputTextToDisplay.grid() elif self.componentType.get() == "Image": self.labelImage.grid() self.buttonImage.grid() elif self.componentType.get() == "Text From File": self.labelFile.grid() self.buttonFile.grid() elif self.componentType.get() == "Pixel Gap": self.labelGap.grid() self.gapFrame.grid() def updateGrid(self, e): self.hideAllDropdownDependentFields() self.displayCurrentComponentTypeDependencies() def selectImageFile(self): filename = filedialog.askopenfilename( initialdir=os.getcwd() + "/imagefiles", title="Select image file", filetypes=[("PNG", "*.png"), ("JPEG", "*.jpg; *.jpeg; *.jpe; *.jfif")]) if filename: self.imagePath.set(helperMethods.getFileNameFromPath(filename)) self.imageValue.set(filename) def selectTextFile(self): filename = filedialog.askopenfilename(initialdir=os.getcwd(), title="Select text file", filetypes=[("txt files", "*.txt") ]) if filename: self.filePath.set(helperMethods.getFileNameFromPath(filename)) self.fileValue.set(filename) def getValue(self): if self.componentType.get() == "Text": return self.textValue.get() elif self.componentType.get() == "Image": return self.imageValue.get() elif self.componentType.get() == "Text From File": return self.fileValue.get() elif self.componentType.get() == "Pixel Gap": return self.gapValue.get()
class fen_info(Tk): """ Fenêtre permettant de saisir les informations sur les joueurs """ def __init__(self): super().__init__() # Initialisation des pions à la valeur initiale. self.pion1 = "X" self.pion2 = "O" # Titre de la fenêtre self.title("Ultimate TIC-TAC-TOE") # Pour changer taille minimum de fenêtre et taille centrer, # changer variable self.width_fen, self.height_fen. self.width_fen, self.height_fen = 430, 500 # Taille minimum de la fenêtre self.minsize(self.width_fen, self.height_fen) # Centrer la fenêtre. centreFen(self, self.width_fen, self.height_fen) # Création d'un canvas avec l'image "logo.gif" canvas = Canvas(self, width=280, height=100) self.img = PhotoImage(file="logo.gif") canvas.create_image(280, 100, anchor=SE, image=self.img) canvas.grid(row=0, columnspan=5, pady=10) # Libellé - Nouvelle Partie Label(self, text="Nouvelle partie", font=("Arial", 16), fg="#0080FF", justify=CENTER).grid(row=1, columnspan=5, padx=20, pady=5) separateur(20).grid(row=10, columnspan=5) # Sélection du type de partie avec bouton radio self.choixJoueur = IntVar() r1 = Radiobutton(self, text="Jouer avec l'ordinateur", variable=self.choixJoueur, value=1, command=self.define_choix) r1.select() r1.grid(row=20, column=0) r2 = Radiobutton(self, text="Jouer avec un autre joueur", variable=self.choixJoueur, value=2, command=self.define_choix) r2.grid(row=20, column=1) # Saisie du nom du joueur 1. f_j1 = Frame(self, borderwidth=1, padx=5, pady=5, relief=SUNKEN) f_j1.grid(row=30, columnspan=5, padx=5, pady=5) Label(f_j1, text="Nom joueur 1:").grid(row=1, column=0, sticky=E, padx=5, pady=5) self.nom_joueur1 = Entry(f_j1) self.nom_joueur1.grid(row=1, column=1) # Sélection du pion joueur 1. Le pion restant est automatiquement attribué au joueur 2. Label(f_j1, text="Choix de pion:").grid(row=1, column=2, padx=5) self.sel_pion = IntVar() p1 = Radiobutton(f_j1, indicatoron=0, width=5, text="X", variable=self.sel_pion, value=1, command=self.choix_pion) p1.grid(row=1, column=3, padx=2) p1.select() Radiobutton(f_j1, indicatoron=0, width=5, text="O", variable=self.sel_pion, value=2, command=self.choix_pion).grid(row=1, column=4, padx=2) # Saisie du nom du joueur 2. Apparaît seulement si on sélection 2 joueurs. Voir define_choix self.f_j2 = Frame(self, width=420, borderwidth=1, padx=5, pady=5, relief=SUNKEN) Label(self.f_j2, text="Nom joueur 2").grid(row=1, column=0, sticky=E, padx=5, pady=5) self.nom_joueur2 = Entry(self.f_j2, state="disabled") self.nom_joueur2.grid(row=1, column=1) self.label_pion2 = Label(self.f_j2, text="Pion Joueur 2 = O") self.label_pion2.grid(row=1, column=2, padx=5) # Information sur l'ordinateur. Disparaît si on choisi 2 joueurs. self.f_ordi = Frame(self, width=420, borderwidth=1, padx=5, pady=5, relief=SUNKEN) self.f_ordi.grid(row=40, columnspan=5, padx=5, pady=5) Label(self.f_ordi, text="Ordinateur = Colosse", font=("Arial", 12), fg="#0080FF")\ .grid(row=1, column=0, sticky=E, padx = 5, pady = 5) self.pion_ordi = Label(self.f_ordi, text="| Pion de l'ordinateur = O", font=("Arial", 12), fg="#0080FF") self.pion_ordi.grid(row=1, column=2) separateur(20).grid(row=50, columnspan=5) # Sélection de la force de l'ordinateur self.choixForce = IntVar() self.f1 = Radiobutton(self, indicatoron=0, width=20, padx=20, text="Facile", variable=self.choixForce, value=1, command=self.define_choix) self.f1.select() self.f1.grid(row=60, columnspan=5) self.f2 = Radiobutton(self, indicatoron=0, width=20, padx=20, text="Moyen", variable=self.choixForce, value=2, command=self.define_choix) self.f2.grid(row=61, columnspan=5) self.f3 = Radiobutton(self, indicatoron=0, width=20, padx=20, text="Difficile", variable=self.choixForce, value=3, command=self.define_choix) self.f3.grid(row=62, columnspan=5) separateur(40).grid(row=70, column=0) #Button pour démarrer la partie self.bt_start = Button(text="Démarrer", font=("Arial", 12), fg="green", command=self.demarrer_jeu) self.bt_start.grid(row=80, columnspan=5) def define_choix(self): """ Fonction qui active ou désactive le nom du joueur 2 selon si on joue contre l'ordinateur ou contre un autre joueur """ if self.choixJoueur.get() == 1: self.nom_joueur2.delete(0, END) self.nom_joueur2["state"] = "disabled" self.f1["state"] = "normal" self.f2["state"] = "normal" self.f3["state"] = "normal" self.f_j2.grid_remove() self.f_ordi.grid(row=40, columnspan=5, padx=5, pady=5) elif self.choixJoueur.get() == 2: self.nom_joueur2["state"] = "normal" self.f1["state"] = "disabled" self.f2["state"] = "disabled" self.f3["state"] = "disabled" self.f_j2.grid(row=40, columnspan=5, padx=5, pady=5) self.f_ordi.grid_remove() def choix_pion(self): # Définition des pions if self.sel_pion.get() == 1: self.pion1 = "X" self.pion2 = "O" self.label_pion2["text"] = "Pion Joueur 2 = {}".format(self.pion2) self.pion_ordi["text"] = "| Pion de l'ordinateur = {}".format( self.pion2) else: self.pion1 = "O" self.pion2 = "X" self.label_pion2["text"] = "Pion Joueur 2 = {}".format(self.pion2) self.pion_ordi["text"] = "| Pion de l'ordinateur = {}".format( self.pion2) def demarrer_jeu(self): """ Démarrer la partie avec les informations saisie. Afficher le plateau """ if self.choixJoueur.get() == 1: type2 = "Ordinateur" if self.nom_joueur1.get() != '': j1 = self.nom_joueur1.get() j2 = "Colosse" else: j1 = "Joueur 1" j2 = "Colosse" elif self.choixJoueur.get() == 2: type2 = "Personne" if self.nom_joueur1.get() != '' and self.nom_joueur2.get() != '': j1 = self.nom_joueur1.get() j2 = self.nom_joueur2.get() elif self.nom_joueur1.get() == '': j1 = "Joueur 1" if self.nom_joueur2.get() == '': j2 = "Joueur 2" else: j2 = self.nom_joueur2.get() else: j1 = self.nom_joueur1.get() if self.nom_joueur2.get() == '': j2 = "Joueur 2" else: j2 = self.nom_joueur2.get() p1 = self.pion1 p2 = self.pion2 force = self.choixForce.get() self.destroy() ma_fenetre = Fenetre(j1, j2, type2, p1, p2, force) ma_fenetre.mainloop()
class Momentary: def __init__(self, master, valves): self.valves = valves self.master = master self.frame1 = Frame(master) self.frame2 = Frame(master) self.master.configure(bg='sky blue') self.frame1.configure(bg='sky blue') self.frame2.configure(bg='sky blue') index = 0 while index < 6: self.frame1.grid_columnconfigure(index, minsize=6) self.frame2.grid_columnconfigure(index, minsize=6) self.frame1.grid_rowconfigure(index, minsize=140) self.frame2.grid_rowconfigure(index, minsize=140) index += 1 self.end_all_image = PhotoImage(file="img/stop.png").subsample(x=6, y=6) self.end_all_button = Button(self.master, image=self.end_all_image, command=lambda: self.end_all()) self.end_all_button.config(bg='brown3', activebackground='brown4', border=5, width=850) self.label = [ Label(self.frame1, textvariable=self.valves[0].get_name()), Label(self.frame1, textvariable=self.valves[1].get_name()), Label(self.frame1, textvariable=self.valves[2].get_name()), Label(self.frame1, textvariable=self.valves[3].get_name()), Label(self.frame2, textvariable=self.valves[4].get_name()), Label(self.frame2, textvariable=self.valves[5].get_name()), Label(self.frame2, textvariable=self.valves[6].get_name()), Label(self.frame2, textvariable=self.valves[7].get_name()) ] row = 0 for each in self.label: each.config(width=7, height=2) each.config(bg='sky blue', fg='RoyalBlue4', font=('Lucida Console', 30), padx=18) each.grid(row=row % 4, column=0) row += 1 self.lightsA = [ LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False) ] self.lightsB = [ LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False) ] self.v = [ IntVar(), IntVar(), IntVar(), IntVar(), IntVar(), IntVar(), IntVar(), IntVar() ] for each in self.v: each.set(3) self.a = [ Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(0), value=1), Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(1), value=1), Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(2), value=1), Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(3), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(4), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(5), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(6), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(7), value=1) ] index = 0 for each in self.a: each.grid(row=index % 4, column=2) each.config(width=4, height=2, indicatoron=0, variable=self.v[index], font=('Lucida Console', 30)) each.config(bg='SkyBlue4', activebackground='midnight blue', selectcolor='midnight blue', fg='white') each.config(activeforeground='white') index += 1 self.b = [ Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(0), value=0), Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(1), value=0), Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(2), value=0), Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(3), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(4), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(5), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(6), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(7), value=0) ] index = 0 for each in self.b: each.grid(row=index % 4, column=3) each.config(width=4, height=2, indicatoron=0, variable=self.v[index], font=('Lucida Console', 30)) each.config(bg='SkyBlue4', activebackground='midnight blue', selectcolor='midnight blue', fg='white') each.config(activeforeground='white') index += 1 self.end_image = PhotoImage(file="img/no.png").subsample(x=6, y=6) self.end_button = [ Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(0)), Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(1)), Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(2)), Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(3)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(4)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(5)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(6)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(7)), ] index = 0 for each in self.end_button: each.grid(row=index % 4, column=5) each.config(value=2, variable=self.v[index], indicatoron=0) each.config(bg='brown3', activebackground='brown4') index += 1 def make_frame(self): self.frame1.grid(row=2, column=0, rowspan=5) self.frame2.grid(row=2, column=1, rowspan=5) self.end_all_button.grid(row=1, column=0, columnspan=2) row = 0 for each in self.lightsA: each.grid(row=row % 4, column=1, padx=20, pady=20) row += 1 row = 0 for each in self.lightsB: each.grid(row=row % 4, column=4, padx=20, pady=20) row += 1 def delete_frame(self): self.frame1.grid_remove() self.frame2.grid_remove() self.end_all_button.grid_remove() for each in self.lightsA: each.grid_remove() for each in self.lightsB: each.grid_remove() def activate_a(self, number): pin_number = 65 + number pin_opposite = 80 - number if self.v[number].get() == 1: self.lightsA[number].set_state(True) self.lightsB[number].set_state(False) wiringpi.digitalWrite(pin_number, 1) wiringpi.digitalWrite(pin_opposite, 0) def activate_b(self, number): pin_number = 80 - number pin_opposite = 65 + number if self.v[number].get() == 0: self.lightsA[number].set_state(False) self.lightsB[number].set_state(True) wiringpi.digitalWrite(pin_number, 1) wiringpi.digitalWrite(pin_opposite, 0) def end(self, number): pin_number = 65 + number pin_opposite = 80 - number wiringpi.digitalWrite(pin_number, 0) wiringpi.digitalWrite(pin_opposite, 0) self.v[number].set(3) self.lightsA[number].set_state(False) self.lightsB[number].set_state(False) def end_all(self): number = 0 while number < 8: self.end(number) number += 1
def hide(frame: tk.Frame): frame.grid_remove()
class PianoTutor: def __init__(self, root): self.root = root self.root.resizable(False, False) self.root.title('Piano Tutor') self.build_mode_selector_frame() self.build_score_sheet_frame() self.build_controls_frame() self.build_keyboard_frame() self.build_chords_frame() self.build_progressions_frame() self.build_scales_frame() def build_mode_selector_frame(self): self.mode_selector_frame = Frame(self.root, width=WINDOW_WIDTH, height=MODE_SELECTOR_HEIGHT, background='mint cream') self.mode_selector_frame.grid_propagate(False) self.mode_selector = ttk.Combobox(self.mode_selector_frame, values=CHOICES) self.mode_selector.bind('<<ComboboxSelected>>', self.on_mode_changed) self.mode_selector.current(0) self.mode_selector.grid( row=0, column=1, columnspan=3, padx=10, pady=10, sticky='nsew', ) self.mode_selector_frame.grid(row=0, column=0) def build_score_sheet_frame(self): self.score_sheet_frame = Frame(self.root, width=WINDOW_WIDTH, height=SCORE_DISPLAY_HEIGHT, background='SteelBlue1') self.score_sheet_frame.grid_propagate(False) Label(self.score_sheet_frame, text='placeholder for score sheet' , background='SteelBlue1').grid(row=1, column=1) self.score_sheet_frame.grid(row=1, column=0) def build_controls_frame(self): self.controls_frame = Frame(self.root, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, background='cornsilk3') self.controls_frame.grid_propagate(False) self.controls_frame.grid(row=2, column=0) def build_keyboard_frame(self): self.keyboard_frame = Frame(self.root, width=WINDOW_WIDTH, height=KEYBOARD_HEIGHT, background='LavenderBlush2') self.keyboard_frame.grid_propagate(False) Label(self.keyboard_frame, text='placeholder for keyboard', background='LavenderBlush2').grid() self.keyboard_frame.grid(row=4, column=0, sticky='nsew') def build_scales_frame(self): self.scales_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, bg='SlateBlue3') Label(self.scales_frame, text='placeholder for scales frame' ).grid(row=1, column=1) self.scales_frame.grid(row=1, column=0, sticky='nsew') def build_chords_frame(self): self.chords_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, bg='cornsilk4') self.chords_frame.grid_propagate(False) Label(self.chords_frame, text='placeholder for chords frame' ).grid(row=1, column=1) self.chords_frame.grid(row=1, column=0, sticky='nsew') def build_progressions_frame(self): self.progressions_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT, bg='plum2') self.progressions_frame.grid_propagate(False) Label(self.progressions_frame, text='placeholder for progression frame').grid(row=1, column=1) self.progressions_frame.grid(row=1, column=0, sticky='nsew') def on_mode_changed(self, event): selected_mode = self.mode_selector.get() if selected_mode == 'Scales': self.show_scales_frame() elif selected_mode == 'Chords': self.show_chords_frame() elif selected_mode == 'Chord Progressions': self.show_progressions_frame() def show_scales_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid_remove() self.scales_frame.grid() def show_chords_frame(self): self.chords_frame.grid() self.progressions_frame.grid_remove() self.scales_frame.grid_remove() def show_progressions_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid() self.scales_frame.grid_remove()
class Momentary: def __init__(self, master, valves): self.valves = valves self.master = master self.frame1 = Frame(master) self.frame2 = Frame(master) self.master.configure(bg='sky blue') self.frame1.configure(bg='sky blue') self.frame2.configure(bg='sky blue') index = 0 while index < 6: self.frame1.grid_columnconfigure(index, minsize=6) self.frame2.grid_columnconfigure(index, minsize=6) self.frame1.grid_rowconfigure(index, minsize=140) self.frame2.grid_rowconfigure(index, minsize=140) index += 1 self.end_all_image = PhotoImage(file="img/stop.png").subsample(x=6, y=6) self.end_all_button = Button(self.master, image=self.end_all_image, command=lambda: self.end_all() ) self.end_all_button.config(bg='brown3', activebackground='brown4', border=5, width=850) self.label = [Label(self.frame1, textvariable=self.valves[0].get_name()), Label(self.frame1, textvariable=self.valves[1].get_name()), Label(self.frame1, textvariable=self.valves[2].get_name()), Label(self.frame1, textvariable=self.valves[3].get_name()), Label(self.frame2, textvariable=self.valves[4].get_name()), Label(self.frame2, textvariable=self.valves[5].get_name()), Label(self.frame2, textvariable=self.valves[6].get_name()), Label(self.frame2, textvariable=self.valves[7].get_name())] row = 0 for each in self.label: each.config(width=7, height=2) each.config(bg='sky blue', fg='RoyalBlue4', font=('Lucida Console', 30), padx=18) each.grid(row=row % 4, column=0) row += 1 self.lightsA = [LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame1, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False), LED(self.frame2, 30, 'green1', 'green', 'dark green', 'Dark Green', False) ] self.lightsB = [LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame1, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False), LED(self.frame2, 30, 'red', 'dark red', 'red4', 'DarkRed', False) ] self.v = [IntVar(), IntVar(), IntVar(), IntVar(), IntVar(), IntVar(), IntVar(), IntVar()] for each in self.v: each.set(3) self.a = [Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(0), value=1), Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(1), value=1), Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(2), value=1), Radiobutton(self.frame1, text='A', command=lambda: self.activate_a(3), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(4), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(5), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(6), value=1), Radiobutton(self.frame2, text='A', command=lambda: self.activate_a(7), value=1)] index = 0 for each in self.a: each.grid(row=index % 4, column=2) each.config(width=4, height=2, indicatoron=0, variable=self.v[index], font=('Lucida Console', 30)) each.config(bg='SkyBlue4', activebackground='midnight blue', selectcolor='midnight blue', fg='white') each.config(activeforeground='white') index += 1 self.b = [Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(0), value=0), Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(1), value=0), Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(2), value=0), Radiobutton(self.frame1, text='B', command=lambda: self.activate_b(3), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(4), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(5), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(6), value=0), Radiobutton(self.frame2, text='B', command=lambda: self.activate_b(7), value=0)] index = 0 for each in self.b: each.grid(row=index % 4, column=3) each.config(width=4, height=2, indicatoron=0, variable=self.v[index], font=('Lucida Console', 30)) each.config(bg='SkyBlue4', activebackground='midnight blue', selectcolor='midnight blue', fg='white') each.config(activeforeground='white') index += 1 self.end_image = PhotoImage(file="img/no.png").subsample(x=6, y=6) self.end_button = [Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(0)), Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(1)), Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(2)), Radiobutton(self.frame1, image=self.end_image, command=lambda: self.end(3)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(4)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(5)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(6)), Radiobutton(self.frame2, image=self.end_image, command=lambda: self.end(7)), ] index = 0 for each in self.end_button: each.grid(row=index % 4, column=5) each.config(value=2, variable=self.v[index], indicatoron=0) each.config(bg='brown3', activebackground='brown4') index += 1 def make_frame(self): self.frame1.grid(row=2, column=0, rowspan=5) self.frame2.grid(row=2, column=1, rowspan=5) self.end_all_button.grid(row=1, column=0, columnspan=2) row = 0 for each in self.lightsA: each.grid(row=row % 4, column=1, padx=20, pady=20) row += 1 row = 0 for each in self.lightsB: each.grid(row=row % 4, column=4, padx=20, pady=20) row += 1 def delete_frame(self): self.frame1.grid_remove() self.frame2.grid_remove() self.end_all_button.grid_remove() for each in self.lightsA: each.grid_remove() for each in self.lightsB: each.grid_remove() def activate_a(self, number): pin_number = 65 + number pin_opposite = 80 - number if self.v[number].get() == 1: self.lightsA[number].set_state(True) self.lightsB[number].set_state(False) wiringpi.digitalWrite(pin_number, 1) wiringpi.digitalWrite(pin_opposite, 0) def activate_b(self, number): pin_number = 80 - number pin_opposite = 65 + number if self.v[number].get() == 0: self.lightsA[number].set_state(False) self.lightsB[number].set_state(True) wiringpi.digitalWrite(pin_number, 1) wiringpi.digitalWrite(pin_opposite, 0) def end(self, number): pin_number = 65 + number pin_opposite = 80 - number wiringpi.digitalWrite(pin_number, 0) wiringpi.digitalWrite(pin_opposite, 0) self.v[number].set(3) self.lightsA[number].set_state(False) self.lightsB[number].set_state(False) def end_all(self): number = 0 while number < 8: self.end(number) number += 1
class PianoTutor: def __init__(self, root): self.root = root self.root.resizable(False, False) self.root.title('Piano Tutor') self.keys = [] self.load_json_files() self.keys_to_highlight = [] self.build_mode_selector_frame() self.build_score_sheet_frame() self.build_controls_frame() self.build_keyboard_frame() self.build_chords_frame() self.build_progressions_frame() self.build_scales_frame() self.find_scale() def load_json_files(self): with open(SCALES_JSON_FILE, 'r') as f: self.scales = json.load(f, object_pairs_hook=OrderedDict) with open(CHORDS_JSON_FILE, 'r') as f: self.chords = json.load(f, object_pairs_hook=OrderedDict) def on_chord_changed(self, event): self.remove_all_key_highlights() self.find_chord(event) def on_chords_key_changed(self, event): self.remove_all_key_highlights() self.find_chord(event) def find_chord(self, event=None): self.selected_chord = self.chords_selector.get() self.chords_selected_key = self.chords_key_selector.get() index_of_selected_key = KEYS.index(self.chords_selected_key) self.keys_to_highlight = [ ALL_KEYS[i+index_of_selected_key] for \ i in self.chords[self.selected_chord]] self.highlight_list_of_keys(self.keys_to_highlight) play_chord_in_new_thread(self.keys_to_highlight) def on_scale_changed(self, event): self.remove_all_key_highlights() self.find_scale(event) def on_scale_key_changed(self, event): self.remove_all_key_highlights() self.find_scale(event) def find_scale(self, event=None): self.selected_scale = self.scale_selector.get() self.scale_selected_key = self.scale_key_selector.get() index_of_selected_key = KEYS.index(self.scale_selected_key) self.keys_to_highlight = [ ALL_KEYS[i+index_of_selected_key] \ for i in self.scales[self.selected_scale]] self.highlight_list_of_keys(self.keys_to_highlight) play_scale_in_new_thread(self.keys_to_highlight) def highlight_list_of_keys(self, key_names): for key in key_names: self.highlight_key(key) def highlight_key(self, key_name): if len(key_name) == 2: img = WHITE_KEY_PRESSED_IMAGE elif len(key_name) == 3: img = BLACK_KEY_PRESSED_IMAGE key_img = PhotoImage(file=img) for widget in self.keys: if widget.name == key_name: widget.configure(image=key_img) widget.image = key_img def remove_key_highlight(self, key_name): if len(key_name) == 2: img = WHITE_KEY_IMAGE elif len(key_name) == 3: img = BLACK_KEY_IMAGE key_img = PhotoImage(file=img) for widget in self.keys: if widget.name == key_name: widget.configure(image=key_img) widget.image = key_img def remove_all_key_highlights(self): for key in self.keys_to_highlight: self.remove_key_highlight(key) self.keys_to_highlight = [] def build_mode_selector_frame(self): self.mode_selector_frame = Frame(self.root, width=WINDOW_WIDTH, height=MODE_SELECTOR_HEIGHT) self.mode_selector_frame.grid_propagate(False) self.mode_selector = ttk.Combobox(self.mode_selector_frame, values=CHOICES) self.mode_selector.bind('<<ComboboxSelected>>', self.on_mode_changed) self.mode_selector.current(0) self.mode_selector.grid( row=0, column=1, columnspan=3, padx=10, pady=10, sticky='nsew', ) self.mode_selector_frame.grid(row=0, column=0) def build_score_sheet_frame(self): self.score_sheet_frame = Frame(self.root, width=WINDOW_WIDTH, height=SCORE_DISPLAY_HEIGHT, background='SteelBlue1') self.score_sheet_frame.grid_propagate(False) Label(self.score_sheet_frame, text='placeholder for score sheet', background='SteelBlue1').grid(row=1, column=1) self.score_sheet_frame.grid(row=1, column=0) def build_controls_frame(self): self.controls_frame = Frame(self.root, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.controls_frame.grid_propagate(False) self.controls_frame.grid(row=2, column=0) def build_keyboard_frame(self): self.keyboard_frame = Frame(self.root, width=WINDOW_WIDTH, height=KEYBOARD_HEIGHT, background='LavenderBlush2') self.keyboard_frame.grid_propagate(False) self.keyboard_frame.grid(row=4, column=0, sticky='nsew') for (index, key) in enumerate(WHITE_KEY_NAMES): x = WHITE_KEY_X_COORDINATES[index] self.create_key(WHITE_KEY_IMAGE, key, x) for (index, key) in enumerate(BLACK_KEY_NAMES): x = BLACK_KEY_X_COORDINATES[index] self.create_key(BLACK_KEY_IMAGE, key, x) def build_scales_frame(self): self.scales_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.scales_frame.grid(row=1, column=0, sticky='nsew') Label(self.scales_frame, text='Select scale').grid(row=0, \ column=1, sticky='w', padx=10,pady=1) self.scale_selector = ttk.Combobox(self.scales_frame, \ values=[k for k in self.scales.keys()]) self.scale_selector.current(0) self.scale_selector.bind("<<ComboboxSelected>>", \ self.on_scale_changed) self.scale_selector.grid(row=1, column=1, sticky='e', padx=10,\ pady=10) Label(self.scales_frame, text='in the key of').grid(row=0, \ column=2, sticky='w', padx=10,pady=1) self.scale_key_selector = ttk.Combobox(self.scales_frame, \ values=[k for k in KEYS]) self.scale_key_selector.current(0) self.scale_key_selector.bind("<<ComboboxSelected>>", \ self.on_scale_key_changed) self.scale_key_selector.grid(row=1, column=2, sticky='e', \ padx=10, pady=10) def build_chords_frame(self): self.chords_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.chords_frame.grid_propagate(False) self.chords_frame.grid(row=1, column=0, sticky='nsew') Label(self.chords_frame, text='Select Chord').grid(row=0, \ column=1, sticky='w', padx=10,pady=1) self.chords_selector = ttk.Combobox(self.chords_frame, \ values=[k for k in self.chords.keys()]) self.chords_selector.current(0) self.chords_selector.bind("<<ComboboxSelected>>", \ self.on_chord_changed) self.chords_selector.grid(row=1, column=1, sticky='e', \ padx=10, pady=10) Label(self.chords_frame, text='in the key of').grid(row=0, \ column=2, sticky='w', padx=10,pady=1) self.chords_key_selector = ttk.Combobox(self.chords_frame, \ values=[k for k in KEYS]) self.chords_key_selector.current(0) self.chords_key_selector.bind("<<ComboboxSelected>>", \ self.on_chords_key_changed) self.chords_key_selector.grid(row=1, column=2, sticky='e', padx=10, pady=10) def build_progressions_frame(self): self.progressions_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.progressions_frame.grid_propagate(False) Label(self.progressions_frame, text='placeholder for progression frame').grid(row=1, column=1) self.progressions_frame.grid(row=1, column=0, sticky='nsew') def on_mode_changed(self, event): self.remove_all_key_highlights() selected_mode = self.mode_selector.get() if selected_mode == 'Scales': self.show_scales_frame() self.find_scale() elif selected_mode == 'Chords': self.show_chords_frame() self.find_chord() elif selected_mode == 'Chord Progressions': self.show_progressions_frame() def show_scales_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid_remove() self.scales_frame.grid() def show_chords_frame(self): self.chords_frame.grid() self.progressions_frame.grid_remove() self.scales_frame.grid_remove() def show_progressions_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid() self.scales_frame.grid_remove() def create_key(self, img, key_name, x_coordinate): key_image = PhotoImage(file=img) label = Label(self.keyboard_frame, image=key_image, border=0) label.image = key_image label.place(x=x_coordinate, y=0) label.name = key_name label.bind('<Button-1>', self.on_key_pressed) label.bind('<ButtonRelease-1>', self.on_key_released) self.keys.append(label) return label def change_image_to_pressed(self, event): if len(event.widget.name) == 2: img = WHITE_KEY_PRESSED_IMAGE elif len(event.widget.name) == 3: img = BLACK_KEY_PRESSED_IMAGE key_img = PhotoImage(file=img) event.widget.configure(image=key_img) event.widget.image = key_img def change_image_to_unpressed(self, event): if len(event.widget.name) == 2: img = WHITE_KEY_IMAGE elif len(event.widget.name) == 3: img = BLACK_KEY_IMAGE key_img = PhotoImage(file=img) event.widget.configure(image=key_img) event.widget.image = key_img def on_key_pressed(self, event): play_note(event.widget.name) self.change_image_to_pressed(event) def on_key_released(self, event): print(event.widget.name + ' released') self.change_image_to_unpressed(event)
class Spectrogram(Module): def __init__(self, app): info(' - initializing module: Spectrogram') self.app = app self.frame = Frame(self.app.BOTTOM) self.frame.grid(row=0, column=1, pady=(self.app.pady * 2, self.app.pady / 2)) self.axis_frame = Frame(self.app.BOTTOM) self.axis_frame.grid(row=0, column=0, sticky='e', pady=(self.app.pady * 2, self.app.pady / 2)) self.canvas_width = self.app.TextGrid.canvas_width self.canvas_height = 106 self.canvas = Canvas(self.frame, width=self.canvas_width, height=self.canvas_height, background='gray', highlightthickness=0) self.spectrogram = None self.spec_freq_max = DoubleVar() self.wl = DoubleVar() self.dyn_range = DoubleVar() self.clicktime = -1 self.specClick = False self.oldSelected = None self.doDefaults() #make spinboxes & buttons for spectrogram specs self.spinwin = Frame(self.axis_frame) #spinboxes axis_ceil_box = Spinbox(self.spinwin, textvariable=self.spec_freq_max, command=self.drawSpectrogram, width=7, increment=100, from_=0, to_=100000) axis_ceil_box.bind('<Return>', self.drawSpectrogram) axis_ceil_box.bind('<Escape>', lambda ev: self.spinwin.focus()) wl_box = Spinbox(self.spinwin, textvariable=self.wl, command=self.drawSpectrogram, width=7, increment=0.0005, from_=0, to_=1) wl_box.bind('<Return>', self.drawSpectrogram) wl_box.bind('<Escape>', lambda ev: self.spinwin.focus()) dyn_range_box = Spinbox(self.spinwin, textvariable=self.dyn_range, command=self.drawSpectrogram, width=7, increment=10, from_=0, to_=10000) dyn_range_box.bind('<Return>', self.drawSpectrogram) dyn_range_box.bind('<Escape>', lambda ev: self.spinwin.focus()) #buttons default_btn = Button(self.spinwin, text='Standards', command=self.restoreDefaults, takefocus=0) apply_btn = Button(self.spinwin, text='Apply', command=self.drawSpectrogram, takefocus=0) # self.axis_frame.create_window(wwidth,self.canvas_height, window=self.spinwin, anchor='ne') #grid spinboxes & buttons on subframe axis_ceil_box.grid(row=0, columnspan=2, sticky='ne') wl_box.grid(row=1, columnspan=2, sticky='ne') dyn_range_box.grid(row=2, columnspan=2, sticky='ne') default_btn.grid(row=3) apply_btn.grid(row=3, column=1) self.grid() self.canvas.bind('<Button-1>', self.jumpToFrame) # self.canvas.bind('<Shift-Button-1>', self.jumpToFrame) def doDefaults(self): self.spec_freq_max.set(5000.0) self.wl.set(0.005) self.dyn_range.set(90) def restoreDefaults(self): self.doDefaults() self.drawSpectrogram() def update(self): ''' Removes and redraws lines on top of Spectrogram corresponding to selected interval(s) ''' self.canvas.delete('line') self.drawInterval() def reset(self): self.drawSpectrogram() self.drawInterval() def drawSpectrogram(self, event=None): ''' Extracts spectrogram data from sound, and draws it to canvas ''' if not LIBS_INSTALLED: return if self.app.Audio.current: sound = parselmouth.Sound(self.app.Audio.current) ts_fac = decimal.Decimal(10000.0) wl = decimal.Decimal(self.wl.get()) start_time = decimal.Decimal(self.app.TextGrid.start) end_time = decimal.Decimal(self.app.TextGrid.end) # the spectrogram is for the audio file, so it makes sense # to get the duration from the audio file and not from the # textgrid -JNW if start_time == end_time: end_time = decimal.Decimal(sound.get_total_duration()) duration = end_time - start_time #duration = decimal.Decimal(sound.get_total_duration()) # in case there isn't a TextGrid or there's some other issue: -JNW self.ts = duration / ts_fac # the amount taken off in spectrogram creation seems to be # ( 2 * ts * floor( wl / ts ) ) + ( duration % ts ) # but we've defined ts as duration / 10000, so duration % ts = 0 # so the amount to increase the length by is ts * floor( wl / ts ) # at either end - D.S. extra = self.ts * math.floor(wl / self.ts) start_time = max(0, start_time - extra) end_time = min(end_time + extra, sound.get_total_duration()) sound_clip = sound.extract_part(from_time=start_time, to_time=end_time) spec = sound_clip.to_spectrogram( window_length=wl, time_step=self.ts, maximum_frequency=self.spec_freq_max.get()) self.spectrogram = 10 * np.log10(np.flip(spec.values, 0)) # self.spectrogram += self.spectrogram.min() # self.spectrogram *= (60.0 / self.spectrogram.max()) mx = self.spectrogram.max() dyn = self.dyn_range.get() # debug(self.spectrogram.min(), self.spectrogram.max()) self.spectrogram = self.spectrogram.clip(mx - dyn, mx) - mx # debug(self.spectrogram.min(), self.spectrogram.max()) self.spectrogram *= (-255.0 / dyn) # self.spectrogram += 60 # debug(self.spectrogram.min(), self.spectrogram.max()) img = PIL.Image.fromarray(self.spectrogram) if img.mode != 'RGB': img = img.convert('RGB') # contrast = ImageEnhance.Contrast(img) # img = contrast.enhance(5) # self.canvas_height = img.height img = img.resize((self.canvas_width, self.canvas_height)) photo_img = ImageTk.PhotoImage(img) self.canvas.config(height=self.canvas_height) # self.canvas.create_image(0,0, anchor='nw', image=photo_img) # self.canvas.create_image(self.canvas_width/2,self.canvas_height/2, image=photo_img) if self.app.TextGrid.selectedItem: tags = self.app.TextGrid.selectedItem[0].gettags( self.app.TextGrid.selectedItem[1]) self.canvas.delete('all') img = self.canvas.create_image(self.canvas_width, self.canvas_height, anchor='se', image=photo_img) self.img = photo_img #pass on selected-ness if self.app.TextGrid.selectedItem: if self.app.TextGrid.selectedItem[0] == self.canvas: self.app.TextGrid.selectedItem = (self.canvas, img) #pass on tags for tag in tags: self.canvas.addtag_all(tag) def drawInterval(self): ''' Adapted with permission from https://courses.engr.illinois.edu/ece590sip/sp2018/spectrograms1_wideband_narrowband.html by Mark Hasegawa-Johnson ''' if self.app.TextGrid.selectedItem: widg = self.app.TextGrid.selectedItem[0] itm = self.app.TextGrid.selectedItem[1] if widg in self.app.TextGrid.tier_pairs: #if widg is label itvl_canvas = self.app.TextGrid.tier_pairs[widg] for i in itvl_canvas.find_withtag('line'): loc = itvl_canvas.coords(i)[0] self.canvas.create_line(loc, 0, loc, self.canvas_height, tags='line', fill='blue') elif widg in self.app.TextGrid.tier_pairs.values( ): #if widg is textgrid canvas if itm - 1 in widg.find_all(): l_loc = widg.coords(itm - 1)[0] self.canvas.create_line(l_loc, 0, l_loc, self.canvas_height, tags='line', fill='blue') if itm + 1 in widg.find_all(): r_loc = widg.coords(itm + 1)[0] self.canvas.create_line(r_loc, 0, r_loc, self.canvas_height, tags='line', fill='blue') elif widg == self.canvas: l_time, r_time = self.app.TextGrid.getMinMaxTime() l_loc = self.timeToX(float(l_time)) r_loc = self.timeToX(float(r_time)) self.canvas.create_line(l_loc, 0, l_loc, self.canvas_height, tags='line', fill='blue') self.canvas.create_line(r_loc, 0, r_loc, self.canvas_height, tags='line', fill='blue') #draw selected frame if self.app.TextGrid.firstFrame <= self.app.frame <= self.app.TextGrid.lastFrame: xcoord = self.app.TextGrid.frames_canvas.coords( self.app.TextGrid.highlighted_frame)[0] self.canvas.create_line(xcoord, 0, xcoord, self.canvas_height, tags='line', fill='red') #draw line where user last clicked on spectrogram if self.clicktime != -1 and self.specClick == False: x = self.timeToX(self.clicktime) self.canvas.create_line(x, 0, x, self.canvas_height, tags='line', fill='green') def jumpToFrame(self, event): ''' ''' #restore textgrid selected interval between clicks if not self.app.TextGrid.selectedItem: key = next(iter(self.app.TextGrid.tier_pairs)) wdg = self.app.TextGrid.tier_pairs[key] self.app.TextGrid.selectedItem = (wdg, wdg.find_all()[0]) self.app.TextGrid.setSelectedIntvlFrames( self.app.TextGrid.selectedItem) if self.app.TextGrid.selectedItem[0] == self.canvas: self.app.TextGrid.selectedItem = self.oldSelected self.app.TextGrid.setSelectedIntvlFrames( self.app.TextGrid.selectedItem) #prevents wiping of canvases because of mouse click # self.app.resized = False # draw line at click location x = self.canvas.canvasx(event.x) self.clicktime = self.xToTime(x) #jump to new frame frame = self.app.TextGrid.my_find_closest( self.app.TextGrid.frames_canvas, self.canvas.canvasx(event.x)) framenum = self.app.TextGrid.frames_canvas.gettags(frame)[0][5:] self.app.frame = int(framenum) self.app.framesUpdate() #remember which interval was selected before specgram click if event.state == 1: self.oldSelected = self.app.TextGrid.selectedItem #for selecting & zooming interval (w/ shift) self.specClick = True def xToTime(self, x): ''' converts from a x coordinate (relative to the canvas) to the timestamp at that coordinate''' return (x * float(self.app.TextGrid.end - self.app.TextGrid.start) / self.canvas_width) + float(self.app.TextGrid.start) def timeToX(self, time): ''' converts from a time to the x coordinate on a canvas representing that time''' return self.canvas_width * (time - float( self.app.TextGrid.start)) / float(self.app.TextGrid.end - self.app.TextGrid.start) def grid(self): ''' Put tkinter items on app ''' self.canvas.grid(row=0, column=0, sticky='news') self.spinwin.grid(row=0, column=0, sticky='ne') # self.axis_canvas.grid(row=0,column=0,sticky='se') def grid_remove(self): self.canvas.grid_remove() self.spinwin.grid_remove()
class Playback(Module): ''' Module to handle playback of audio and video files. ''' def __init__(self, app): self.app = app self.current = None if AUDIO_LIBS_INSTALLED: info( ' - initializing module: Audio' ) self.sfile = None self.p = pyaudio.PyAudio() self.currentInterval = None self.started = False self.paused = False self.sync = threading.Event() self.stoprequest = threading.Event() # widget management self.frame = Frame(self.app.BOTTOM) self.playBtn = Button(self.frame, text="Play/Pause", command=self.playpauseAV, state='disabled', takefocus=0) # NOTE: not currently appearing self.app.bind('<space>', self.playpauseAV ) self.app.bind('<Escape>', self.stopAV ) if VIDEO_LIBS_INSTALLED: info( ' - initializing module: Video' ) self.app.bind('<space>', self.playpauseAV ) self.app.bind('<Escape>', self.stopAV ) self.reset() def update(self): ''' don't change the audio file when we change frames ''' pass def reset(self): ''' try to load an audio file ''' if AUDIO_LIBS_INSTALLED: self.current = None audioFallbacks = [ '.wav', '.flac', '.ogg', '.mp3' ] for codec in audioFallbacks: if self.loadAudio( codec ) == True: self.playBtn.config( state='normal' ) return def loadAudio(self, codec): ''' load an audio file with a specific codec ''' audiofile = self.app.Data.getFileLevel( codec ) if audiofile != None: try: audiofile = self.app.Data.unrelativize(audiofile) self.sfile = AudioSegment.from_file( audiofile ) self.current = audiofile self.duration = len(self.sfile)/1000.0 return True except Exception as e: error('Unable to load audio file: `%s`' % audiofile, e) return False def playpauseAV(self, event): ''' ''' # debug(self.started, self.paused, '1858') if self.started == False or self.currentInterval != self.app.TextGrid.selectedItem: #if we haven't started playing or we're in a new interval #reset monitoring variables self.currentInterval = self.app.TextGrid.selectedItem self.started = False self.paused = False if self.app.TextGrid.selectedItem: start, end = self.app.TextGrid.getMinMaxTime() else: start = self.app.TextGrid.start end = self.app.TextGrid.end # if VIDEO_LIBS_INSTALLED and AUDIO_LIBS_INSTALLED: # self.readyVideo() # self.readyAudio(start, end) # self.playAudio() # elif AUDIO_LIBS_INSTALLED: # self.readyAudio(start, end) # self.playAudio() # elif VIDEO_LIBS_INSTALLED: # self.readyVideo() # self.dicomframeQ = queue.Queue() # for i in range(len(self.pngs)): # self.dicomframeQ.put(self.pngs[i]) # self.playVideoNoAudio() if self.app.Dicom.isLoaded(): self.readyVideo() if AUDIO_LIBS_INSTALLED: self.readyAudio(start, end) self.playAudio() elif self.app.Dicom.isLoaded(): self.dicomframeQ = queue.Queue() for i in range(len(self.pngs)): self.dicomframeQ.put(self.pngs[i]) self.playVideoNoAudio() elif self.started == True: if self.paused == False: self.paused = True self.stream.stop_stream() else: self.paused = False self.playAudio() def readyAudio(self, start, end): ''' ''' #audio stuff start_idx = round(float(start)*1000) end_idx = round(float(end)*1000) self.flen = float(self.app.TextGrid.frame_len) fpb = 512 extrafs = (end_idx-start_idx)%fpb extrasecs = extrafs/self.sfile.frame_rate pad = AudioSegment.silent(duration=round(extrasecs*1000)) seg_nopad = self.sfile[start_idx:end_idx] self.seg = seg_nopad + pad # seg.append() self.audioframe = 0 # open stream using callback (3) self.stream = self.p.open(format=self.p.get_format_from_width(self.seg.sample_width), channels=self.seg.channels, rate=self.seg.frame_rate, frames_per_buffer=fpb, output=True, start=False, stream_callback=self.callback) # debug(self.seg.frame_count()/fpb, 'number of chunks') # debug(self.seg.frame_count()%fpb, 'last chunk size') # self.chunkcount = 0 def readyVideo(self): ''' ''' self.app.Trace.reset() tags = self.app.TextGrid.selectedItem[0].gettags(self.app.TextGrid.selectedItem[1]) framenums = [tag[5:] for tag in tags if tag[:5]=='frame'] self.framestart = int(framenums[0]) imgs = self.app.Dicom.getFrames(framenums) canvas = self.app.Dicom.zframe.canvas bbox = canvas.bbox(canvas.find_all()[0]) dim = (bbox[2] - bbox[0], bbox[3] - bbox[1]) self.pngs = [] traces = self.app.Data.getTopLevel('traces') file = self.app.Data.getCurrentFilename() l = util.CROSSHAIR_SELECT_RADIUS for frame, img in zip(framenums, imgs): img = img.resize(dim) draw = ImageDraw.Draw(img) for name in traces: color = traces[name]['color'] if file in traces[name]['files'] and frame in traces[name]['files'][file]: for pt in traces[name]['files'][file][frame]: x = int(pt['x'] * img.width) y = int(pt['y'] * img.height) draw.line((x-l, y, x+l, y), fill=color) draw.line((x, y-l, x, y+l), fill=color) del draw self.pngs.append(ImageTk.PhotoImage(img)) #video w/audio stuff self.dicomframe_timer = 0 self.dicomframe_num = 1 self.dicomframeQ = queue.Queue() self.dicomframeQ.put(self.pngs[0]) #put now, because audio callback puts frames when audio segments end # for i in range(len(self.pngs)): # self.dicomframeQ.put(self.pngs[i]) def callback(self, in_data, frame_count, time_info, status): ''' Called by pyaudio stream. Gets chunks of audio ready for playing With video capabilities, also updates video frame information ''' # self.sync.clear() # self.chunkcount+=1 data = b''.join([self.seg.get_frame(i) for i in range(self.audioframe, self.audioframe+frame_count)]) # debug(len(data), 'line 1960') self.audioframe+=frame_count if self.app.Dicom.isLoaded(): #check & update video frame canvas = self.app.Dicom.zframe.canvas callbacklen = frame_count/self.seg.frame_rate self.dicomframe_timer += callbacklen #go to next frame if self.dicomframe_timer % self.flen != self.dicomframe_timer and self.dicomframe_num < len(self.pngs): floor = math.floor(self.dicomframe_timer/self.flen) # debug(floor, 'line 1961') self.dicomframe_timer = self.dicomframe_timer-self.flen*floor if floor > 1: for i in range(floor-1): # debug(self.dicomframe_num+self.framestart+i, 'putting frame into Q') if self.dicomframe_num+i < len(self.pngs): self.dicomframeQ.put(self.pngs[self.dicomframe_num+i]) else: self.dicomframeQ.put(self.pngs[self.dicomframe_num]) # self.sync.set() self.dicomframe_num+=floor # debug(self.dicomframe_num, len(self.pngs), 'line 1968') # else: #stop video loop if self.dicomframe_num >= len(self.pngs): self.stoprequest.set() return (data, pyaudio.paContinue) def playAudio(self): self.stream.start_stream() self.started = True if self.app.Dicom.isLoaded(): self.playVideoWithAudio() else: pass #write a loop that keeps audio playing # stop stream (6) if self.stoprequest.is_set(): self.stopAV() # self.stream.stop_stream() # if self.stoprequest.is_set(): # self.stream.close() # self.started = False # debug(self.chunkcount) # close PyAudio (7) # self.p.terminate() # NOTE: needs to be removed in order to play multiple audio files in a row def playVideoWithAudio(self): ''' ''' # self.sync.wait() if self.paused == True: return canvas = self.app.Dicom.zframe.canvas # debug(self.dicomframeQ.qsize(),'line 1991') try: pic = self.dicomframeQ.get(timeout=.5) canvas.itemconfig(canvas.find_all()[0] , image=pic ) # canvas.lift(pic) # canvas.img = pic canvas.update() except Exception as e: error(e) # debug(pic, 'displayed') # debug(self.dicomframe_num+self.framestart, 'displayed') if not self.stoprequest.is_set() or not self.dicomframeQ.empty(): #should this if be at the top? self.playVideoWithAudio() # canvas.after(10, self.playVideoWithAudio) def playVideoNoAudio(self): ''' ''' canvas = self.app.Dicom.zframe.canvas # pic = self.dicomframeQ.get() pic = self.dicomframeQ.get(block=False) canvas.itemconfig( canvas.find_all()[0], image=pic ) canvas.update() if not self.dicomframeQ.empty() and self.stoprequest.is_set() == False: #should this if be at the top? self.playVideoNoAudio() def stopAV(self,event=None): self.stoprequest.set() if AUDIO_LIBS_INSTALLED: self.stream.stop_stream() self.stream.close() self.started = False self.paused = False self.app.framesJumpTo() self.stoprequest.clear() def grid(self): ''' grid widgets ''' self.frame.grid( row=0 ) self.playBtn.grid() def grid_remove(self): ''' remove widgets from grid ''' self.frame.grid_remove() self.playBtn.grid_remove()
class Tab(ABC): def __init__(self, view, tab_control): self.view = view self.bandas_estandar_repository = RepositoryProvider.provide_bandas_estandar_repository( ) self.tab_frame = tab_control.agregar_tab(self, self.titulo_tab) self.construir_tab() @abstractmethod def obtener_bandas(self): pass def construir_tab(self): self.construir_frame_titulo() self.construir_frame_grafica() self.construir_frame_medicion() def construir_frame_titulo(self): self.frame_titulo_grafica = Frame(self.tab_frame) self.frame_titulo_grafica.config(width=400, borderwidth=2, relief="groove") self.frame_titulo_grafica.grid(row=0, column=0, sticky="nsew", padx=10, pady=(15, 0)) self.label_titulo_grafica = Label(self.frame_titulo_grafica) self.label_titulo_grafica.config( text="Nivel de respuesta impulsional - Curva de decaimiento", bg="#0c005a") self.label_titulo_grafica.pack(fill="both", expand="True") def construir_frame_grafica(self): self.frame_grafica = Frame(self.tab_frame) self.frame_grafica.grid(row=1, column=0, padx=10, pady=10) self.frame_label_grafica = Frame(self.frame_grafica) self.frame_label_grafica.config(width=600, height=400) self.frame_label_grafica.pack_propagate(False) self.frame_label_grafica.grid(row=0, column=0) self.label_grafica = Label(self.frame_label_grafica) self.label_grafica.config(borderwidth=2, relief="groove", bg="#5893d4") self.label_grafica.pack(expand="True", fill="both") self.frame_toolbar = Frame(self.frame_grafica) self.frame_toolbar.config(width=400, height=40, borderwidth=2) self.frame_toolbar.pack_propagate(False) self.frame_toolbar.grid(row=1, column=0, sticky="nsew") self.construir_plot() def construir_plot(self): self.figura = Figure(figsize=(6, 4), dpi=100) self.figura.patch.set_facecolor("#becbff") self.sistema_ejes = self.figura.add_subplot(1, 1, 1) self.sistema_ejes.set_facecolor("#dee1ec") self.limpiar_ejes() self.canvas = FigureCanvasTkAgg(self.figura, master=self.label_grafica) self.canvas.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=True) toolbar = NavigationToolbar2Tk(self.canvas, self.frame_toolbar) toolbar.update() def limpiar_ejes(self): self.sistema_ejes.cla() self.sistema_ejes.set_xlabel('Tiempo (s)') self.sistema_ejes.set_ylabel('Nivel (dB)') self.sistema_ejes.set_xlim(left=0, auto=True) self.sistema_ejes.set_ylim(bottom=-120, top=0, auto=True) def construir_frame_medicion(self): self.frame_medicion = Frame(self.tab_frame) self.frame_medicion.grid(row=0, column=1, rowspan=2, sticky="nsew") self.construir_frame_bandas() def construir_frame_bandas(self): self.construir_seleccion_banda() self.construir_frame_rts() def construir_seleccion_banda(self): self.frame_titulo_bandas = Label(self.frame_medicion) self.frame_titulo_bandas.config(borderwidth=2, relief="groove") self.frame_titulo_bandas.grid(row=0, column=0, sticky="nsew", padx=10, pady=(15, 0)) self.label_titulo_bandas_octava = Label(self.frame_titulo_bandas) self.label_titulo_bandas_octava.config(text=self.titulo_bandas_text, bg="#0c005a") self.label_titulo_bandas_octava.pack(ipadx=10, expand="True", fill="both") self.frame_medicion_bandas = Frame(self.frame_medicion) self.frame_medicion_bandas.grid(row=1, column=0, sticky="nsew", padx=10, pady=(20, 0)) bandas_estandar = self.obtener_bandas() self.banda_seleccionada = StringVar() self.banda_seleccionada.set(bandas_estandar[0]) self.combobox_banda = OptionMenu(self.frame_medicion_bandas, self.banda_seleccionada, *bandas_estandar) self.combobox_banda.config(relief="groove", borderwidth=0, bg="#5893d4", activebackground="#0060ca", width=20) self.combobox_banda['menu'].config(bg="#5893d4", activebackground="#0060ca") self.combobox_banda.grid(row=0, column=0, padx=10) self.ponderacion_A_checked = BooleanVar(False) self.checkbutton_ponderacion_A = Checkbutton( self.frame_medicion_bandas) self.checkbutton_ponderacion_A.config( text="Ponderación A", variable=self.ponderacion_A_checked, selectcolor="#5e0606") self.checkbutton_ponderacion_A.grid(row=0, column=1, padx=20) self.boton_calcular = Button(self.frame_medicion_bandas) self.boton_calcular.config(text="Calcular", command=self.view.on_calcular, bg="#5e0606", width=20) self.boton_calcular.grid(row=0, column=2, padx=10) def construir_frame_rts(self): self.frame_rts = Frame(self.frame_medicion) self.frame_rts.config(borderwidth=2, relief='ridge') self.frame_rts.grid(row=4, column=0, padx=10, pady=(15, 0)) self.frame_titulo_rts = Label(self.frame_rts) self.frame_titulo_rts.config(borderwidth=2, relief="groove") self.frame_titulo_rts.grid(row=0, column=0, sticky="nsew", padx=10, pady=10, columnspan=2) self.label_titulo_rts = Label(self.frame_titulo_rts) self.label_titulo_rts.config(text="Tiempos de reverberación", bg="#0c005a") self.label_titulo_rts.pack(ipadx=10, expand="True", fill="both") self.frame_titulo_linealidad = Label(self.frame_rts) self.frame_titulo_linealidad.config(borderwidth=2, relief="groove") self.frame_titulo_linealidad.grid(row=0, column=2, sticky="nsew", padx=10, pady=10, columnspan=4) self.label_titulo_linealidad = Label(self.frame_titulo_linealidad) self.label_titulo_linealidad.config(text="Parámetros de linealidad", bg="#0c005a") self.label_titulo_linealidad.pack(ipadx=10, expand="True", fill="both") self.construir_frame_edt() self.construir_frame_t20() self.construir_frame_t30() self.construir_frame_curvatura() self.construir_frame_progressbar() def construir_frame_edt(self): self.frame_edt = Frame(self.frame_rts) self.frame_edt.grid(row=1, column=0, pady=(0, 10), columnspan=2) self.label_edt = Label(self.frame_edt) self.label_edt.config(text="EDT", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_edt.grid(row=0, column=0, padx=(0, 10), pady=10) self.edt_var = StringVar() self.label_res_edt = Label(self.frame_edt) self.label_res_edt.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.edt_var, fg="black") self.label_res_edt.grid(row=0, column=1, padx=(10, 0), pady=10) self.frame_linealidad_edt = Frame(self.frame_rts) self.frame_linealidad_edt.grid(row=1, column=2, pady=(0, 10), columnspan=4) self.label_r_edt = Label(self.frame_linealidad_edt) self.label_r_edt.config(text="r", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_r_edt.grid(row=0, column=0, padx=10, pady=10) self.r_edt_var = StringVar() self.label_res_r_edt = Label(self.frame_linealidad_edt) self.label_res_r_edt.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.r_edt_var, fg="black") self.label_res_r_edt.grid(row=0, column=1, padx=10, pady=10) self.label_xi_edt = Label(self.frame_linealidad_edt) self.label_xi_edt.config(text="ξ", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_xi_edt.grid(row=0, column=2, padx=10, pady=10) self.xi_edt_var = StringVar() self.label_res_xi_edt = Label(self.frame_linealidad_edt) self.label_res_xi_edt.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, fg="black", textvariable=self.xi_edt_var) self.label_res_xi_edt.grid(row=0, column=3, padx=10, pady=10) def construir_frame_t20(self): self.frame_t20 = Frame(self.frame_rts) self.frame_t20.grid(row=2, column=0, pady=(0, 10), columnspan=2) self.label_t20 = Label(self.frame_t20) self.label_t20.config(text="T20", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_t20.grid(row=0, column=0, padx=(0, 10), pady=10, sticky='w') self.t20_var = StringVar() self.label_res_t20 = Label(self.frame_t20) self.label_res_t20.config(relief="sunken", borderwidth=2, bg="#becbff", width=10, textvariable=self.t20_var, fg='black') self.label_res_t20.grid(row=0, column=1, padx=(10, 0), pady=10, sticky='e') self.frame_linealidad_t20 = Frame(self.frame_rts) self.frame_linealidad_t20.grid(row=2, column=2, pady=(0, 10), columnspan=4) self.label_r_t20 = Label(self.frame_linealidad_t20) self.label_r_t20.config(text="r", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_r_t20.grid(row=0, column=2, padx=10, pady=10) self.r_t20_var = StringVar() self.label_res_r_t20 = Label(self.frame_linealidad_t20) self.label_res_r_t20.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.r_t20_var, fg='black') self.label_res_r_t20.grid(row=0, column=3, padx=10, pady=10) self.label_xi_t20 = Label(self.frame_linealidad_t20) self.label_xi_t20.config(text="ξ", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_xi_t20.grid(row=0, column=4, padx=10, pady=10) self.xi_t20_var = StringVar() self.label_res_xi_t20 = Label(self.frame_linealidad_t20) self.label_res_xi_t20.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, fg='black', textvariable=self.xi_t20_var) self.label_res_xi_t20.grid(row=0, column=5, padx=10, pady=10) def construir_frame_t30(self): self.frame_t30 = Frame(self.frame_rts) self.frame_t30.grid(row=3, column=0, pady=(0, 10), columnspan=2) self.label_t30 = Label(self.frame_t30) self.label_t30.config(text="T30", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_t30.grid(row=0, column=0, padx=(0, 10), pady=10, sticky='w') self.t30_var = StringVar() self.label_res_t30 = Label(self.frame_t30) self.label_res_t30.config(relief="sunken", borderwidth=2, bg="#becbff", width=10, textvariable=self.t30_var, fg='black') self.label_res_t30.grid(row=0, column=1, padx=(10, 0), pady=10, sticky='e') self.frame_linealidad_t30 = Frame(self.frame_rts) self.frame_linealidad_t30.grid(row=3, column=2, pady=(0, 10), columnspan=4) self.label_r_t30 = Label(self.frame_linealidad_t30) self.label_r_t30.config(text="r", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_r_t30.grid(row=0, column=2, padx=10, pady=10) self.r_t30_var = StringVar() self.label_res_r_t30 = Label(self.frame_linealidad_t30) self.label_res_r_t30.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, textvariable=self.r_t30_var, fg='black') self.label_res_r_t30.grid(row=0, column=3, padx=10, pady=10) self.label_xi_t30 = Label(self.frame_linealidad_t30) self.label_xi_t30.config(text="ξ", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_xi_t30.grid(row=0, column=4, padx=10, pady=10) self.xi_t30_var = StringVar() self.label_res_xi_t30 = Label(self.frame_linealidad_t30) self.label_res_xi_t30.config(relief="sunken", bg="#becbff", borderwidth=2, width=10, fg='black', textvariable=self.xi_t30_var) self.label_res_xi_t30.grid(row=0, column=5, padx=10, pady=10) def construir_frame_curvatura(self): self.frame_curvatura = Frame(self.frame_rts) self.frame_curvatura.grid(row=4, column=2, pady=(0, 10), columnspan=4, sticky='e') self.label_curvatura = Label(self.frame_curvatura) self.label_curvatura.config(text="C", bg="#5893d4", borderwidth=2, relief="groove", width=4) self.label_curvatura.grid(row=0, column=0, padx=(0, 10), pady=10, sticky='w') self.curvatura_var = StringVar() self.label_res_curvatura = Label(self.frame_curvatura) self.label_res_curvatura.config(relief="sunken", borderwidth=2, bg="#becbff", width=10, textvariable=self.curvatura_var, fg='black') self.label_res_curvatura.grid(row=0, column=1, padx=10, pady=10) def get_frecuencia_central_banda_seleccionada(self): return float(self.banda_seleccionada.get()) def get_tipo(self): return self.tipo def verificar_ponderacion_A(self): return self.ponderacion_A_checked.get() def desactivar(self): self.combobox_banda.config(state=DISABLED) self.checkbutton_ponderacion_A.config(state=DISABLED) self.boton_calcular.config(state=DISABLED) def activar(self): self.combobox_banda.config(state=NORMAL) self.checkbutton_ponderacion_A.config(state=NORMAL) self.boton_calcular.config(state=NORMAL) def graficar(self, nivel_respuesta_impulsional, curva_decaimiento): dominio_temporal_ri = nivel_respuesta_impulsional.get_dominio_temporal( ) valores_ri = nivel_respuesta_impulsional.get_valores() dominio_temporal_cd = curva_decaimiento.get_dominio_temporal() valores_cd = curva_decaimiento.get_valores() self.limpiar_ejes() self.sistema_ejes.plot(dominio_temporal_ri, valores_ri, color='#0000ff', linewidth=0.5, label='Nivel respuesta impulsional') self.sistema_ejes.plot(dominio_temporal_cd, valores_cd, color="#ff0000", linewidth=1, label='Curva de decaimiento') self.sistema_ejes.legend() self.canvas.draw() def mostrar_tiempos_de_reverberacion(self, edt, t20, t30): self.edt_var.set(str(round(edt, 4)) + "seg") self.t20_var.set(str(round(t20, 4)) + "seg") self.t30_var.set(str(round(t30, 4)) + "seg") def mostrar_parametros_de_linealidad(self, edt, t20, t30, curvatura): self.r_edt_var.set(round(edt.get_coef_correlacion(), 4)) self.xi_edt_var.set(str(round(edt.get_xi(), 4)) + "‰") self.r_t20_var.set(round(t20.get_coef_correlacion(), 4)) self.xi_t20_var.set(str(round(t20.get_xi(), 4)) + "‰") self.r_t30_var.set(round(t30.get_coef_correlacion(), 4)) self.xi_t30_var.set(str(round(t30.get_xi(), 4)) + "‰") self.curvatura_var.set(str(round(curvatura, 4)) + "%") def construir_frame_progressbar(self): self.pb_frame = Frame(self.frame_medicion) self.pb_frame.config(padx=20, pady=20) self.frame_calculando = Frame(self.pb_frame) self.frame_calculando.grid(row=0, column=0, pady=10) self.label_calculando = Label(self.frame_calculando) self.label_calculando.config(text="Calculando") self.label_calculando.pack(expand="True", fill="both") self.progressbar = Progressbar(self.pb_frame) self.progressbar.config(mode="indeterminate", length=250) self.progressbar.grid(row=1, column=0, pady=10) def activar_progressbar(self): self.pb_frame.grid(row=5, column=0) self.progressbar.start(10) def desactivar_progressbar(self): self.progressbar.stop() self.pb_frame.grid_remove() def redibujar_canvas(self): self.canvas.draw() self.canvas.get_tk_widget().pack() def ocultar_grafica(self): self.canvas.get_tk_widget().pack_forget()
class PianoTutor: def __init__(self, root): self.root = root self.root.resizable(False, False) self.root.title('Piano Tutor') self.keys = [] self.progression_buttons = [] self.load_json_files() self.keys_to_highlight = [] self.build_mode_selector_frame() self.build_score_sheet_frame() self.build_controls_frame() self.build_keyboard_frame() self.build_chords_frame() self.build_progressions_frame() self.build_scales_frame() self.find_scale() def load_json_files(self): with open(SCALES_JSON_FILE, 'r') as f: self.scales = json.load(f, object_pairs_hook=OrderedDict) with open(CHORDS_JSON_FILE, 'r') as f: self.chords = json.load(f, object_pairs_hook=OrderedDict) with open(PROGRESSIONS_JSON_FILE, 'r') as f: self.progressions = json.load(f, object_pairs_hook=OrderedDict) def on_progression_scale_changed(self, event): selected_progression_scale = \ self.progression_scale_selector.get() progressions = [ k for k in self.progressions[selected_progression_scale].keys() ] self.progression_selector['values'] = progressions self.progression_selector.current(0) self.show_progression_buttons() def on_progression_key_changed(self, event): self.show_progression_buttons() def on_progression_changed(self, event): self.show_progression_buttons() def destroy_current_progression_buttons(self): for buttons in self.progression_buttons: buttons.destroy() def show_progression_buttons(self): self.destroy_current_progression_buttons() selected_progression_scale = \ self.progression_scale_selector.get() selected_progression = self.progression_selector.get().split('-') self.progression_buttons = [] for i in range(len(selected_progression)): self.progression_buttons.append( Button(self.progressions_frame, text=selected_progression[i], command=partial(self.on_progression_button_clicked, i))) sticky = ('W' if i == 0 else 'E') col = (i if i > 1 else 1) self.progression_buttons[i].grid(column=col, row=2, sticky=sticky, padx=10) def on_progression_button_clicked(self, i): self.remove_all_key_highlights() selected_progression = self.progression_selector.get().split('-')[i] if any(x.isupper() for x in selected_progression): selected_chord = 'Major' else: selected_chord = 'Minor' key_offset = ROMAN_TO_NUMBER[selected_progression] selected_key = self.progression_key_selector.get() index_of_selected_key = (KEYS.index(selected_key) + key_offset) \ % 12 self.keys_to_highlight = [ ALL_KEYS[j + index_of_selected_key] for j in self.chords[selected_chord] ] self.score_maker.draw_chord(self.keys_to_highlight) self.highlight_list_of_keys(self.keys_to_highlight) play_chord_in_new_thread(self.keys_to_highlight) def on_chord_changed(self, event): self.remove_all_key_highlights() self.find_chord(event) def on_chords_key_changed(self, event): self.remove_all_key_highlights() self.find_chord(event) def find_chord(self, event=None): self.selected_chord = self.chords_selector.get() self.chords_selected_key = self.chords_key_selector.get() index_of_selected_key = KEYS.index(self.chords_selected_key) self.keys_to_highlight = [ ALL_KEYS[i + index_of_selected_key] for i in self.chords[self.selected_chord] ] self.score_maker.draw_chord(self.keys_to_highlight) self.highlight_list_of_keys(self.keys_to_highlight) play_chord_in_new_thread(self.keys_to_highlight) def on_scale_changed(self, event): self.remove_all_key_highlights() self.find_scale(event) def on_scale_key_changed(self, event): self.remove_all_key_highlights() self.find_scale(event) def find_scale(self, event=None): self.selected_scale = self.scale_selector.get() self.scale_selected_key = self.scale_key_selector.get() index_of_selected_key = KEYS.index(self.scale_selected_key) self.keys_to_highlight = [ ALL_KEYS[i + index_of_selected_key] for i in self.scales[self.selected_scale] ] self.score_maker.draw_notes(self.keys_to_highlight) self.highlight_list_of_keys(self.keys_to_highlight) play_scale_in_new_thread(self.keys_to_highlight) def highlight_list_of_keys(self, key_names): for key in key_names: self.highlight_key(key) def highlight_key(self, key_name): if len(key_name) == 2: img = WHITE_KEY_PRESSED_IMAGE elif len(key_name) == 3: img = BLACK_KEY_PRESSED_IMAGE key_img = PhotoImage(file=img) for widget in self.keys: if widget.name == key_name: widget.configure(image=key_img) widget.image = key_img def remove_key_highlight(self, key_name): if len(key_name) == 2: img = WHITE_KEY_IMAGE elif len(key_name) == 3: img = BLACK_KEY_IMAGE key_img = PhotoImage(file=img) for widget in self.keys: if widget.name == key_name: widget.configure(image=key_img) widget.image = key_img def remove_all_key_highlights(self): for key in self.keys_to_highlight: self.remove_key_highlight(key) self.keys_to_highlight = [] def build_mode_selector_frame(self): self.mode_selector_frame = Frame(self.root, width=WINDOW_WIDTH, height=MODE_SELECTOR_HEIGHT) self.mode_selector_frame.grid_propagate(False) self.mode_selector = ttk.Combobox(self.mode_selector_frame, values=CHOICES) self.mode_selector.bind('<<ComboboxSelected>>', self.on_mode_changed) self.mode_selector.current(0) self.mode_selector.grid(row=0, column=1, columnspan=3, padx=10, pady=10, sticky='nsew') self.mode_selector_frame.grid(row=0, column=0) def build_score_sheet_frame(self): self.score_sheet_frame = Frame(self.root, width=WINDOW_WIDTH, height=SCORE_DISPLAY_HEIGHT) self.score_sheet_frame.grid_propagate(False) self.score_sheet_frame.grid(row=1, column=0) self.score_maker = ScoreMaker(self.score_sheet_frame) def build_controls_frame(self): self.controls_frame = Frame(self.root, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.controls_frame.grid_propagate(False) self.controls_frame.grid(row=2, column=0) def build_keyboard_frame(self): self.keyboard_frame = Frame(self.root, width=WINDOW_WIDTH, height=KEYBOARD_HEIGHT, background='LavenderBlush2') self.keyboard_frame.grid_propagate(False) self.keyboard_frame.grid(row=4, column=0, sticky='nsew') for (index, key) in enumerate(WHITE_KEY_NAMES): x = WHITE_KEY_X_COORDINATES[index] self.create_key(WHITE_KEY_IMAGE, key, x) for (index, key) in enumerate(BLACK_KEY_NAMES): x = BLACK_KEY_X_COORDINATES[index] self.create_key(BLACK_KEY_IMAGE, key, x) def build_scales_frame(self): self.scales_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.scales_frame.grid(row=1, column=0, sticky='nsew') Label(self.scales_frame, text='Select scale').grid(row=0, column=1, sticky='w', padx=10, pady=1) self.scale_selector = ttk.Combobox( self.scales_frame, values=[k for k in self.scales.keys()]) self.scale_selector.current(0) self.scale_selector.bind('<<ComboboxSelected>>', self.on_scale_changed) self.scale_selector.grid(row=1, column=1, sticky='e', padx=10, pady=10) Label(self.scales_frame, text='in the key of').grid(row=0, column=2, sticky='w', padx=10, pady=1) self.scale_key_selector = ttk.Combobox(self.scales_frame, values=[k for k in KEYS]) self.scale_key_selector.current(0) self.scale_key_selector.bind('<<ComboboxSelected>>', self.on_scale_key_changed) self.scale_key_selector.grid(row=1, column=2, sticky='e', padx=10, pady=10) def build_chords_frame(self): self.chords_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.chords_frame.grid_propagate(False) self.chords_frame.grid(row=1, column=0, sticky='nsew') Label(self.chords_frame, text='Select Chord').grid(row=0, column=1, sticky='w', padx=10, pady=1) self.chords_selector = ttk.Combobox( self.chords_frame, values=[k for k in self.chords.keys()]) self.chords_selector.current(0) self.chords_selector.bind('<<ComboboxSelected>>', self.on_chord_changed) self.chords_selector.grid(row=1, column=1, sticky='e', padx=10, pady=10) Label(self.chords_frame, text='in the key of').grid(row=0, column=2, sticky='w', padx=10, pady=1) self.chords_key_selector = ttk.Combobox(self.chords_frame, values=[k for k in KEYS]) self.chords_key_selector.current(0) self.chords_key_selector.bind('<<ComboboxSelected>>', self.on_chords_key_changed) self.chords_key_selector.grid(row=1, column=2, sticky='e', padx=10, pady=10) def build_progressions_frame(self): self.progressions_frame = Frame(self.controls_frame, width=WINDOW_WIDTH, height=CONTROLS_FRAME_HEIGHT) self.progressions_frame.grid_propagate(False) self.progressions_frame.grid(row=1, column=0, sticky='nsew') Label(self.progressions_frame, text='Select Scale').grid(row=0, column=1, sticky='w', padx=10, pady=1) Label(self.progressions_frame, text='Select Progression').grid(row=0, column=2, sticky='w', padx=10, pady=1) Label(self.progressions_frame, text='in the Key of').grid(row=0, column=3, sticky='w', padx=10, pady=1) self.progression_scale_selector = \ ttk.Combobox(self.progressions_frame, values=[k for k in self.progressions.keys()], width=18) self.progression_scale_selector.bind('<<ComboboxSelected>>', self.on_progression_scale_changed) self.progression_scale_selector.current(0) self.progression_scale_selector.grid(row=1, column=1, sticky='w', padx=10, pady=10) self.progression_selector = \ ttk.Combobox(self.progressions_frame, values=[k for k in self.progressions['Major'].keys()], width=18) self.progression_selector.bind('<<ComboboxSelected>>', self.on_progression_changed) self.progression_selector.current(0) self.progression_selector.grid(row=1, column=2, sticky='w', padx=10, pady=10) self.progression_key_selector = \ ttk.Combobox(self.progressions_frame, values=KEYS, width=18) self.progression_key_selector.current(0) self.progression_key_selector.bind('<<ComboboxSelected>>', self.on_progression_key_changed) self.progression_key_selector.grid(row=1, column=3, sticky='w', padx=10, pady=10) def on_mode_changed(self, event): self.remove_all_key_highlights() selected_mode = self.mode_selector.get() if selected_mode == 'Scales': self.show_scales_frame() self.find_scale() elif selected_mode == 'Chords': self.show_chords_frame() self.find_chord() elif selected_mode == 'Chord Progressions': self.show_progressions_frame() self.show_progression_buttons() def show_scales_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid_remove() self.scales_frame.grid() def show_chords_frame(self): self.chords_frame.grid() self.progressions_frame.grid_remove() self.scales_frame.grid_remove() def show_progressions_frame(self): self.chords_frame.grid_remove() self.progressions_frame.grid() self.scales_frame.grid_remove() def create_key(self, img, key_name, x_coordinate): key_image = PhotoImage(file=img) label = Label(self.keyboard_frame, image=key_image, border=0) label.image = key_image label.place(x=x_coordinate, y=0) label.name = key_name label.bind('<Button-1>', self.on_key_pressed) label.bind('<ButtonRelease-1>', self.on_key_released) self.keys.append(label) return label def change_image_to_pressed(self, event): if len(event.widget.name) == 2: img = WHITE_KEY_PRESSED_IMAGE elif len(event.widget.name) == 3: img = BLACK_KEY_PRESSED_IMAGE key_img = PhotoImage(file=img) event.widget.configure(image=key_img) event.widget.image = key_img def change_image_to_unpressed(self, event): if len(event.widget.name) == 2: img = WHITE_KEY_IMAGE elif len(event.widget.name) == 3: img = BLACK_KEY_IMAGE key_img = PhotoImage(file=img) event.widget.configure(image=key_img) event.widget.image = key_img def on_key_pressed(self, event): play_note(event.widget.name) self.change_image_to_pressed(event) def on_key_released(self, event): self.change_image_to_unpressed(event)
class fen_info(Tk): """ Fenêtre permettant de saisir les informations sur les joueurs """ def __init__(self): super().__init__() # Initialisation des pions à la valeur initiale. self.pion1 = "X" self.pion2 = "O" # Titre de la fenêtre self.title("Ultimate TIC-TAC-TOE") # Pour changer taille minimum de fenêtre et taille centrer, # changer variable self.width_fen, self.height_fen. self.width_fen, self.height_fen = 430, 500 # Taille minimum de la fenêtre self.minsize(self.width_fen, self.height_fen) # Centrer la fenêtre. centreFen(self, self.width_fen, self.height_fen) # Création d'un canvas avec l'image "logo.gif" canvas = Canvas(self, width=280, height=100) self.img = PhotoImage(file="logo.gif") canvas.create_image(280, 100, anchor=SE, image=self.img) canvas.grid(row=0, columnspan=5, pady=10) # Libellé - Nouvelle Partie Label(self, text="Nouvelle partie", font=("Arial", 16), fg="#0080FF", justify=CENTER).grid( row=1, columnspan=5, padx = 20, pady = 5) separateur(20).grid(row=10,columnspan=5) # Sélection du type de partie avec bouton radio self.choixJoueur = IntVar() r1 = Radiobutton(self, text="Jouer avec l'ordinateur", variable = self.choixJoueur, value = 1, command=self.define_choix) r1.select() r1.grid(row=20, column=0) r2 = Radiobutton(self, text="Jouer avec un autre joueur", variable = self.choixJoueur, value = 2, command=self.define_choix) r2.grid(row=20, column=1) # Saisie du nom du joueur 1. f_j1 = Frame(self, borderwidth=1, padx=5, pady=5, relief=SUNKEN) f_j1.grid(row=30, columnspan=5, padx=5, pady=5) Label(f_j1, text="Nom joueur 1:").grid(row=1, column=0, sticky=E, padx = 5, pady = 5) self.nom_joueur1 = Entry(f_j1) self.nom_joueur1.grid(row=1,column=1) # Sélection du pion joueur 1. Le pion restant est automatiquement attribué au joueur 2. Label(f_j1, text="Choix de pion:").grid(row=1, column=2, padx=5) self.sel_pion=IntVar() p1 = Radiobutton(f_j1, indicatoron=0, width=5, text="X", variable=self.sel_pion, value=1, command=self.choix_pion) p1.grid(row=1, column=3, padx=2) p1.select() Radiobutton(f_j1, indicatoron=0, width=5, text="O", variable=self.sel_pion, value=2, command=self.choix_pion).grid(row=1, column=4, padx=2) # Saisie du nom du joueur 2. Apparaît seulement si on sélection 2 joueurs. Voir define_choix self.f_j2 = Frame(self, width=420, borderwidth=1, padx=5, pady=5, relief=SUNKEN) Label(self.f_j2, text="Nom joueur 2").grid(row=1, column=0, sticky=E, padx = 5, pady = 5) self.nom_joueur2 = Entry(self.f_j2, state="disabled") self.nom_joueur2.grid(row=1, column=1) self.label_pion2 = Label(self.f_j2, text="Pion Joueur 2 = O") self.label_pion2.grid(row=1, column=2, padx=5) # Information sur l'ordinateur. Disparaît si on choisi 2 joueurs. self.f_ordi = Frame(self, width=420, borderwidth=1, padx=5, pady=5, relief=SUNKEN) self.f_ordi.grid(row=40, columnspan=5, padx=5, pady=5) Label(self.f_ordi, text="Ordinateur = Colosse", font=("Arial", 12), fg="#0080FF")\ .grid(row=1, column=0, sticky=E, padx = 5, pady = 5) self.pion_ordi = Label(self.f_ordi, text="| Pion de l'ordinateur = O", font=("Arial", 12), fg="#0080FF") self.pion_ordi.grid(row=1, column=2) separateur(20).grid(row=50,columnspan=5) # Sélection de la force de l'ordinateur self.choixForce = IntVar() self.f1 = Radiobutton(self, indicatoron=0, width = 20, padx = 20, text="Facile", variable=self.choixForce, value=1, command=self.define_choix) self.f1.select() self.f1.grid(row=60, columnspan=5) self.f2 = Radiobutton(self, indicatoron=0, width = 20, padx = 20, text="Moyen", variable=self.choixForce, value=2, command=self.define_choix) self.f2.grid(row=61, columnspan=5) self.f3 = Radiobutton(self, indicatoron=0, width = 20, padx = 20, text="Difficile", variable=self.choixForce, value=3, command=self.define_choix) self.f3.grid(row=62, columnspan=5) separateur(40).grid(row=70, column=0) #Button pour démarrer la partie self.bt_start = Button(text="Démarrer", font=("Arial", 12), fg="green", command=self.demarrer_jeu) self.bt_start.grid(row=80, columnspan=5) def define_choix(self): """ Fonction qui active ou désactive le nom du joueur 2 selon si on joue contre l'ordinateur ou contre un autre joueur """ if self.choixJoueur.get()==1: self.nom_joueur2.delete(0, END) self.nom_joueur2["state"]="disabled" self.f1["state"]="normal" self.f2["state"]="normal" self.f3["state"]="normal" self.f_j2.grid_remove() self.f_ordi.grid(row=40, columnspan=5, padx=5, pady=5) elif self.choixJoueur.get()==2: self.nom_joueur2["state"]="normal" self.f1["state"]="disabled" self.f2["state"]="disabled" self.f3["state"]="disabled" self.f_j2.grid(row=40, columnspan=5, padx=5, pady=5) self.f_ordi.grid_remove() def choix_pion(self): # Définition des pions if self.sel_pion.get()==1: self.pion1="X" self.pion2="O" self.label_pion2["text"]="Pion Joueur 2 = {}".format(self.pion2) self.pion_ordi["text"]="| Pion de l'ordinateur = {}".format(self.pion2) else: self.pion1="O" self.pion2="X" self.label_pion2["text"]="Pion Joueur 2 = {}".format(self.pion2) self.pion_ordi["text"]="| Pion de l'ordinateur = {}".format(self.pion2) def demarrer_jeu(self): """ Démarrer la partie avec les informations saisie. Afficher le plateau """ if self.choixJoueur.get()==1: type2 = "Ordinateur" if self.nom_joueur1.get()!='': j1 = self.nom_joueur1.get() j2 = "Colosse" else: j1 = "Joueur 1" j2 = "Colosse" elif self.choixJoueur.get()==2: type2 = "Personne" if self.nom_joueur1.get()!='' and self.nom_joueur2.get()!='': j1 = self.nom_joueur1.get() j2 = self.nom_joueur2.get() elif self.nom_joueur1.get()=='': j1 = "Joueur 1" if self.nom_joueur2.get()=='': j2 = "Joueur 2" else: j2 = self.nom_joueur2.get() else: j1 = self.nom_joueur1.get() if self.nom_joueur2.get()=='': j2 = "Joueur 2" else: j2 = self.nom_joueur2.get() p1 = self.pion1 p2 = self.pion2 force = self.choixForce.get() self.destroy() ma_fenetre = Fenetre(j1, j2, type2, p1, p2, force) ma_fenetre.mainloop()
class GUI(Tk): 'Graphic user interface using Tkinter, main / root window' def __init__(self, root, worker): 'Generate object for main / root window.' self.root = root self.worker = worker ### "constants" for the gui ### if self.worker.storage.windows: self.JOBLISTLENGTH = 10 self.BUTTONWIDTH = 16 self.BIGENTRYWIDTH = 128 self.INTWIDTH = 6 self.TARGETWIDTH = 160 self.PADX = 8 self.PADY = 8 self.OPTPADX = 6 self.CHNGWIDTH = 144 self.CHNGHEIGHT = 12 self.MSGHEIGHT = 8 else: self.JOBLISTLENGTH = 10 self.BUTTONWIDTH = 16 self.BIGENTRYWIDTH = 96 self.INTWIDTH = 6 self.TARGETWIDTH = 120 self.PADX = 8 self.PADY = 8 self.OPTPADX = 6 self.CHNGWIDTH = 128 self.CHNGHEIGHT = 14 self.MSGHEIGHT = 8 ############################### self.__close2quit__() # handle closing of root window self.jobs = [] # start with empty list for the jobs self.root.title('Social Media Downloader') # window title for somedo self.__set_icon__( self.root) # give the window manager an application icon frame_jobs = LabelFrame( self.root, text=' \u25a4 Jobs ' ) # in this tk-frame the jobs will be displayed frame_jobs.pack(fill=X, expand=True, padx=self.PADX, pady=self.PADY) frame_jobs_inner = Frame(frame_jobs) frame_jobs_inner.pack(fill=X, expand=True, padx=self.PADX, pady=self.PADY) self.tk_jobbuttons = [] self.jobbuttons = [] self.upbuttons = [] self.downbuttons = [] for i in range(self.JOBLISTLENGTH): frame_row = Frame(frame_jobs_inner) frame_row.pack(fill=X, expand=True) self.tk_jobbuttons.append(StringVar(frame_row)) self.jobbuttons.append( Button(frame_row, textvariable=self.tk_jobbuttons[i], anchor=W, command=partial(self.__job_edit__, i))) self.jobbuttons[i].pack(side=LEFT, fill=X, expand=True) self.upbuttons.append( Button(frame_row, text='\u2191', command=partial(self.__job_up__, i))) self.upbuttons[i].pack(side=LEFT) self.downbuttons.append( Button(frame_row, text='\u2193', command=partial(self.__job_down__, i))) self.downbuttons[i].pack(side=LEFT) self.colour_fg = self.jobbuttons[0].cget('fg') self.colour_bg = self.jobbuttons[0].cget('bg') frame_row = Frame(frame_jobs_inner) frame_row.pack(fill=BOTH, expand=True) self.startbutton = Button(frame_row, text="\u25b9 Start jobs", width=self.BUTTONWIDTH, command=self.__start__) self.startbutton.pack(side=LEFT, pady=self.PADY) Label(frame_row, text=' ').pack(side=LEFT) self.stopbutton = Button(frame_row, text="\u25ad Stop / Abort", width=self.BUTTONWIDTH, state=DISABLED, command=self.__stop__) self.stopbutton.pack(side=LEFT, padx=self.PADX, pady=self.PADY) self.purgebutton = Button(frame_row, text='\u2672 Purge job list', width=self.BUTTONWIDTH, command=self.__purge_jobs__) self.purgebutton.pack(side=RIGHT, pady=self.PADY) frame_row = LabelFrame(self.root, text=' + Add Job ') # add job frame frame_row.pack(fill=X, expand=True, padx=self.PADX, pady=self.PADY) self.modulebuttons = dict() for i in self.worker.modulenames: # generate buttons for the modules self.modulebuttons[i] = Button(frame_row, text='\u271a %s' % i, font='bold', height=3, command=partial( self.__new_job__, i)) self.modulebuttons[i].pack(side=LEFT, fill=BOTH, expand=True, padx=self.PADX, pady=self.PADY) self.frame_changeling = LabelFrame( self.root) # frame for configuration or messages self.frame_changeling.pack(fill=X, expand=True, padx=self.PADX, pady=self.PADY) self.frame_messages = Frame(self.frame_changeling) # message frame self.text_messages = scrolledtext.ScrolledText(self.frame_messages, padx=self.PADX, pady=self.PADY, height=self.MSGHEIGHT) self.text_messages.pack(fill=BOTH, expand=True, padx=self.PADX, pady=self.PADY) self.text_messages.bind("<Key>", lambda e: "break") self.worker.logger.addHandler(GUILogHandler( self.text_messages)) # give tk loghandler to worker self.frame_config = Frame(self.frame_changeling) # config frame nb_config = ttk.Notebook( self.frame_config) # here is the tk-notebook for the modules nb_config.pack(padx=self.PADX, pady=self.PADY) frame_nb = ttk.Frame(nb_config) nb_config.add(frame_nb, text='General') frame_row = Frame(frame_nb) frame_row.pack(fill=BOTH, expand=True) Label(frame_row, text='Output directory:', anchor=E, width=self.BUTTONWIDTH).pack(side=LEFT, padx=self.PADX) self.tk_outdir = StringVar(frame_row, self.worker.storage.outdir) self.tk_outdir_entry = Entry(frame_row, textvariable=self.tk_outdir, width=self.BIGENTRYWIDTH) self.tk_outdir_entry.pack(side=LEFT) Button(frame_row, text='...', command=self.__output_dir__).pack(side=LEFT, padx=self.PADX, pady=self.PADY) frame_row = Frame(frame_nb) frame_row.pack(fill=BOTH, expand=True) Label(frame_row, text='Chrome path:', anchor=E, width=self.BUTTONWIDTH).pack(side=LEFT, padx=self.PADX, pady=self.PADY) self.tk_chrome = StringVar(frame_row, self.worker.chrome.path) self.tk_chrome_entry = Entry(frame_row, textvariable=self.tk_chrome, width=self.BIGENTRYWIDTH) self.tk_chrome_entry.pack(side=LEFT) Button(frame_row, text='...', command=self.__chrome__).pack(side=LEFT, padx=self.PADX) self.tk_logins = dict() # login credentials self.tk_login_entries = dict() for i in self.worker.MODULES: # notebook tabs for the module configuration if i['login'] != None: frame_nb = ttk.Frame(nb_config) nb_config.add(frame_nb, text=i['name']) self.tk_logins[i['name']], self.tk_login_entries[ i['name']] = self.__login_frame__( frame_nb, i['name'], self.worker.logins[i['name']]) frame_row = Frame(self.frame_config) frame_row.pack(side=LEFT, anchor=N) Button(frame_row, text="\u2912 Save configuration", width=self.BUTTONWIDTH, command=self.__save_config__).pack(side=LEFT, padx=self.PADX, pady=self.PADY) Button(frame_row, text="\u2913 Load configuration", width=self.BUTTONWIDTH, command=self.__load_config__).pack(side=LEFT, padx=self.PADX, pady=self.PADY) Label(self.frame_changeling, width=self.CHNGWIDTH).grid(row=1, column=0) Label(self.frame_changeling, height=self.CHNGHEIGHT).grid(row=0, column=1) frame_row = LabelFrame(self.root, text=' \u2191\u2193 ') frame_row.pack(fill=X, expand=True, padx=self.PADX, pady=self.PADY) self.button_toggle = Button(frame_row, command=self.__toggle_config__, width=self.BUTTONWIDTH) self.button_toggle.pack(side=LEFT, padx=self.PADX, pady=self.PADY) self.button_clear = Button(frame_row, text='\u2610 Clear messages', command=self.__clear_messages__, width=self.BUTTONWIDTH) self.button_clear.pack(side=LEFT, padx=self.PADX, pady=self.PADY) self.__enable_config__() frame_row = Frame(self.root) frame_row.pack(fill=X, expand=True) for i in ('README.md', 'README.txt', 'README.md.txt', 'README'): try: with open(self.worker.storage.rootdir + self.worker.storage.slash + i, 'r', encoding='utf-8') as f: self.about_help = f.read() Button(frame_row, text="\u2370 About / Help", width=self.BUTTONWIDTH, command=self.__help__).pack(side=LEFT, padx=self.PADX, pady=self.PADY) break except: continue self.quitbutton = Button(frame_row, text="\u2297 Quit", width=self.BUTTONWIDTH, command=self.__quit__) self.quitbutton.pack(side=RIGHT, padx=self.PADX, pady=self.PADY) def __set_icon__(self, master): 'Try to Somedo icon for the window' try: master.call( 'wm', 'iconphoto', master._w, PhotoImage( file='%s%ssomedo.png' % (self.worker.storage.icondir, self.worker.storage.slash))) except: pass def __quit__(self): 'Close the app' if messagebox.askyesno('Quit', 'Close this Application?'): self.__terminate__() def __close2quit__(self): 'Ask to quit on close windows by "X"' self.root.protocol("WM_DELETE_WINDOW", self.__quit__) def __close2stop__(self): 'Ask to stop job(s) on close windows by "X"' self.root.protocol("WM_DELETE_WINDOW", self.__stop__) def __close2kill__(self): 'Ask to kill Somedo immediatly on close windows by "X"' self.root.protocol("WM_DELETE_WINDOW", self.__kill__) def __login_frame__(self, frame, module, login): 'Create Tk Frame for login credentials' tk_login = dict() tk_login_entry = dict() for i in login: frame_row = Frame(frame) frame_row.pack(fill=BOTH, expand=True) Label(frame_row, text=i, anchor=E, padx=self.PADX, width=self.BUTTONWIDTH).pack(side=LEFT) tk_login[i] = StringVar(frame_row) if self.worker.logins[module] != None: tk_login[i].set(login[i]) tk_login_entry[i] = Entry(frame_row, textvariable=tk_login[i], show='*', width=self.BIGENTRYWIDTH) tk_login_entry[i].pack(side=LEFT) tk_hide = BooleanVar(frame_row, True) Checkbutton(frame_row, text='hide', variable=tk_hide, command=partial(self.__hide_entry__, tk_login_entry[i], tk_hide)).pack(side=LEFT) return tk_login, tk_login_entry def __hide_entry__(self, entry, check): 'Toggle hidden login credentials' if check.get(): entry.config(show='*') else: entry.config(show='') def __job_dialog__(self, job, row): 'Open window to edit a job' self.__disable_jobbuttons__() self.job_dialog_root.title(job['module']) frame_row = LabelFrame(self.job_dialog_root, text=' \u229a Target(s) ') frame_row.pack(fill=BOTH, expand=True, padx=self.PADX, pady=self.PADY) tk_job = { 'module': job['module'], 'target': StringVar(frame_row, job['target']) } # tk variables for the job configuration tk_target_entry = Entry(frame_row, textvariable=tk_job['target'], width=self.TARGETWIDTH) tk_target_entry.pack(side=LEFT, padx=self.PADX, pady=self.PADY) tk_job['options'] = dict() # tk variables for the options if job['options'] != None: frame_grid = LabelFrame(self.job_dialog_root, text=' \u2714 Options ') frame_grid.pack(fill=BOTH, expand=True, padx=self.PADX, pady=self.PADY) for i in self.worker.options[job['module']]: definition = self.worker.options[job['module']][i] value = job['options'][i] Label(frame_grid, text=definition['name']).grid( row=definition['row'], column=definition['column'] * 2, sticky=E, pady=self.PADY) if isinstance(value, bool): # checkbutton for boolean tk_job['options'][i] = BooleanVar(frame_grid, value) Checkbutton(frame_grid, variable=tk_job['options'][i]).grid( row=definition['row'], column=definition['column'] * 2 + 1, sticky=W) width = 0 elif isinstance(value, int): # integer tk_job['options'][i] = IntVar(frame_grid, value) width = self.INTWIDTH elif isinstance(value, str): # string tk_job['options'][i] = StringVar(frame_grid, value) width = self.BUTTONWIDTH if width != 0: Entry(frame_grid, textvariable=tk_job['options'][i], width=width).grid(row=definition['row'], column=definition['column'] * 2 + 1, sticky=W, padx=self.OPTPADX) if job['login'] != None: frame_login = LabelFrame(self.job_dialog_root, text=' \u2737 Login') frame_login.pack(fill=BOTH, expand=True, padx=self.PADX, pady=self.PADY) tk_job['login'], dummy = self.__login_frame__( frame_login, job['module'], job['login']) frame_row = Frame(self.job_dialog_root) frame_row.pack(fill=BOTH, expand=True) if row == len(self.jobs): Button(frame_row, text="Add job", width=self.BUTTONWIDTH, command=partial(self.__add_job__, tk_job)).pack(side=LEFT, padx=self.PADX, pady=self.PADY) else: Button(frame_row, text="Update job", width=self.BUTTONWIDTH, command=partial(self.__update_job__, tk_job, row)).pack(side=LEFT, padx=self.PADX, pady=self.PADY) Button(frame_row, text="Remove job", width=self.BUTTONWIDTH, command=partial(self.__remove_job__, row)).pack(side=LEFT, padx=self.PADX, pady=self.PADY) Button(frame_row, text="Quit, do nothing", width=self.BUTTONWIDTH, command=self.__quit_job_dialog__).pack(side=RIGHT, padx=self.PADX, pady=self.PADY) def __quit_job_dialog__(self): 'Close the job configuration window' self.job_dialog_root.destroy() self.__enable_jobbuttons__() def __get_login__(self, module): 'Get login credentials for a module from root window' if self.worker.logins[module] == None: return None return { i: self.tk_logins[module][i].get() for i in self.worker.logins[module] } def __new_job__(self, module): 'Create new job to add to job list' if len(self.jobs ) == self.JOBLISTLENGTH - 1: # check if free space in job list return job = self.worker.new_job(module) if self.worker.logins[module] != None: job['login'] = self.__get_login__(module) self.job_dialog_root = Tk() self.__job_dialog__(job, len(self.jobs)) def __job_edit__(self, row): 'Edit or remove jobin job list' if row >= len(self.jobs): return self.job_dialog_root = Tk() self.__job_dialog__(self.jobs[row], row) def __tk2job__(self, tk_job): 'Get Tk values for a job' job = { 'module': tk_job['module'], 'target': tk_job['target'].get(), 'options': {i: tk_job['options'][i].get() for i in tk_job['options']} } try: job['login'] = { i: tk_job['login'][i].get() for i in tk_job['login'] } except: job['login'] = None return job def __add_job__(self, tk_job): 'Add job to list' if tk_job['target'].get() == '': # no target, no job return self.job_dialog_root.destroy() self.__enable_jobbuttons__() self.jobs.append(self.__tk2job__(tk_job)) self.__update_joblist__() def __update_job__(self, tk_job, row): 'Update job in list' if tk_job['target'].get() == '': # no target, no job return self.job_dialog_root.destroy() self.__enable_jobbuttons__() self.jobs[row] = self.__tk2job__(tk_job) self.__update_joblist__() def __purge_jobs__(self): 'Purge job list' if len(self.jobs) < 1: return if messagebox.askyesno('Purge job list', 'Are you sure to remove all jobs fromk list?'): self.jobs = [] self.__update_joblist__() def __job_text__(self, row): 'Generate string for one job button' if row >= len(self.jobs): return '' return '%s - %s' % (self.jobs[row]['module'], self.jobs[row]['target']) def __update_joblist__(self): 'Update the list of jobs' for i in range(self.JOBLISTLENGTH): self.tk_jobbuttons[i].set(self.__job_text__(i)) def __job_up__(self, row): 'Move job up in list' if row > 0: self.jobs[row], self.jobs[row - 1] = self.jobs[row - 1], self.jobs[row] self.__update_joblist__() def __job_down__(self, row): 'Move job down in list' if row < (len(self.jobs) - 1): self.jobs[row], self.jobs[row + 1] = self.jobs[row + 1], self.jobs[row] self.__update_joblist__() def __remove_job__(self, row): 'Remove job from list' if messagebox.askyesno('Remove job', 'Are you sure?'): self.job_dialog_root.destroy() self.__enable_jobbuttons__() self.jobs.pop(row) self.__update_joblist__() def __output_dir__(self): 'Set path to output directory.' path = filedialog.askdirectory(initialdir="~/", title='Destination directory') if path != (): self.tk_outdir_entry.delete(0, END) self.tk_outdir_entry.insert(0, path) self.worker.storage.outdir = path def __chrome__(self): 'Set path to chrome.' path = filedialog.askopenfilename(title='chrome', filetypes=[('All files', '*.*')]) if path != () and path != '': self.tk_chrome_entry.delete(0, END) self.tk_chrome_entry.insert(0, path) self.worker.chrome.path = path def __save_config__(self): 'Save configuration to file.' path = filedialog.asksaveasfilename(title='Configuration file', filetypes=[ ('Somedo configuration files', '*.smdc') ]) if path[-5:] != '.smdc': path += '.smdc' try: self.worker.storage.json_dump( { 'Output': self.tk_outdir.get(), 'Chrome': self.tk_chrome.get(), 'Modules': { i: self.__get_login__(i) for i in self.worker.modulenames if self.worker.logins[i] != None } }, path) except: messagebox.showerror('Error', 'Could not save configuration file') def __load_config__(self): 'Load configuration from file.' path = filedialog.askopenfilename(title='Configuration file', filetypes=[ ('Somedo configuration files', '*.smdc'), ('All files', '*.*') ]) if path != () and path != '': try: config = self.worker.storage.json_load(path) except: messagebox.showerror('Error', 'Could not load configuration file') return try: self.tk_outdir_entry.delete(0, END) self.tk_outdir_entry.insert(0, config['Output']) self.worker.storage.outdir = config['Output'] self.tk_chrome_entry.delete(0, END) self.tk_chrome_entry.insert(0, config['Chrome']) self.worker.chrome.path = config['Chrome'] for i in config['Modules']: for j in config['Modules'][i]: self.tk_login_entries[i][j].delete(0, END) self.tk_login_entries[i][j].insert( 0, config['Modules'][i][j]) except: messagebox.showerror('Error', 'Could not decode configuration file') def __help__(self): 'Open window to show About / Help' help_win = Tk() help_win.wm_title('About / Help') text = scrolledtext.ScrolledText(help_win, padx=self.PADX, pady=self.PADY, width=self.TARGETWIDTH) text.bind("<Key>", lambda e: "break") text.insert(END, self.about_help) text.pack() Button(help_win, text="Close", width=self.BUTTONWIDTH, command=help_win.destroy).pack(padx=self.PADX, pady=self.PADY, side=RIGHT) def __disable_jobbuttons__(self): 'Disable the job related buttons except Abort' for i in range(self.JOBLISTLENGTH): self.jobbuttons[i].config(state=DISABLED) self.upbuttons[i].config(state=DISABLED) self.downbuttons[i].config(state=DISABLED) self.startbutton.config(state=DISABLED) self.purgebutton.config(state=DISABLED) for i in self.worker.modulenames: self.modulebuttons[i].config(state=DISABLED) def __enable_jobbuttons__(self): 'Enable the job related buttons except Abort' for i in range(self.JOBLISTLENGTH): self.jobbuttons[i].config(state='normal') self.upbuttons[i].config(state='normal') self.downbuttons[i].config(state='normal') self.startbutton.config(state='normal') self.purgebutton.config(state='normal') for i in self.worker.modulenames: self.modulebuttons[i].config(state='normal') def __disable_quitbutton__(self): 'Disable the button Quit and enable Abort' self.quitbutton.config(state=DISABLED) self.stopbutton.config(state='normal') def __enable_quitbutton__(self): 'Enable the button Quit and disable Abort' self.quitbutton.config(state='normal') self.stopbutton.config(state=DISABLED) def __enable_config__(self): 'Enable configuration frame' self.config_visible = True self.frame_changeling.config(text=' \u2737 Configuration ') self.frame_config.grid(row=0, column=0, sticky=W + E + N + S) self.frame_messages.grid_remove() self.button_toggle.config(text='\u2609 Show Messages') self.button_clear.config(state=DISABLED) def __enable_messages__(self): 'Enable configuration frame' self.config_visible = False self.frame_changeling.config(text=' \u2709 Messages') self.frame_config.grid_remove() self.frame_messages.grid(row=0, column=0, sticky=W + E + N + S) self.button_toggle.config(text='\u2609 Show Configuration') self.button_clear.config(state='normal') def __toggle_config__(self): 'Toggle Configuration / Messages' if self.config_visible: self.__enable_messages__() else: self.__enable_config__() def __clear_messages__(self): 'Clear message / logging output fild' if messagebox.askyesno('Somedo', 'Clear messages?'): self.text_messages.delete('1.0', END) def __write_message__(self, msg): 'Write to message fiels' self.text_messages.insert(END, msg + '\n') self.text_messages.yview(END) def __start__(self): 'Start the jobs' if len(self.jobs) < 1: messagebox.showerror('Error', 'Nothing to do') return try: # check if task is running if self.thread_worker.isAlive(): return except: pass self.__disable_jobbuttons__() self.__disable_quitbutton__() self.__enable_messages__() self.__close2stop__() self.stop = Event() # to stop working thread self.stop_set = False self.running_job = 0 self.thread_worker = Thread(target=self.__worker__) self.thread_worker.start() # start work self.thread_showjob = Thread(target=self.__showjob__) self.thread_showjob.start() # start work def __stop__(self): 'Stop running job but give results based on already optained data' if self.stop_set: self.__kill__() return try: # check if task is running if self.thread_worker.isAlive() and messagebox.askyesno( 'Somedo', 'Stop running task?'): self.stop.set() except: pass self.running_job = -1 self.stop_set = True def __kill__(self): 'Kill Somedo immediatly' if messagebox.askyesno( 'Somedo', 'Kill Somedo as fast as possible?\n\nAlready downloaded data mightbe lost!' ): self.__terminate__() def __worker__(self): 'Execute jobs' if len(self.jobs) > 1: self.__write_message__('\n--- Executing jobs ---\n') while self.running_job < len(self.jobs): self.worker.execute_job(self.jobs[self.running_job], jobnumber=self.running_job + 1, stop=self.stop) self.running_job += 1 else: self.__write_message__('\n--- Executing job ---\n') self.worker.execute_job(self.jobs[self.running_job], stop=self.stop) self.__write_message__('\n--- Done ---\n') self.__close2quit__() self.__enable_jobbuttons__() self.__enable_quitbutton__() def __showjob__(self): 'Show what the worker is doing' while self.thread_worker.isAlive(): running = self.running_job self.jobbuttons[running].config(fg=self.colour_bg) self.jobbuttons[running].config(bg=self.colour_fg) sleep(0.75) self.jobbuttons[running].config(fg=self.colour_fg) self.jobbuttons[running].config(bg=self.colour_bg) sleep(0.75) def __terminate__(self): 'Terminate GUI' try: if self.thread_worker.isAlive(): raise SystemExit('Worker thread was still running') except: pass try: if self.thread_showjob.isAlive(): raise SystemExit('Thread that indicates job was still running') except: pass self.root.quit()