Problème de sauvegarde.
Résolu/FerméLapwace Messages postés 5 Date d'inscription jeudi 19 janvier 2023 Statut Membre Dernière intervention 19 janvier 2023 - 19 janv. 2023 à 23:22
- Problème de sauvegarde.
- Logiciel de sauvegarde - Guide
- Sauvegarde android - Guide
- Sauvegarde facile - Télécharger - Sauvegarde
- Sauvegarde time machine - Guide
- Sauvegarde automatique windows 10 - Guide
3 réponses
Salut, cela vient du fait que tu affectes autant de fois le tag de ton rectangle que tu n'en crées.
.
Donc vérifier, que le tag n'existe pas avant de créer ton rectangle, sinon, modifier sa couleur.
De plus quel intérêt d'enregistrer une liste de points ? Enregistre seulement s'il y a une couleur.
.
import tkinter as tk import csv WIDTH = 100 HEIGHT = 100 root = tk.Tk() root.title("App Pixel") # root.state('zoomed') # fonctionne pas sur Linux def draw_pixel(): x = int(x_coordinate.get()) y = int(y_coordinate.get()) pixel_color = color.get() rects = canvas.find_withtag(f"pixel_{x}_{y}") if rects: canvas.itemconfig(rects[0], fill=pixel_color) else: canvas.create_rectangle( x, y, x, y, fill=pixel_color, width=0, tags=(f"pixel_{x}_{y}") ) def save_to_csv(): with open("canvas_content.csv", "w", newline="") as f: writer = csv.writer(f) for x in range(WIDTH): for y in range(HEIGHT): color = canvas.itemcget(canvas.find_withtag(f"pixel_{x}_{y}"), "fill") if color: writer.writerow([x, y, color]) def load_from_csv(): with open("canvas_content.csv", "r") as f: reader = csv.reader(f) for row in reader: x, y, color = row canvas.create_rectangle(int(x), int(y), int(x), int(y), fill=color, width=0) x_coordinate = tk.StringVar() y_coordinate = tk.StringVar() color = tk.StringVar() frame = tk.Frame(root) frame.pack(expand=True, fill='both') frame_Menu = tk.Frame(frame) frame_Menu.grid(row=0, column=0, sticky="N") frame_Canvas = tk.Frame(frame) frame_Canvas.grid(row=0, column=2, sticky="W") x_entry = tk.Entry(frame_Menu, textvariable=x_coordinate) x_entry.grid(row=0, column=0, pady=1, sticky="N") x_entry.config(bd=1, relief="solid") y_entry = tk.Entry(frame_Menu, textvariable=y_coordinate) y_entry.grid(row=1, column=0, sticky="N") y_entry.config(bd=1, relief="solid") color_entry = tk.Entry(frame_Menu, textvariable=color) color_entry.grid(row=2, column=0, pady=1, sticky="N") color_entry.config(bd=1, relief="solid") draw_button = tk.Button(frame_Menu, text="Dessiner", command=draw_pixel) draw_button.grid(row=3, column=0, sticky="N") save_button = tk.Button(frame_Menu, text="Sauvegarder", command=save_to_csv) save_button.grid(row=4, column=0, sticky="N") load_button = tk.Button(frame_Menu, text="Charger", command=load_from_csv) load_button.grid(row=5, column=0, sticky="N") close_button = tk.Button(frame_Menu, text="Fermer", command=root.destroy) close_button.grid(row=6, column=0, sticky="N") canvas = tk.Canvas(frame_Canvas, width=WIDTH, height=HEIGHT, bg='yellow') canvas.grid(row=0, column=0, rowspan=1, sticky="NSEW") canvas.config(bd=1, relief="solid") root.mainloop()
La meilleure solution serait de ne pas utiliser de tag qui sert principalement à faire des groupes d'items, et d'user de la méthode find_enclosed du canvas.
Préfère aussi utiliser les constantes tkinter plutôt que des strings.
import tkinter as tk import csv WIDTH = 100 HEIGHT = 100 CSV_NAME = "canvas_content.csv" root = tk.Tk() root.title("App Pixel") # root.state('zoomed') # fonctionne pas sur Linux def draw_pixel(): pixel_color = color.get() try: assert pixel_color x = int(x_coordinate.get()) y = int(y_coordinate.get()) assert WIDTH > x >= 0 assert HEIGHT > y >= 0 except (ValueError, AssertionError): return rects = canvas.find_enclosed(x - 1, y - 1, x + 1, y + 1) if rects: canvas.itemconfig(rects[0], fill=pixel_color) else: canvas.create_rectangle(x, y, x, y, fill=pixel_color, width=0) def save_to_csv(): pixels = canvas.find_all() if pixels: with open(CSV_NAME, "w", newline="") as f: writer = csv.writer(f) for pixel in pixels: row = canvas.coords(pixel)[:2] row.append(canvas.itemcget(pixel, "fill")) writer.writerow(row) def load_from_csv(): with open(CSV_NAME, "r") as f: reader = csv.reader(f) for row in reader: x, y = (float(v) for v in row[0:2]) color = row[2] rects = canvas.find_enclosed(x - 1, y - 1, x + 1, y + 1) if rects: canvas.itemconfig(rects[0], fill=color) else: canvas.create_rectangle(x, y, x, y, fill=color, width=0) x_coordinate = tk.StringVar() y_coordinate = tk.StringVar() color = tk.StringVar() frame = tk.Frame(root) frame.pack(expand=True, fill=tk.BOTH) frame_Menu = tk.Frame(frame) frame_Menu.grid(row=0, column=0, sticky=tk.N) frame_Canvas = tk.Frame(frame) frame_Canvas.grid(row=0, column=2, sticky=tk.W) x_entry = tk.Entry(frame_Menu, textvariable=x_coordinate) x_entry.grid(row=0, column=0, pady=1, sticky=tk.N) x_entry.config(bd=1, relief=tk.SOLID) y_entry = tk.Entry(frame_Menu, textvariable=y_coordinate) y_entry.grid(row=1, column=0, sticky=tk.N) y_entry.config(bd=1, relief=tk.SOLID) color_entry = tk.Entry(frame_Menu, textvariable=color) color_entry.grid(row=2, column=0, pady=1, sticky=tk.N) color_entry.config(bd=1, relief=tk.SOLID) draw_button = tk.Button(frame_Menu, text="Dessiner", command=draw_pixel) draw_button.grid(row=3, column=0, sticky=tk.N) save_button = tk.Button(frame_Menu, text="Sauvegarder", command=save_to_csv) save_button.grid(row=4, column=0, sticky=tk.N) load_button = tk.Button(frame_Menu, text="Charger", command=load_from_csv) load_button.grid(row=5, column=0, sticky=tk.N) close_button = tk.Button(frame_Menu, text="Fermer", command=root.destroy) close_button.grid(row=6, column=0, sticky=tk.N) canvas = tk.Canvas( frame_Canvas, width=WIDTH, height=HEIGHT, bg='white', bd=1, relief=tk.SOLID ) canvas.grid(row=0, column=0, rowspan=1, sticky=tk.NSEW) root.mainloop()
Tu pourrais aussi utiliser des IntVar plutôt que des StringVar pour les coordonnées des Entry, mais il faudrait pour cela utiliser la méthode d'autorisation de saisie.
19 janv. 2023 à 21:18
Je vais probablement modifier le code pour utiliser la méthode find_enclosed qui a l'air plus efficace.
Pour les entrées en IntVar, ce sera un bot Discord qui les fera, donc elles seront toujours des entiers ou le bot refusera la commande. J'ai pensé que c'était plus simple de faire comme je le connaissais déjà, ça me fait moins de choses à rechercher sur le moment. Cependant, je prends note de cette méthode pour mon apprentissage.
En ce qui concerne les constantes tkinter, je les ignorais également, merci pour le conseil. Pouvez-vous m'expliquer pourquoi il est préférable de les utiliser par rapport à des chaînes de caractères ?
19 janv. 2023 à 22:36
Il est préférable d'utiliser les constantes d'un modules plutôt que la valeur de ces constantes, pour la simple raison qu'il peut prendre au développeur/mainteneur de ce module de changer la valeur des constantes pour x raison.
En utilisant les constantes on ne sera pas exposé à des bugs de nos programmes, bon, tkinter, ça n'a pas trop bougé et ne bougera sans doute jamais, mais ça reste tout de même une bonne habitude à adopter.
19 janv. 2023 à 23:22
Ok je vois , merci pour ses précisions.
19 janv. 2023 à 14:00
Pour le deuxième problème j'ai réussi à comprendre mon erreur en rajoutant le tag au create_rectangle ligne 28.
canvas.create_rectangle(int(x), int(y), int(x), int(y), fill=color,width=0,tags=(f"pixel_{x}_{y}"))
mais je n'arrive toujours pas à trouver mon erreur pour le premier problème.
19 janv. 2023 à 20:45
Merci beaucoup, d'accord donc si je comprend bien mon erreur c'est un peu comme si je superposais deux pixels et que ça sélectionnait tout le temps le premier qui n'avait plus de couleur.
19 janv. 2023 à 22:31
Il suffit de tester pour comprendre ce qu'il se passe ^^
Là, on comprend pourquoi tu avais ce souci.
On peut mettre n'importe quel type d'objet en tags, donc tkinter accepte sans broncher ce que retourne find_withtag (un tuple des identifiants items ayant ce tag, 'r' ici), on pourrait tout de même reprocher qu'il ne jette pas une erreur au cas où on demande la valeur de l'option d'un item inexistant.