J'essaie de suivre vos recommandations et me plonge dans les nombreuses documentations, cette fois je tente de travailler avec Grid pour de vrai, ainsi que des cadres.
Voici mon premier essai, avec trois questions.
1) Est-ce que cette façon de faire est correcte du point de vue grid ?
2) Comment faire pour que les contenus soient automatiquement redimensionnés lors du redimensionnement de la fenêtre ? Vous notrez que j'ai tenté autant que possible de définir mes contenus avec des variables afin qu'ils soient dynamiques, et j'ai aussi essayé d'utiliser au mieux les boucles et fonctions (par exemple pour la création des rectangles)
3) J'ai un problème sur ma boucle à la ligne 47. Python me répond : "_tkinter.TclError: image "img_unite" doesn't exist".
Pourtant elle est bien déclarée plus haut à la ligne 39.
Qu'est-ce qui ne va pas ?
Un grand merci (et pour votre patience aussi).
Il s'agit d'un programme pour faire travailler mes élèves avec des cubes représentant les unités, dizaines, centaines, milliers.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from tkinter import *
from random import *
#Création de la fenêtre
fenetre = Tk()
larg=fenetre.winfo_screenwidth()-100
haut=fenetre.winfo_screenheight()-100
fenetre.title("Numération")
fenetre.geometry(f"{larg}x{haut}+0+0")
#Cré"ation des cadres
zone_haut=Frame(fenetre, height=100, relief="sunken").grid(row=0,column=0)
zone_gauche=Frame(fenetre, width=100, height=haut-100, relief="raised").grid(row=1,column=0)
zone_princ=Canvas(fenetre, width=larg-100, height=haut-100, bg="white")
zone_princ.grid(row=1,column=1)
#Variables
larg_canvas=larg-100
haut_canvas=haut-100
marge=50
larg_colonne=(larg_canvas-(5*marge))/4
posx=posy=marge
#Création des zones milliers, centaines, dizaines, unités
for i in ("milliers","centaines","dizaines","unités"):
i=zone_princ.create_rectangle(posx,posy,larg_colonne+posx,haut_canvas-marge, tags=f"{i}")
posx=posx+marge+larg_colonne
#Déclaration des images
img_unite=PhotoImage(file="images/unite.png")
img_dizaine=PhotoImage(file="images/dizaine.png")
img_centaine=PhotoImage(file="images/centaine.png")
img_millier=PhotoImage(file="images/millier.png")
#Boucle de création d'une image
def cree(objet,img):
objet=create_image(randint(0,800),randint(0,800), image=img)
#Appuis sur les touches
fenetre.bind_all('<u>', lambda event: cree("unite","img_unite"))
fenetre.bind_all('<d>', lambda event: cree("dizaine","img_dizaine"))
fenetre.bind_all('<c>', lambda event: cree("dizaine","img_dizaine"))
fenetre.bind_all('<m>', lambda event: cree("dizaine","img_dizaine"))
fenetre.mainloop()
ta boucle des rectangles n'est pas géniale, le i c'est ta variable d'itération de la boucle et tu la redéfinis par l'id du rectangle mais tu perds cette information; soit tu retires le i=, soit si tu veux conserver la référence des rectangles, il faut les mémoriser dans un tableau.
#Création des zones milliers, centaines, dizaines, unités
mes_rect=[]
for i in ("milliers","centaines","dizaines","unités"):
mes_rect.append(zone_princ.create_rectangle(posx,posy,larg_colonne+posx,haut_canvas-marge, tags=f"{i}"))
posx=posx+marge+larg_colonne
ta boucle des rectangles n'est pas géniale, le i c'est ta variable d'itération de la boucle et tu la redéfinis par l'id du rectangle mais tu perds cette information; soit tu retires le i=, soit si tu veux conserver la référence des rectangles, il faut les mémoriser dans un tableau.
#Création des zones milliers, centaines, dizaines, unités
mes_rect=[]
for i in ("milliers","centaines","dizaines","unités"):
mes_rect.append(zone_princ.create_rectangle(posx,posy,larg_colonne+posx,haut_canvas-marge, tags=f"{i}"))
posx=posx+marge+larg_colonne
mes_rect[0] sera celui pour i="milliers", etc
Merci Umfred pour cette réponse. Je ne l'avais pas vue hier, je ne sais pas pourquoi je ne suis pas notifié par mail en cas de nouveaux messages dans le fil.
Ta remarque vient de me faire comprendre quelque chose de logique mais que j'avais pas encore "construit" dans ma représentation du codage.
En effet quand on crée un rectangle on dit rectangle1=canvas.create_rectangle .....
Jusque-là dans ma tête, rectangle1 venait donner un nom au rectangle. En fait c'est l'inverse, et c'est logique car c'est la syntaxe du signe =
Quand j'écrivais i= c'est parce que je voulais que la variable d'itération, autrement dit "milliers", "centaines" ... soit "injectée" comme "nom du rectangle".
En fait c'était l'inverse.
Bref, j'ai supprimé le i et j'identifie mes rectangles via un tag généré d'après le i , ce qui me permet juste après de stocker leurs coordonnées dans des listes (que j'ai appris récemment à utiliser. Je viens de comprendre d'ailleurs qu'il va me falloir me mettre aux tableaux désormais) :
#Création des zones milliers, centaines, dizaines, unités
for i in ("milliers","centaines","dizaines","unites"):
i=zone_princ.create_rectangle(posx,posy,larg_colonne+posx,haut_canvas-marge, fill="#d9dce6", tags=f"{i}")
posx=posx+marge+larg_colonne
#Création de listes des coordonnées des coins des rectangles
liste_millier=zone_princ.coords("milliers")
liste_centaine=zone_princ.coords("centaines")
liste_dizaine=zone_princ.coords("dizaines")
liste_unite=zone_princ.coords("unites")
Merci en tout cas pour vos réponses patientes face à mes questions de débutant qui doit faire un peu n'importe quoi parfois (mais je suis motivé).
Pour la petite histoire je suis prof des écoles et je me suis dit tout récemment "et si je créais les logiciels pédagogiques qui nous manquent". Jusqu-là je ne savais coder qu'en Scratch (langage pédagogique pour l'apprentissage du codage en primaire et collège). J'ai donc tenté l'aventure du python à partir de docs glanés sur internet et des essais & erreurs.
Comme les autres (Multiples, Barres et Ensembles) le code source est, et restera, sous licence libre.
Et voici le code actuel de ce matin :
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from tkinter import *
from random import *
import time
#Création de la fenêtre
fenetre = Tk()
larg=fenetre.winfo_screenwidth()-100
haut=fenetre.winfo_screenheight()-100
fenetre.title("Numération")
fenetre.geometry(f"{larg}x{haut}+0+0")
#Cré"ation des cadres
zone_haut=Frame(fenetre, height=100, relief="sunken").grid(row=0,column=0)
zone_gauche=Frame(fenetre, width=100, height=haut-100, relief="raised").grid(row=1,column=0)
zone_princ=Canvas(fenetre, width=larg-100, height=haut-100, bg="#d6e2e4")
zone_princ.grid(row=1,column=1)
#Variables
larg_canvas=larg-100
haut_canvas=haut-100
marge=50
larg_colonne=(larg_canvas-(5*marge))/4
posx=posy=marge
tagobjet=0
nombre=0
milliers=centaines=dizaines=unites=0
m=c=d=u=1
#Création des zones milliers, centaines, dizaines, unités
for i in ("milliers","centaines","dizaines","unites"):
i=zone_princ.create_rectangle(posx,posy,larg_colonne+posx,haut_canvas-marge, fill="#d9dce6", tags=f"{i}")
posx=posx+marge+larg_colonne
#Création de listes des coordonnées des coins des rectangles
liste_millier=zone_princ.coords("milliers")
liste_centaine=zone_princ.coords("centaines")
liste_dizaine=zone_princ.coords("dizaines")
liste_unite=zone_princ.coords("unites")
objets_milliers=[]
objets_centaines=[]
objets_dizaines=[]
objets_unites=[]
#Déclaration des images
img_unite=PhotoImage(file="images/unite.png")
img_unite_select=PhotoImage(file="images/unite_select.png")
img_dizaine=PhotoImage(file="images/dizaine.png")
img_dizaine_select=PhotoImage(file="images/dizaine_select.png")
img_centaine=PhotoImage(file="images/centaine.png")
img_centaine_select=PhotoImage(file="images/centaine_select.png")
img_millier=PhotoImage(file="images/millier.png")
img_millier_select=PhotoImage(file="images/millier_select.png")
#Pour afficher en console le nombre total et le nombre de chaque puissance de 10
def console():
print(nombre)
print(f'{milliers} milliers')
print(f'{centaines} centaines')
print(f'{dizaines} dizaines')
print(f'{unites} unités')
#Boucle de création d'une image
def cree(objet,img,valeur):
global nombre, milliers, centaines, dizaines, unites,u,d,c,m
#On incrémente les compteur
nombre=nombre+valeur
#On récupère les coordonnées de la colonne correspondante et on incrémente le nombre de chaque
if objet=="millier":
liste_coords=liste_millier
milliers=milliers+1
if objet=="centaine":
liste_coords=liste_centaine
centaines=centaines+1
if objet=="dizaine":
liste_coords=liste_dizaine
dizaines=dizaines+1
if objet=="unite":
liste_coords=liste_unite
unites=unites+1
#affichages en console
maj()
#On attribue des positions maxi
x1=int(liste_coords[0]+60)
x2=int(liste_coords[2]-60)
y1=int(liste_coords[1]+60)
y2=int(liste_coords[3]-60)
#On crée l'objet à une position aléatoire à l'intérieur des positions maxi et on le taggue avec le type d'objet
if objet=="millier":
objets_milliers.append(zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img, tags=objet))
m=1
if objet=="centaine":
objets_centaines.append(zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img, tags=objet))
c=1
if objet=="dizaine":
objets_dizaines.append(zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img, tags=objet))
d=1
if objet=="unite":
objets_unites.append(zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img, tags=objet))
u=1
def maj():
compteur.configure(text=nombre)
compteur_milliers.configure(text=milliers)
compteur_centaines.configure(text=centaines)
compteur_dizaines.configure(text=dizaines)
compteur_unites.configure(text=unites)
def suppr(objet):
global nombre, milliers, centaines, dizaines, unites, u,d,c,m
if objet=="millier":
milliers = milliers - 1
m = m - 1
nombre = nombre - 1000
zone_princ.delete(objets_milliers[-1])
objets_milliers.pop()
if objet=="centaine":
centaines = centaines - 1
nombre = nombre - 100
c = c - 1
zone_princ.delete(objets_centaines[-1])
objets_centaines.pop()
if objet=="dizaine":
dizaines = dizaines - 1
nombre = nombre - 10
d = d - 1
zone_princ.delete(objets_dizaines[-1])
objets_dizaines.pop()
if objet=="unite":
unites= unites - 1
nombre = nombre - 1
u = u - 1
zone_princ.delete(objets_unites[-1])
objets_unites.pop()
nombre=1000*milliers+100*centaines+10*dizaines+unites
maj()
def reset(objet):
global nombre, milliers, centaines, dizaines, unites
if objet=="millier":
zone_princ.delete("millier")
milliers=0
if objet=="centaine":
zone_princ.delete("centaine")
centaines=0
if objet=="dizaine":
zone_princ.delete("dizaine")
dizaines=0
if objet=="unite":
zone_princ.delete("unite")
unites=0
nombre=1000*milliers+100*centaines+10*dizaines+unites
maj()
def casse(objet,compteur):
global milliers,centaines,dizaines,unites, objets_milliers, nombre, m,c,d,u
if compteur>0:
compteur=compteur-1
if objet=="millier":
milliers=milliers-1
m=m-1
nombre=nombre-1000
zone_princ.delete(objets_milliers[-1])
objets_milliers.pop()
for i in range(10):
cree("centaine", img_centaine,100)
if objet=="centaine":
centaines=centaines-1
nombre=nombre-100
c=c-1
zone_princ.delete(objets_centaines[-1])
objets_centaines.pop()
for i in range(10):
cree("dizaine", img_dizaine,10)
if objet=="dizaine":
dizaines=dizaines-1
nombre=nombre-10
d=d-1
zone_princ.delete(objets_dizaines[-1])
objets_dizaines.pop()
for i in range(10):
cree("unite", img_unite,1)
def groupe(objet,compteur):
global milliers,centaines,dizaines,unites, objets_milliers, nombre,u,d,c,m, dx, dy
dx=-10
dy=0
if compteur>=10:
compteur=compteur+10
if objet=="unite" and u-1==10:
unites=unites-10
u=u-10
nombre=nombre-10
for i in range (10):
zone_princ.delete(objets_unites[-1])
objets_unites.pop()
cree("dizaine", img_dizaine,10)
if objet=="dizaine" and d-1==10:
dizaines=dizaines-10
d=d-10
nombre=nombre-100
for i in range(10):
zone_princ.delete(objets_dizaines[-1])
objets_dizaines.pop()
cree("centaine", img_centaine,100)
if objet=="centaine" and c-1==10:
centaines=centaines-10
c=c-10
nombre=nombre-1000
for i in range(10):
zone_princ.delete(objets_centaines[-1])
objets_centaines.pop()
cree("millier", img_millier,1000)
def select(objet):
global m,c,d,u,unites,dizaines,centaines,milliers
if objet=="unite" and unites>0 and u<=len(objets_unites):
zone_princ.itemconfig((objets_unites[-u]),image=img_unite_select)
u=u+1
if objet=="dizaine" and dizaines>0 and d<=len(objets_dizaines):
zone_princ.itemconfig((objets_dizaines[-d]),image=img_dizaine_select)
d=d+1
if objet=="centaine" and centaines>0 and c<=len(objets_centaines):
zone_princ.itemconfig((objets_centaines[-c]),image=img_centaine_select)
c=c+1
if objet=="millier" and milliers>0 and m<=len(objets_centaines):
zone_princ.itemconfig((objets_milliers[-m]),image=img_millier_select)
m=m+1
def deselect(objet):
global m,c,d,u,unites,dizaines,centaines,milliers
if objet=="unite" and unites>0 and u>0:
zone_princ.itemconfig((objets_unites[1-u]),image=img_unite)
u=u-1
if objet=="dizaine" and dizaines>0 and d>0:
zone_princ.itemconfig((objets_dizaines[1-d]),image=img_dizaine)
d=d-1
if objet=="centaine" and centaines>0 and c>0:
zone_princ.itemconfig((objets_centaines[1-c]),image=img_centaine)
c=c-1
if objet=="millier" and milliers>0 and m>0:
zone_princ.itemconfig((objets_milliers[1-m]),image=img_millier)
m=m-1
#Compteurs
compteur=Label(zone_gauche, text=nombre)
compteur.grid(row=0,column=0)
compteur_milliers=Label(zone_haut, text=milliers)
compteur_centaines=Label(zone_haut, text=centaines)
compteur_dizaines=Label(zone_haut, text=dizaines)
compteur_unites=Label(zone_haut, text=unites)
compteur_milliers.place(x = (liste_millier[0]+liste_millier[2])/2+100, y = 80, anchor=CENTER)
compteur_centaines.place(x = (liste_centaine[0]+liste_centaine[2])/2+100, y = 80, anchor=CENTER)
compteur_dizaines.place(x = (liste_dizaine[0]+liste_dizaine[2])/2+100, y = 80, anchor=CENTER)
compteur_unites.place(x = (liste_unite[0]+liste_unite[2])/2+100, y = 80, anchor=CENTER)
#Boutons
reset_millier=Button(zone_haut, text="reset milliers", command=lambda:reset("millier"))
reset_centaine=Button(zone_haut, text="reset centaines", command=lambda:reset("centaine"))
reset_dizaine=Button(zone_haut, text="reset dizaines", command=lambda:reset("dizaine"))
reset_unite=Button(zone_haut, text="reset unités", command=lambda:reset("unite"))
reset_millier.place(x = (liste_millier[0]+liste_millier[2])/2+100, y = 50, anchor=CENTER)
reset_centaine.place(x = (liste_centaine[0]+liste_centaine[2])/2+100, y = 50, anchor=CENTER)
reset_dizaine.place(x = (liste_dizaine[0]+liste_dizaine[2])/2+100, y = 50, anchor=CENTER)
reset_unite.place(x = (liste_unite[0]+liste_unite[2])/2+100, y = 50, anchor=CENTER)
casse_millier=Button(zone_princ, text=">>>", command=lambda:casse("millier",milliers))
casse_centaine=Button(zone_princ, text=">>>", command=lambda:casse("centaine",centaines))
casse_dizaine=Button(zone_princ, text=">>>", command=lambda:casse("dizaine",dizaines))
groupe_unites=Button(zone_princ, text="<<<", command=lambda:groupe("unite",unites))
groupe_dizaines=Button(zone_princ, text="<<<", command=lambda:groupe("dizaine",dizaines))
groupe_centaines=Button(zone_princ, text="<<<", command=lambda:groupe("centaine",centaines))
casse_millier.place(x=(liste_millier[0]+liste_millier[2])/2,y=haut_canvas-marge/2, anchor=CENTER)
casse_centaine.place(x=(liste_centaine[0]+liste_centaine[2])/2,y=haut_canvas-marge/2, anchor=W)
casse_dizaine.place(x=(liste_dizaine[0]+liste_dizaine[2])/2,y=haut_canvas-marge/2, anchor=W)
groupe_centaines.place(x=(liste_centaine[0]+liste_centaine[2])/2,y=haut_canvas-marge/2, anchor=E)
groupe_dizaines.place(x=(liste_dizaine[0]+liste_dizaine[2])/2,y=haut_canvas-marge/2, anchor=E)
groupe_unites.place(x=(liste_unite[0]+liste_unite[2])/2,y=haut_canvas-marge/2, anchor=CENTER)
select_unite=Button(zone_princ, text="✅", command=lambda: select("unite"),background="red", fg="white")
select_dizaine=Button(zone_princ, text="✅", command=lambda: select("dizaine"),background="red")
select_centaine=Button(zone_princ, text="✅", command=lambda: select("centaine"),background="red")
deselect_unite=Button(zone_princ, text="✅", command=lambda: deselect("unite"),background="#fefb00")
deselect_dizaine=Button(zone_princ, text="✅", command=lambda: deselect("dizaine"),background="#fefb00")
deselect_centaine=Button(zone_princ, text="✅", command=lambda: deselect("centaine"),background="#fefb00")
add_unite=Button(zone_princ, text="+", command= lambda: cree("unite",img_unite, 1))
add_dizaine=Button(zone_princ, text="+", command=lambda: cree("dizaine", img_dizaine, 10))
add_centaine=Button(zone_princ, text="+", command=lambda: cree("centaine", img_centaine, 100))
add_millier=Button(zone_princ, text="+", command=lambda: cree("millier",img_millier, 1000))
suppr_unite=Button(zone_princ, text="-", command= lambda: suppr("unite"))
suppr_dizaine=Button(zone_princ, text="-", command=lambda: suppr("dizaine"))
suppr_centaine=Button(zone_princ, text="-", command=lambda: suppr("centaine"))
suppr_millier=Button(zone_princ, text="-", command=lambda: suppr("millier"))
l=30
select_unite.place(x=(liste_unite[0]+liste_unite[2])/2,y=marge/2, anchor=W, width=l)
select_dizaine.place(x=(liste_dizaine[0]+liste_dizaine[2])/2,y=marge/2, anchor=W, width=l)
select_centaine.place(x=(liste_centaine[0]+liste_centaine[2])/2,y=marge/2, anchor=W, width=l)
deselect_unite.place(x=((liste_unite[0]+liste_unite[2])/2)+l,y=marge/2, anchor=W, width=l)
deselect_dizaine.place(x=((liste_dizaine[0]+liste_dizaine[2])/2)+l,y=marge/2, anchor=W, width=l)
deselect_centaine.place(x=((liste_centaine[0]+liste_centaine[2])/2)+l,y=marge/2, anchor=W, width=l)
add_unite.place(x=(liste_unite[0]+liste_unite[2])/2,y=marge/2, anchor=E, width=l)
add_dizaine.place(x=(liste_dizaine[0]+liste_dizaine[2])/2,y=marge/2, anchor=E, width=l)
add_centaine.place(x=(liste_centaine[0]+liste_centaine[2])/2,y=marge/2, anchor=E, width=l)
add_millier.place(x=(liste_millier[0]+liste_millier[2])/2,y=marge/2, anchor=E, width=l)
suppr_unite.place(x=((liste_unite[0]+liste_unite[2])/2)-l,y=marge/2, anchor=E, width=l)
suppr_dizaine.place(x=((liste_dizaine[0]+liste_dizaine[2])/2)-l,y=marge/2, anchor=E, width=l)
suppr_centaine.place(x=((liste_centaine[0]+liste_centaine[2])/2)-l,y=marge/2, anchor=E, width=l)
suppr_millier.place(x=(liste_millier[0]+liste_millier[2])/2,y=marge/2, anchor=W, width=l)
#Corbeille
img_corbeille=PhotoImage(file="images/corbeille.png")
corbeille=Label(zone_gauche, image=img_corbeille)
corbeille.grid(row=1,column=0)
#Appuis sur les touches
fenetre.bind_all('<u>', lambda event: cree("unite",img_unite, 1))
fenetre.bind_all('<d>', lambda event: cree("dizaine",img_dizaine, 10))
fenetre.bind_all('<c>', lambda event: cree("centaine",img_centaine, 100))
fenetre.bind_all('<m>', lambda event: cree("millier",img_millier, 1000))
fenetre.bind_all('<g>', lambda event: select("millier"))
fenetre.bind_all('<h>', lambda event: select("centaine"))
fenetre.bind_all('<j>', lambda event: select("dizaine"))
fenetre.bind_all('<k>', lambda event: select("unite"))
fenetre.mainloop()
Créer des objets avec une fonction
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Python c'est bon, mangez-en.