def __init__(self, window): """ Constructeur par défaut de l'interface du menu multijoueur Prend comme argument la fenêtre Ce menu n'est absolument pas encore travaillé et n'est là qu'en prévision """ GUI.__init__(self, window, True) # Création des boutons local = tk.Button(window, textvariable=msgs.LOCAL, font=("Plantagenet Cherokee", 30), anchor="center", width=15, borderwidth=4, bg=utils.BUTTON_BACKGROUND, relief="raise", command=lambda: utils.showMessageDialog( msgs.SOON, msgs.FUTURE_FEATURE)) online = tk.Button(window, textvariable=msgs.ONLINE, font=("Plantagenet Cherokee", 30), anchor="center", width=15, borderwidth=4, bg=utils.BUTTON_BACKGROUND, relief="raise", command=lambda: utils.showMessageDialog( msgs.SOON, msgs.FUTURE_FEATURE)) backBtn = tk.Button(window, textvariable=msgs.BACK, font=("Plantagenet Cherokee", 30), anchor="center", width=15, borderwidth=4, bg=utils.BUTTON_BACKGROUND, relief="raise", command=lambda: back(window)) # Affichage et positionnement des boutons sur l'interface local.place(relx=.025, rely=.37, relwidth=.42, relheight=.11) online.place(relx=.025, rely=.49, relwidth=.42, relheight=.11) backBtn.place(relx=.74, rely=.88, relwidth=.26, relheight=.12) # Ajout des boutons comme enfants self.appendChild(local) self.appendChild(online) self.appendChild(backBtn)
def __init__(self, window: tk.Tk, gameBuilder: GameBuilder): """ Constructeur par défaut du sélecteur de voiture Prend comme argument la fenêtre et le constructeur de partie """ GUI.__init__(self, window) self.builder = gameBuilder # master représente un cadre dans lequel sera incorporé le sélecteur ainsi que les barres de défilement master = tk.Frame(window, width=window.winfo_screenwidth(), height=window.winfo_screenheight()) master.place(x=0, y=0, relwidth=1, relheight=1) self.appendChild(master) # Création des barres de défilement vscrollbar = tk.Scrollbar(master, orient=tk.VERTICAL) hscrollbar = tk.Scrollbar(master, orient=tk.HORIZONTAL) vscrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=tk.FALSE) hscrollbar.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.FALSE) self.appendChild(vscrollbar) self.appendChild(hscrollbar) # Afin de pouvoir déplacer la fenêtre, nécessité de passer par un canevas # x(y)scrollcommand : Contrôle la taille des barres de défilement # scrollregion : Définit la zone de défilement (pour des raisons obscrures, nécessité de définir cela de façon statique) canvas = tk.Canvas(master, xscrollcommand=hscrollbar.set, yscrollcommand=vscrollbar.set, width=window.winfo_screenwidth(), height=window.winfo_screenheight(), scrollregion="0 0 %s %s" % (window.winfo_screenwidth() + 54, window.winfo_screenheight() - 100)) # Création du cadre dans lequel seront déposés les composants frame = tk.Frame(canvas, width=window.winfo_screenwidth(), height=window.winfo_screenheight()) # Placement du cadre dans le canevas canvas.create_window(0, 0, window=frame, anchor=tk.NW) # Placement du canevas canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.FALSE) canvas.xview_moveto(0) canvas.yview_moveto(0) # Définition de l'action des barres de défilement (déplacer le canevas) vscrollbar.config(command=canvas.yview) hscrollbar.config(command=canvas.xview) for i in range(len(cars.CARS)): # Pour chaque voiture, affichae d'une ligne d'informations car = cars.CARS[i] # Chargement de l'image de miniature grâce au module PIL image = Image.open("images/thumbnails/" + car.thumbnail_file) # Redimensionnement de l'image en 100x100 avec anti-crénelage image = image.resize((100, 100), Image.ANTIALIAS) # Remplacement de l'image image.save("images/thumbnails/" + car.thumbnail_file, car.thumbnail_file[-3:]) # Conversion de l'image en Tkinter thumbnail = tk.PhotoImage(file="images/thumbnails/" + car.thumbnail_file) # Passage de l'image en Label et placement dans l'interface thumbnailLabel = tk.Label(frame, image=thumbnail) thumbnailLabel.image = thumbnail thumbnailLabel.grid(row=5 * i, column=0, rowspan=4) # Affichage du nom de la voiture label = tk.Label(frame, textvariable=car.name, font=("Plantagenet Cherokee", 30)) label.grid(row=5 * i, column=1, rowspan=4) # Affichage de la vitesse de la voiture speedLabel = tk.Label(frame, textvariable=msgs.MAX_SPEED.format( car.max_speed), font=("Plantagenet Cherokee", 16)) speedLabel.grid(row=5 * i, column=2) # Affichage de la capacité d'accélération de la voiture accelerateLabel = tk.Label(frame, textvariable=msgs.ACCELERATION.format( 60 * car.acceleration), font=("Plantagenet Cherokee", 16)) accelerateLabel.grid(row=5 * i + 1, column=2) # Affichage de la taille de la voiture sizeLabel = tk.Label(frame, textvariable=msgs.SIZE.format( car.width, car.height), font=("Plantagenet Cherokee", 16)) sizeLabel.grid(row=5 * i + 2, column=2) # Affichage de la maniabilité de la voiture (présenté comme unité arbitraire sans réellement en être une) maniabilityLabel = tk.Label(frame, textvariable=msgs.MANIABILITY.format( 2 * car.maniability), font=("Plantagenet Cherokee", 16)) maniabilityLabel.grid(row=5 * i + 3, column=2) # Affichage du bouton de sélection choose = tk.Button(frame, textvariable=msgs.CHOOSE, bg=utils.BUTTON_BACKGROUND, font=("Plantagenet Cherokee", 22)) choose.grid(row=5 * i, column=3, rowspan=4) # Si la voiture a déjà été choisie (pour modification), affichage d'un check à côté if self.builder.car == car: ok = tk.Label(frame, text="ü", font=("Wingdings", 42)) ok.grid(row=5 * i, column=4, rowspan=4) self.appendChild(ok) # Si ce n'est pas la dernière voiture, affichage d'une ligne grisée if i < len(cars.CARS) - 1: canvas = tk.Canvas(frame, width=window.winfo_screenwidth(), height=5, bg="lightgray") canvas.grid(row=5 * i + 4, columnspan=4) self.appendChild(canvas) # Inscription de l'écouteur pour le click du bouton de sélection self.registerChooseListener(window, choose, car) # Ajout de tous les composants comme enfants self.appendChild(frame) self.appendChild(thumbnailLabel) self.appendChild(label) self.appendChild(speedLabel) self.appendChild(accelerateLabel) self.appendChild(sizeLabel) self.appendChild(maniabilityLabel) self.appendChild(choose) # Ajout du bouton retour backBtn = tk.Button(frame, textvariable=msgs.BACK, bg=utils.BUTTON_BACKGROUND, font=("Plantagenet Cherokee", 30), anchor="center", width=20, borderwidth=10, relief="groove", command=lambda: back(window)) backBtn.grid(row=5 * (len(cars.CARS) + 1), columnspan=4, pady=100) self.appendChild(backBtn) # Configuration des poids (rapports de longueur) de chaque colonne frame.columnconfigure(0, weight=1) frame.columnconfigure(1, weight=2) frame.columnconfigure(2, weight=3) frame.columnconfigure(3, weight=2) frame.columnconfigure(4, weight=1) # Mise à jour de la zone de scroll lorsque le cadre est redimensionné # En apparence mystérieusement non fonctionnel # noinspection PyUnusedLocal def _configure_frame(eventf): size = (frame.winfo_reqwidth(), frame.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) frame.bind("<Configure>", _configure_frame)
def choose_map(): self.builder.map = map back(window)
def __init__(self, window: tk.Tk, gameBuilder: GameBuilder): """ Constructeur par défaut du sélecteur de carte Prend comme argument la fenêtre et le constructeur de partie """ GUI.__init__(self, window) self.builder = gameBuilder for i in range(len(maps.MAPS)): # Pour chaque carte, affiche une ligne d'informations et de sélection map = maps.MAPS[i] # Lecture de l'image de miniature grâce au module PIL image = Image.open("images/thumbnails/" + map.thumbnail) # Redimensionnement de l'image en 100x100 avec anti-crénelage image = image.resize((100, 100), Image.ANTIALIAS) # Remplacement de l'ancien fichier image.save("images/thumbnails/" + map.thumbnail, map.thumbnail[-3:]) # Conversion de l'image en image Tkinter thumbnail = tk.PhotoImage(file="images/thumbnails/" + map.thumbnail) # Placement de l'image dans un label et positionnement dans l'interface thumbnailLabel = tk.Label(window, image=thumbnail) thumbnailLabel.image = thumbnail thumbnailLabel.grid(row=i, column=0, rowspan=1) # Affichage du nom de la carte label = tk.Label(window, textvariable=map.name, font=("Plantagenet Cherokee", 30)) label.grid(row=i, column=1, rowspan=1) # Affichage de la taille (en pixels) de la carte sizeLabel = tk.Label(window, textvariable=msgs.SIZE.format( map.width, map.height), font=("Plantagenet Cherokee", 22)) sizeLabel.grid(row=i, column=2) # Affichage du bouton de sélection de la carte choose = tk.Button(window, textvariable=msgs.CHOOSE, bg=utils.BUTTON_BACKGROUND, font=("Plantagenet Cherokee", 22)) choose.grid(row=i, column=3, rowspan=1) # Si une carte était déjà sélectionné, affichage d'un check à côté if self.builder.map == map: ok = tk.Label(window, text="ü", font=("Wingdings", 42)) ok.grid(row=i, column=4, rowspan=1) self.appendChild(ok) # Inscription de l'écouteur pour le clic du bouton self.registerChooseListener(window, choose, map) # Ajout des enfants self.appendChild(thumbnailLabel) self.appendChild(label) self.appendChild(sizeLabel) self.appendChild(choose) # Configuration des poids des colonnes window.columnconfigure(0, weight=1) window.columnconfigure(1, weight=2) window.columnconfigure(2, weight=3) window.columnconfigure(3, weight=2) window.columnconfigure(4, weight=1) # Affichage du bouton retour backBtn = tk.Button(window, textvariable=msgs.BACK, font=("Plantagenet Cherokee", 30), bg=utils.BUTTON_BACKGROUND, anchor="center", width=20, borderwidth=10, relief="groove", command=lambda: back(window)) backBtn.grid(row=len(cars.CARS) * 2 + 1, column=0, columnspan=5, pady=100) self.appendChild(backBtn)
def choose_car(): self.builder.car = car back(window)
def __init__(self, window): """ Constructeur par défaut de l'interface du menu un joueur Prend comme argument la fenêtre """ GUI.__init__(self, window, True) # builder représente le constructeur de partie actuel (créé si inexistant) builder = GameBuilder.CURRENT_GAME_BUILDER if builder is None: builder = GameBuilder.CURRENT_GAME_BUILDER = GameBuilder( GameBuilder.SINGLE_PLAYER_MODE) # Création des boutons car = tk.Button(window, textvariable=msgs.CAR_CHOICE, font=("Plantagenet Cherokee", 30), anchor="center", width=15, borderwidth=4, bg=utils.BUTTON_BACKGROUND, relief="raise", command=lambda: CarChooser(window, builder)) chooseMap = tk.Button(window, textvariable=msgs.MAP_CHOICE, font=("Plantagenet Cherokee", 30), anchor="center", width=15, borderwidth=4, bg=utils.BUTTON_BACKGROUND, relief="raise", command=lambda: MapChooser(window, builder)) start = tk.Button(window, textvariable=msgs.START, font=("Plantagenet Cherokee", 30), anchor="center", width=15, borderwidth=4, bg=utils.BUTTON_BACKGROUND, relief="raise", state=tk.DISABLED if builder.car is None or builder.map is None else tk.NORMAL, command=lambda: builder.start(window)) backBtn = tk.Button(window, textvariable=msgs.BACK, font=("Plantagenet Cherokee", 30), anchor="center", width=15, borderwidth=4, bg=utils.BUTTON_BACKGROUND, relief="raise", command=lambda: back(window)) # Positionnement des boutons sur l'interface car.place(relx=.025, rely=.25, relwidth=.42, relheight=.11) chooseMap.place(relx=.025, rely=.37, relwidth=.42, relheight=.11) start.place(relx=.025, rely=.49, relwidth=.42, relheight=.11) backBtn.place(relx=.74, rely=.88, relwidth=.26, relheight=.12) # Ajout des boutons comme enfants self.appendChild(car) self.appendChild(chooseMap) self.appendChild(start) self.appendChild(backBtn)
def __init__(self, window : tk.Tk): """ Constructeur par défaut du menu de scores Prend comme argument la fenêtre et le constructeur de partie """ GUI.__init__(self, window) # Création du bouton retour backBtn = tk.Button(window, textvariable = msgs.BACK, font = ("Plantagenet Cherokee", 30), anchor = "center", width = 15, borderwidth = 4, bg = utils.BUTTON_BACKGROUND, relief = "groove", command = lambda : back(window)) backBtn.place(relx = .74, rely = .88, relwidth = .26, relheight = .12) self.appendChild(backBtn) # Détermination du nombre de colonnes (1 colonne pour la carte, 1 colonne pour le temps, 1 colonne pour la voiture, autant de colonnes qui il y a de tours au maximum columns = 3 for map in maps.MAPS: columns = max(columns, map.max_laps + 3) # Définition du poids de chaque colonne à 1 for i in range(columns): window.columnconfigure(i, weight = 1) # Définition et affichage des en-têtes total_time_label = tk.Label(window, textvariable = msgs.TOTAL_TIME, font = ("Plantagenet Cherokee", 18, "bold"), relief = "groove") total_time_label.grid(row = 0, column = 1, sticky = "nsew") self.appendChild(total_time_label) car_label = tk.Label(window, textvariable = msgs.CAR, font = ("Plantagenet Cherokee", 18, "bold"), relief = "groove") car_label.grid(row = 0, column = columns - 1, sticky = "nsew") self.appendChild(car_label) # Affichage des en-têtes des temps par tour for lap in range(0, columns - 3): lap_time_label = tk.Label(window, textvariable = msgs.LAP_TIME.format(lap + 1), font = ("Plantagenet Cherokee", 18, "bold"), relief = "groove") lap_time_label.grid(row = 0, column = lap + 2, sticky = "nsew") self.appendChild(lap_time_label) # Curseur donnant la ligne actuelle du tableau row_index = 1 for map_index in range(len(maps.MAPS)): # Pour chaque carte, récupérer la liste des scores triés par le temps effectués sur cette carte map = maps.MAPS[map_index] map_scores = list() for score in utils.SCORES: if score.map == map: map_scores.append(score) map_scores.sort() # Afficher le nom de la carte à gauche mapLabel = tk.Label(window, textvariable = map.name, font = ("Plantagenet Cherokee", 18, "bold"), relief = "groove") mapLabel.grid(row = row_index, column = 0, rowspan = max(1, len(map_scores)), sticky = "nsew") self.appendChild(mapLabel) for score in map_scores: # Pour chaque score, afficher le temps total et la voiture utilisée total_time_label = tk.Label(window, text = score.total_time, font = ("Plantagenet Cherokee", 18), relief = "groove") total_time_label.grid(row = row_index, column = 1, sticky = "nsew") self.appendChild(total_time_label) car_label = tk.Label(window, textvariable = score.car.name, font = ("Plantagenet Cherokee", 18), relief = "groove") car_label.grid(row = row_index, column = columns - 1, sticky = "nsew") self.appendChild(car_label) for lap in range(map.max_laps): # Pour chaque tour, afficher le temps effectué lap_time_label = tk.Label(window, text = score.laps_time[lap], font = ("Plantagenet Cherokee", 18), relief = "groove") lap_time_label.grid(row = row_index, column = lap + 2, sticky = "nsew") self.appendChild(lap_time_label) # Incrémenter le compteur de ligne row_index += 1
def __init__(self, window): """ Constructeur par défaut de l'interface de paramètres (Fond d'écran actif) Prend en paramètre la fenêtre """ GUI.__init__(self, window, True) # Définition des textes des boutons de (dés)activation de la musique et des effets sonores en fonction des paramètres actuels switchMusicMsg = (msgs.DISABLE_MUSIC if window.music_enabled else msgs.ENABLE_MUSIC).clone() switchSoundsMsg = (msgs.DISABLE_SOUNDS if window.sounds_enabled else msgs.ENABLE_SOUNDS).clone() # Création des boutons music = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = switchMusicMsg, font = ("Plantagenet Cherokee", 30), anchor = "center", width = 22, borderwidth = 4, relief = "raise") sounds = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = switchSoundsMsg, font = ("Plantagenet Cherokee", 30), anchor = "center", width = 22, borderwidth = 4, relief = "raise") changeLanguage = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = msgs.CHANGE_LANGUAGE, font = ("Plantagenet Cherokee", 30), anchor = "center", width = 22, borderwidth = 4, relief = "raise", command = msgs.switchLanguage) controls = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = msgs.CHANGE_CONTROLS, font = ("Plantagenet Cherokee", 30), anchor = "center", width = 22, borderwidth = 4, relief = "raise", command = lambda : Controls(window)) back = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = msgs.BACK, font = ("Plantagenet Cherokee", 30), anchor = "center", width = 15, borderwidth = 4, relief = "groove", command = lambda : guis.back(window)) # Affichage des boutons music.place(relx = .025, rely = .25, relwidth = .42, relheight = .11) sounds.place(relx = .025, rely = .37, relwidth = .42, relheight = .11) changeLanguage.place(relx = .025, rely = .49, relwidth = .42, relheight = .11) controls.place(relx = .025, rely = .61, relwidth = .42, relheight = .11) back.place(relx = .74, rely = .88, relwidth = .26, relheight = .12) def switchMusicState(): """ Change l'état d'activation de la musique La musique est lancée dans le sous-module audio """ if window.music_enabled: switchMusicMsg.switch(msgs.ENABLE_MUSIC) else: switchMusicMsg.switch(msgs.DISABLE_MUSIC) window.music_enabled ^= True saveSettings() def switchSoundsState(): """ Change l'état d'activation des effets sonores """ if window.sounds_enabled: switchSoundsMsg.switch(msgs.ENABLE_SOUNDS) else: switchSoundsMsg.switch(msgs.DISABLE_SOUNDS) window.sounds_enabled ^= True saveSettings() # Affectation des évenements de clics music.config(command = switchMusicState) sounds.config(command = switchSoundsState) # Ajout des enfants self.appendChild(music) self.appendChild(sounds) self.appendChild(changeLanguage) self.appendChild(controls) self.appendChild(back)
def __init__(self, window): """ Constructeur par défaut de l'interface de changements des contrôles (fond d'écran actif) Prend en paramètre la fenêtre """ super().__init__(window, True) # Création des labels et des boutons forwardLabel = tk.Label(window, textvariable = msgs.FORWARD, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") forwardText = tk.StringVar(window, utils.CONTROLS["forward"].replace("_", " ")) forward = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = forwardText, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") leftLabel = tk.Label(window, textvariable = msgs.TURN_LEFT, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") leftText = tk.StringVar(window, utils.CONTROLS["left"].replace("_", " ")) left = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = leftText, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") backwardLabel = tk.Label(window, textvariable = msgs.BACKWARD, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") backwardText = tk.StringVar(window, utils.CONTROLS["backward"].replace("_", " ")) backward = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = backwardText, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") rightLabel = tk.Label(window, textvariable = msgs.TURN_RIGHT, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") rightText = tk.StringVar(window, utils.CONTROLS["right"].replace("_", " ")) right = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = rightText, font = ("Plantagenet Cherokee", 21), width = 10, relief ="raise") # Création du bouton retour back = tk.Button(window, bg = utils.BUTTON_BACKGROUND, textvariable = msgs.BACK, font = ("Plantagenet Cherokee", 30), anchor = "center", width = 15, borderwidth = 4, relief ="groove", command = lambda : guis.back(window)) # Affichage des boutons sur l'interface forwardLabel.place(relx = .025, rely = .30, relwidth = 0.275, relheight = .07) forward.place(relx = .35, rely = .30, relwidth = .2, relheight = .07) leftLabel.place(relx = .025, rely = .38, relwidth = .275, relheight = .07) left.place(relx = .35, rely = .38, relwidth = .2, relheight = .07) backwardLabel.place(relx = .025, rely = .46, relwidth = .275, relheight = .07) backward.place(relx = .35, rely = .46, relwidth = .2, relheight = .07) rightLabel.place(relx = .025, rely = .54, relwidth = .275, relheight = .07) right.place(relx = .35, rely = .54, relwidth = .2, relheight = .07) back.place(relx = .74, rely = .88, relwidth = .26, relheight = .12) def requestNewKey(index, buttonText, label): """ Affiche une boîte de dialogue demandant la nouvelle touche à affecter à l'action Le paramètre index représente le numéro de l'action Le paramètre buttonText représente l'affichage du bouton, soit le nom de la touche Le paramètre label représente le nom de l'action (localisé/traduit) """ # Création d'une boîte de dialogue popup = tk.Toplevel(window) # Ajout du texte dans la boîte label = tk.Label(popup, textvariable = msgs.WHAT_KEY_FOR.format(label.get().lower()), font = ("Plantagenet Cherokee", 30)) label.grid(row = 0, column = 0, padx = 10, pady = 10) # Définition de la géométrie de la boîte ainsi que son positionnement sur l'écran (centré) width = label.winfo_reqwidth() + 20 height = label.winfo_height() + 80 screenWidth = popup.winfo_screenwidth() screenHeight = popup.winfo_screenheight() popup.geometry(str(width) + "x" + str(height) + "+" + str(int((screenWidth - width) / 2)) + "+" + str(int((screenHeight - height) / 2) - 40)) # Variable expliquée plus tard sound_started = tk.BooleanVar(False) def catch_key_event(event): """ Méthode invoquée lorsqu'une touche est pressée Paramètre : informations par rapport à l'évennemment "appuyer sur une touche" """ # event.keycode est le numéro de la touche dans la table ASCII key = event.keycode # La touche 27 est la touche ÉCHAP qui annule alors la modification de contrôle if key == 27: popup.destroy() return # On vérifie si la touche n'est pas déjà assignée et si ce n'est pas la touche F11 (utile pour le plein écran) if event.keysym.upper() in utils.CONTROLS.values() or event.keysym.upper() == "F11": # Si on est sous windows, le son d'erreur est alors déclenché # La variable sound_started permet alors de savoir si ce son a déjà été déclenché if utils.isWindows(): import winsound, threading if not sound_started.get(): def start_sound(): sound_started.set(True) winsound.PlaySound("*", winsound.SND_ALIAS) sound_started.set(False) threading.Thread(target = start_sound).start() return # Changement du texte du bouton avec le nouveau contrôle buttonText.set(event.keysym.upper().replace("_", " ")) # Affectation du nouveau contrôle utils.CONTROLS[index] = event.keysym.upper() # Fermeture de la boîte de dialogue popup.destroy() # Écriture des paramètres saveSettings() # Appelle la fonction catch_key_event lors de l'appui de n'importe quelle touche de clavier popup.bind("<KeyPress>", catch_key_event) # Force la mise en avant de la boîte de dialogue et la laisse en avant-plan popup.focus_force() popup.wm_attributes("-topmost", 1) popup.grab_set() forward.bind("<ButtonRelease-1>", lambda event : requestNewKey("forward", forwardText, msgs.FORWARD)) left.bind("<ButtonRelease-1>", lambda event : requestNewKey("left", leftText, msgs.TURN_LEFT)) backward.bind("<ButtonRelease-1>", lambda event : requestNewKey("backward", backwardText, msgs.BACKWARD)) right.bind("<ButtonRelease-1>", lambda event : requestNewKey("right", rightText, msgs.TURN_RIGHT)) window.columnconfigure(0, weight = 3) window.columnconfigure(1, weight = 2) # Ajout des enfants self.appendChild(forwardLabel) self.appendChild(forward) self.appendChild(leftLabel) self.appendChild(left) self.appendChild(backwardLabel) self.appendChild(backward) self.appendChild(rightLabel) self.appendChild(right) self.appendChild(back)