Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

erreur 'UnboundLocalError' incompréhensible

2 réponses
Avatar
Lulu
Bonjour,

Je cherche à afficher une nouvelle fenetre depuis mon application et je
voudrais qu'elle utilise une autre fonte que ma fenetre principale :

mon code (ceci n'est pas un ECM) :
import tkinker as tk
from tkinter import font
...
# fonction appelée par le clic sur le bouton "Dessiner le spectre"
def callback()
ze_info_window = tk.Toplevel(height=200, width=120)
ze_info_window_font = font.Font(family='Courier', size='9'
label = tk.label( ze_info_window, text = "test", font=ze_info_wondow_font)

mais si ma nouvelle fenetre s'affiche bien (sans afficher 'test') mon
application plante avec :
Exception in TKinter callback
Traceback (most recent caall last):
File "/usr/lib/pyrhon3.6/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File 'spectres_tk.py" line 68, in callback
ze_info_window_font = font.Font(family='Courier', size='9')
UnboundLocalError: local variable 'font' referenced before assignment

J'ai parcouru le web à la recherche d'une solution, j'ai compris qu'il
doit s'agir d'un problème de local/global, mais aucune piste pour
résoudre le problème.

Tout ce que je veux, c'est ouvrir une nouvelle fenêtre à partir de la
fenêtre principale quand on clique sur le bouton qui appelle la fonction
callback() en changeant la fonte pour cette nouvelle fenêtre.

Je précise que si je ne cherche pas à ouvrir cette nouvelle fenêtre, mon
application fonctionne très bien.

Merci de vos avis.

2 réponses

Avatar
Nicolas
Bonjour,
Le 19/03/2020 à 00:33, Lulu a écrit :
Bonjour,
Je cherche à afficher une nouvelle fenetre depuis mon application et je
voudrais qu'elle utilise une autre fonte que ma fenetre principale :
mon code (ceci n'est pas un ECM) :
import tkinker as tk
from tkinter import font
...
# fonction appelée par le clic sur le bouton "Dessiner le spectre"
def callback()
ze_info_window = tk.Toplevel(height 0, width0)
ze_info_window_font = font.Font(family='Courier', size='9'
label = tk.label( ze_info_window, text = "test", font=ze_info_wondow_font)
mais si ma nouvelle fenetre s'affiche bien (sans afficher 'test') mon
application plante avec :
Exception in TKinter callback
Traceback (most recent caall last):
File "/usr/lib/pyrhon3.6/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File 'spectres_tk.py" line 68, in callback
ze_info_window_font = font.Font(family='Courier', size='9')
UnboundLocalError: local variable 'font' referenced before assignment
J'ai parcouru le web à la recherche d'une solution, j'ai compris qu'il
doit s'agir d'un problème de local/global, mais aucune piste pour
résoudre le problème.
Tout ce que je veux, c'est ouvrir une nouvelle fenêtre à partir de la
fenêtre principale quand on clique sur le bouton qui appelle la fonction
callback() en changeant la fonte pour cette nouvelle fenêtre.
Je précise que si je ne cherche pas à ouvrir cette nouvelle fenêtre, mon
application fonctionne très bien.
Merci de vos avis.

Le code de de la fonction "callback" est
complet ?
Je ne connais pas tKinter mais il est possible que la police de
caractères doive être chargée lors du lancement de l'application pour
qu'elle soit toujours accessible.
Dans le code fourni, la police de caractères n'existe que dans la
fonction callback.
Nicolas
Avatar
Lulu
Le 19-03-2020, Nicolas a écrit :
Le 19/03/2020 à 00:33, Lulu a écrit :
Je cherche à afficher une nouvelle fenetre depuis mon application et
je voudrais qu'elle utilise une autre fonte que ma fenetre principale
:
mon code (ceci n'est pas un ECM) :
import tkinker as tk
from tkinter import font
...
# fonction appelée par le clic sur le bouton "Dessiner le spectre"
def callback()
ze_info_window = tk.Toplevel(height 0, width0)
ze_info_window_font = font.Font(family='Courier', size='9'
label = tk.label( ze_info_window, text = "test", font=ze_info_wondow_font)
mais si ma nouvelle fenetre s'affiche bien (sans afficher 'test') mon
application plante avec :
Exception in TKinter callback
Traceback (most recent caall last):
File "/usr/lib/pyrhon3.6/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File 'spectres_tk.py" line 68, in callback
ze_info_window_font = font.Font(family='Courier', size='9')
UnboundLocalError: local variable 'font' referenced before assignment
J'ai parcouru le web à la recherche d'une solution, j'ai compris qu'il
doit s'agir d'un problème de local/global, mais aucune piste pour
résoudre le problème.
Tout ce que je veux, c'est ouvrir une nouvelle fenêtre à partir de la
fenêtre principale quand on clique sur le bouton qui appelle la fonction
callback() en changeant la fonte pour cette nouvelle fenêtre.
Je précise que si je ne cherche pas à ouvrir cette nouvelle fenêtre, mon
application fonctionne très bien.

Le code de de la fonction "callback" est
complet ?

Oh non, loin de là !
Je mets ton mon code à la fin du message.
Je ne connais pas tKinter mais il est possible que la police de
caractères doive être chargée lors du lancement de l'application pour
qu'elle soit toujours accessible.
Dans le code fourni, la police de caractères n'existe que dans la
fonction callback.

J'ai résolu mon problème quand je me suis rendu compte (dans une partie
du code écrite il y a plusieurs semaines) que j'utilisais le mot 'font'
pour sélectionner la fonte pour écrire sur mon image :
font = ImageFont.truetype(CONST_FONTE, CONST_FONTE_TAILLE)
dès que j'ai remplacé par :
font_image = ImageFont.truetype(CONST_FONTE, CONST_FONTE_TAILLE)
tout est rentré dans l'ordre.
Mon code (testé uniquement sous linux) :
8<-----------8<---------8<----------8<----------8<----------8<----------8<
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Auteur : , Lycée Jules Siegfried, Le Havre
# Creative Commons : https://creativecommons.org/licenses/by-nc-sa/2.0/fr/
# Attribution :: Pas d'utilisation commerciale :: Partage dans les mêmes conditions
CONST_FONTE = 'courbd.ttf'
CONST_FONTE_TAILLE = 14
import sys
from datetime import datetime
#from tkinter import *
import tkinter as tk
from tkinter import font
from tkinter import messagebox
# sous windows :
# - ouvrir une "Commande MS-DOS" en tant qu'administrateur
# - se placer dans le répertoire programs<répertoire_d'installation_de_python>
# - taper la commande : py -m pip install Pillow
from PIL import Image, ImageDraw, ImageFont
# cette fonction détermine la couleur RGB d'une longueur d'onde WL
def color_of_ray( WL ):
rouge = vert = bleu = int( 0 )
if WL >80 and WL < 420:
amplification = 0.3 + 0.7 * ( WL - 380) / 40
rouge = int( amplification * 255 * ( 440 - WL ) / 60 )
vert = int( 0 )
bleu = int( amplification * 255 )
elif WL >B0 and WL < 440:
rouge = int( 255 * ( 440 - WL ) / 60 )
vert = int( 0 )
bleu = int( 255 )
elif WL >= 440 and WL < 490:
rouge = int( 0 )
vert = int( 255 * ( WL - 440 ) / 50 )
bleu = int( 255 )
elif WL >= 490 and WL < 510:
rouge = int( 0 )
vert = int( 255 )
bleu = int( 255 * ( 510 - WL ) / 20 )
elif WL >= 510 and WL < 580:
rouge = int( 255 * ( WL - 510 ) / 70 )
vert = int( 255 )
bleu = int( 0 )
elif WL >= 580 and WL < 645:
rouge = int( 255 )
vert = int( 255 * ( 645 - WL ) / 65 )
bleu = int( 0 )
elif WL >= 645 and WL < 700:
rouge = int( 255 )
vert = bleu = int( 0 )
elif WL >= 700 and WL < 800:
amplification = 0.3 + 0.7 * ( 800 - WL) / 100
rouge = int( amplification * 255 )
vert = bleu = int( 0 )
return (rouge, vert, bleu)
# fonction appelée par le clic sur le bouton "Dessiner le spectre"
def dessiner_le_spectre():
# création d'une fenêtre d'info
ze_info_window = tk.Toplevel(fenetre, , width&0)
ze_info_window.configure(background='#000')
ze_info_window.geometry("%dx%d%+d%+d" % (400, 260, 10, 10))
ze_info_window.title('info')
ze_font_info = font.Font(family='Helvetica', size='12', weight='bold')
ze_bg = "#000"
ze_fg = "#f00"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = "Paramètres :", font=ze_font_info, anchor='w')
label.grid(row=0, column=0, sticky = 'ew')
while True :
x = WL_start_saisie.get()
try :
WL_start = int(x)
break
except ValueError :
WL_start_saisie.set("380")
WL_start = 380
pass
while True :
x = WL_end_saisie.get()
try :
WL_end = int(x)
break
except ValueError :
WL_end_saisie.set("800")
WL_end = 800
pass
if WL_start > WL_end: swap = WL_start ; WL_start = WL_end ; WL_end = swap
if WL_start > 800: WL_start = 380
if WL_end < 380: WL_end = 800
# on se limite évidemment au spectre visible
if WL_start < 380: WL_start = 380
if WL_end > 800: WL_end = 800
# Si un plaisantin a saisi des valeurs telles que WL_start = WL_end
if int( WL_start ) == int( WL_end ):
WL_start = 380
WL_end = 800
# fin traitement saisie WL_start et WL_end
WL_start_saisie.set(WL_start)
WL_end_saisie.set(WL_end)
WL_range = WL_end - WL_start
ze_font_info = font.Font(family='Helvetica', size='12', weight='normal')
ze_text = " --> " + str(WL_start) + " nm à " + str(WL_end) + " nm"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid( row = 1, column = 0, sticky = 'ew')
ze_text = " --> range : " + str(WL_range) + " nm"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid( row = 2, column = 0, sticky ='ew')
while True :
x = nb_pixels_largeur_saisie.get()
try :
nb_pixels_largeur = int(x)
break
except ValueError :
nb_pixels_largeur_saisie.set("1260")
nb_pixels_largeur = 1260
pass
while True :
x = nb_pixels_hauteur_saisie.get()
try :
nb_pixels_hauteur = int(x)
break
except ValueError :
nb_pixels_hauteur_saisie.set("160")
nb_pixels_hauteur = 160
pass
s = nb_pixels_largeur * nb_pixels_hauteur
# WL_resolution est le nombre de nanomètre que représente un pixel
WL_resolution = ( WL_range ) / ( nb_pixels_largeur )
ze_text = " --> taille de l'image : " + str(nb_pixels_largeur) + " px × " + str(nb_pixels_hauteur) + " px = " + str(s) + " px² "
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid( row = 3, column = 0, sticky = 'ew')
ze_text = " --> résolution : {0:.2e}".format(WL_resolution) + " nm/pixel"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid( row = 4, column = 0, sticky = 'ew')
# une fois connue la largeur du spectre en pixels, création de deux listes
# contenant la valeur en nanomètres du début du pixel et de la fin du pixel
WL_list_start = []
WL_list_end = []
for i in range(nb_pixels_largeur):
WL_list_start.append( WL_start + i * WL_resolution )
WL_list_end.append( WL_start + ( i + 1 ) * WL_resolution )
# test de l'argument n°5 : le type de spectre, 1, 2 ou 3
choix_spectre = choix_spectre_value.get()
if choix_spectre == "1":
grad_color = ( 0, 0, 0 )
ze_text = " --> spectre continu"
elif choix_spectre == "2":
grad_color = ( 255, 255, 255 )
ze_text = " --> spectre d'émission"
elif choix_spectre == "3":
grad_color = ( 0, 0, 0 )
ze_text = " --> spectre d'absorption"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid( row = 5, column = 0, sticky = 'ew')
# test de l'argument n°6 : oui ou non, imprimer la range en nm ?
imprime_nanometres = imprime_nanometres_value.get()
if imprime_nanometres =='n':
choix_imprime_nanometres = False
ze_text = " --> pas d'impression des nanomètres"
else:
choix_imprime_nanometres = True
ze_text = " --> impression des nanomètres"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid(row = 6, column = 0, sticky = 'ew')
# on n'a pas choisi le spectre continu : test des autres arguments.
if choix_spectre != "1":
liste_elements = []
if var_Hydrogene.get() == "1" :
liste_elements.append("H")
if var_Helium.get() == "1" :
liste_elements.append("He")
if var_Lithium.get() == "1" :
liste_elements.append("Li")
if var_Sodium.get() == "1" :
liste_elements.append("Na")
if var_Magnesium.get() == "1" :
liste_elements.append("Mg")
if var_Argon.get() == "1" :
liste_elements.append("Ar")
if var_Calcium.get() == "1" :
liste_elements.append("Ca")
if var_Titane.get() == "1" :
liste_elements.append("Ti")
if var_Manganese.get() == "1" :
liste_elements.append("Mn")
if var_Fer.get() == "1" :
liste_elements.append("Fe")
if var_Hydrargyrum.get() == "1" :
liste_elements.append("Hg")
if ( len(liste_elements) == 0) :
ze_font_info = font.Font(family='Helvetica', size='12', weight='bold')
ze_text = " --> AUCUN ÉLÉMENT SÉLECTIONNÉ !!"
else :
ze_text = " --> liste des éléments : " + str( liste_elements )
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid(row = 7, column = 0, sticky = 'ew')
imprime_elements = imprime_elements_value.get()
if imprime_elements == 'n':
choix_imprime_elements = False
ze_text = " --> pas d'impression du nom des éléments"
else:
choix_imprime_elements = True
ze_text = " --> impression du nom des éléments"
ze_font_info = font.Font(family='Helvetica', size='12', weight='normal')
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid(row = 8, column = 0, sticky = 'ew')
# Établissement de la liste des raies à tracer
# raies trouvées sur
# https://media4.obspm.fr/public/ressources_lu/pages_tp-spectre-soleil/identification.html
liste_de_toutes_les_raies=[]
nom_element = ""
for ze_element in liste_elements:
if ze_element == "H":
nom_element = nom_element + "Hydrogène "
liste_raies = [ 388.9, 397, 410.2, 434.1, 486.1, 656.3 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "He":
nom_element = nom_element + "Hélium "
liste_raies = [ 447, 468.5, 471.5, 492, 501.5, 587.5, 668 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Li":
nom_element = nom_element + "Lithium "
liste_raies = [ 496, 549, 610, 671 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Na":
nom_element = nom_element + "Sodium "
liste_raies = [ 568.8, 589, 589.6, 615.4 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Mg":
nom_element = nom_element + "Magnésium "
liste_raies = [ 516.7, 517.3, 518.4 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Ar":
nom_element = nom_element + "Argon "
liste_raies = [ 452, 472, 562, 605, 644, 670 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Ca":
nom_element = nom_element + "Calcium "
liste_raies = [ 393.3, 396.9, 425, 433, 447, 588, 589, 614, 618, 646, 648, 674, 717, 735 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Ti":
nom_element = nom_element + "Titane "
liste_raies = [ 466.8, 469.1, 498.2 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Mn":
nom_element = nom_element + "Manganèse "
liste_raies = [ 402.1, 403.1, 403.6 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Fe":
nom_element = nom_element + "Fer "
liste_raies = [ 389.9, 404.6, 423.4, 425.1, 426, 427.2, 438.3, 452.9, 459.3, 489.1, 491.9, 495.7, 501.2, 508, 527, 532.8, 536.7, 536.9, 543, 543.4, 544.7, 545.6, 561.6 ]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
elif ze_element == "Hg":
nom_element = nom_element + "Hydrargyrum "
liste_raies = [ 404.7, 435.8, 546.1, 577, 579.1]
for raie in liste_raies:
if raie >= WL_start - 1 and raie <= WL_end + 1 :
liste_de_toutes_les_raies.append(raie)
if ( len(liste_elements) == 0 ) :
choix_imprime_elements = True
nom_element = "C'est pas très malin de demander un spectre d'"
if choix_spectre == "2" :
nom_element = nom_element + "émission"
else :
nom_element = nom_element + "absorption"
nom_element = nom_element + " sans sélectionner d'élément !"
# tri de la liste de toutes les raies par ordre croissant
x = liste_de_toutes_les_raies.sort()
#creation en mémoire de l'image du spectre
try:
spectre_image = Image.new( "RGB", ( nb_pixels_largeur, nb_pixels_hauteur) )
except:
ze_font_info = font.Font(family='Helvetica', size='12', weight='bold')
ze_text = " Erreur à la création de l'image du spectre !!"
label = tk.Label( ze_info_window, bg=ze_fg, fg=ze_bg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid(row = 9, column = 0, sticky = 'ew')
# sys.exit(1)
now = datetime.now()
timestamp_debut = datetime.timestamp(now)
draw = ImageDraw.Draw(spectre_image)
if choix_spectre == "1" :
for i in range(nb_pixels_largeur):
WL_middle = ( WL_list_start[i] + WL_list_end[i] ) / 2
draw.line(( i, 0, i, nb_pixels_hauteur ), fill = color_of_ray( WL_middle ))
else:
if ( len(liste_elements) != 0 ) :
ze_text = " --> Liste des raies pour " + str( liste_elements ) + " :"
# label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), anchor = 'w')
# label.grid(row = 8, column = 0, sticky = 'ew')
ze_text = str(liste_de_toutes_les_raies)
# label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), anchor = 'w')
# label.grid(row = 9, column = 0, sticky = 'ew')
ze_text = " --> " + str(len(liste_de_toutes_les_raies)) + " raies à tracer"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid(row = 9, column = 0, sticky = 'ew')
# La largeur d'une raie dépend de la valeur de WL_resolution de manière à séparer les
# raies mitoyennes quand on "zoome" en demandant une étendue faible en nanomètre mais
# élevée en pixels.
# Mais je voudrais qu'une raie soit large d'un nombre impair de pixels...
# Sur la TODO list !
if choix_spectre == "2" :
for i in range(nb_pixels_largeur):
WL_middle = ( WL_list_start[i] + WL_list_end[i] ) / 2
for raie in liste_de_toutes_les_raies:
if abs( WL_middle - raie ) <= ( 2 * WL_resolution ):
draw.line(( i, 0, i, nb_pixels_hauteur ), fill = color_of_ray( WL_middle ))
if choix_spectre == "3" :
for i in range(nb_pixels_largeur):
WL_middle = ( WL_list_start[i] + WL_list_end[i] ) / 2
draw_the_ray = True
for raie in liste_de_toutes_les_raies:
if abs( WL_middle - raie ) <= ( 2 * WL_resolution ):
draw_the_ray = False # on est à moins de 0,5 nm d'une raie : laisser noir
if draw_the_ray:
draw.line(( i, 0, i, nb_pixels_hauteur ), fill = color_of_ray( WL_middle ))
fonte_image = ImageFont.truetype(CONST_FONTE, CONST_FONTE_TAILLE)
draw = ImageDraw.Draw(spectre_image)
if choix_imprime_nanometres:
Comment = "from " + str( WL_start ) + " nm to " + str( WL_end ) + " nm"
else:
Comment = ""
if choix_spectre == "2" :
# fond noir
if choix_imprime_nanometres:
draw.text((10.0, 8.0), Comment, grad_color, font=fonte_image)
if choix_imprime_elements:
draw.text((10.0, 22.0), nom_element, grad_color, font=fonte_image)
else:
# fond coloré pour le spectre continu (1) ou le spectre d'absoption (3)
if choix_imprime_nanometres:
draw.text((9.0, 7.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((9.0, 8.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((9.0, 9.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((10.0, 7.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((10.0, 9.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((11.0, 7.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((11.0, 8.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((11.0, 9.0), Comment, ( 255, 255, 255 ), font=fonte_image)
draw.text((10.0, 8.0), Comment, grad_color, font=fonte_image)
if choix_spectre == "3" :
if choix_imprime_elements:
draw.text((9.0, 21.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((9.0, 22.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((9.0, 22.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((10.0, 21.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((10.0, 23.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((11.0, 21.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((11.0, 22.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((11.0, 23.0), nom_element, ( 255, 255, 255 ), font=fonte_image)
draw.text((10.0, 22.0), nom_element, grad_color, font=fonte_image)
# tracé des graduations
h100nm = nb_pixels_hauteur // 4 # un trait long pour 100 nm
h50nm = nb_pixels_hauteur // 8 # un trait moyen pour 50 nm
h10nm = nb_pixels_hauteur // 16 # un trait court pour 10 nm
base = nb_pixels_hauteur # base du trait
# grad_color a été déterminée au moment du choix de type de spectre.
# largeur d'un trait de graduation en pixel : grad_W
# impair
# peu ou prou égal à un nanomètre donc (presque égal à 1 / WL_resolution)
WL_res_inverse = 1 / WL_resolution
if int( WL_res_inverse ) % 2 == 0: # pair
grad_W = int( WL_res_inverse ) + 1
else: # impair
grad_W = int( WL_res_inverse )
# graduation sur le premier pixel ? (donc i = 0)
if WL_start % 100 == 0:
draw.line( ( 0, base, 0, base - h100nm ), fill=grad_color )
draw.rectangle(((0, base), (((grad_W - 1) / 2), base - h100nm + 1)), fill=grad_color )
elif WL_start % 50 == 0:
draw.line( ( 0, base, 0, base - h50nm ), fill=grad_color )
draw.rectangle(((0, base), (((grad_W - 1 ) / 2), base - h50nm + 1)), fill=grad_color)
elif WL_start % 10 == 0:
draw.line(( 0, base, 0, base - h10nm ), fill=grad_color )
draw.rectangle(((0, base), (((grad_W - 1 ) / 2), base - h10nm + 1)), fill=grad_color)
for i in range(nb_pixels_largeur):
# un trait vertical quand passer de WL_list_start[i] à WL_list_end[i] fait
# changer de centaine sur les nanomètres...
if WL_list_start[i] // 100 != WL_list_end[i] // 100 :
# changement de centaine sur les nanomètres
draw.line(( i, base, i, base - h100nm), fill=grad_color)
draw.rectangle(((i-((grad_W-1)/2),base),(i+((grad_W-1)/2),base - h100nm + 1)), fill=grad_color)
elif WL_list_start[i] // 50 != WL_list_end[i] // 50 :
# changement de cinquantaine sur les nanomètres
draw.line(( i, base, i, base - h50nm), fill=grad_color)
draw.rectangle(((i-((grad_W-1)/2),base),(i+((grad_W-1)/2),base - h50nm + 1)), fill=grad_color)
elif WL_list_start[i] // 10 != WL_list_end[i] // 10 :
# changement de dizaine sur les nanomètres
draw.line(( i, base, i, base - h10nm), fill=grad_color)
draw.rectangle(((i-((grad_W-1)/2),base),(i+((grad_W-1)/2),base - h10nm + 1)), fill=grad_color)
spectre_image.show()
now = datetime.now()
timestamp_fin = datetime.timestamp(now)
duree = timestamp_fin - timestamp_debut
ze_text = " --> done in {0:.3f}".format(duree) + " seconde"
label = tk.Label( ze_info_window, bg=ze_bg, fg=ze_fg, text = str(ze_text), font=ze_font_info, anchor = 'w')
label.grid(row = 10, column = 0, sticky = 'ew')
if messagebox.askyesno("Enregister", "Enregister le spectre ?") :
if choix_spectre == "1" :
nom_image = "Spectre_continu_"
elif choix_spectre == "2" :
nom_image = "Spectre_emission_"
else :
nom_image = "Spectre_absorption_"
nom_image = nom_image + str(WL_start) + "_to_" + str(WL_end)
if choix_spectre == "2" or choix_spectre == "3":
for ze_element in liste_elements:
nom_image = nom_image + "_" + ze_element
year = now.year
month = now.month
if month < 10:
month = "0" + str( month )
day = now.day
if day < 10:
day = "0" + str( day )
hour = now.hour
if hour < 10:
hour = "0" + str( hour )
minute = now.minute
if minute < 10:
minute = "0" + str( minute )
second = now.second
if second < 10:
second = "0" + str( second )
nom_image = nom_image + "_" + str(year) + "-" + str(month) + "-" + str(day)
nom_image = nom_image + "_" + str(hour) + str(minute) + str(second) + str(".png")
spectre_image.save( nom_image, "PNG" )
messagebox.showinfo("Enregistré", "Spectre enregistré sousn" + nom_image)
ze_info_window.destroy()
else :
ze_info_window.destroy()
fenetre = tk.Tk()
# http://python.jpvweb.com/python/mesrecettespython/doku.php?id=geometrie_fenetre
#fenetre.geometry("%dx%d%+d%+d" % (700,400,50,50))
#fenetre.geometry('700x400')
fenetre.configure(background='#86b')
fenetre.title('Spectres lumineux')
fenetre.iconbitmap('@' + 'spectre.xbm')
ze_font = font.Font(family='Helvetica', size='12')
# code RGB classique, sur 4, 8 ou 12 bits
ze_bg='#a0a0ff' #bg = background = couleur du fond
ze_fg='#404080' #fg = foreground = couleur du texte
ze_abg='#ffff60' #active_foreground = couleur du fond survolé
# à choisir parmi 'flat', 'raised', 'sunken', 'groove', 'ridge'
# http://tkinter.fdex.eu/doc/sa.html#reliefs
ze_relief='groove'
# 'borderwidth' peut s'abréger en 'bd' : valeur en pixels
ze_bd=4
# frame pour le mode d'emploi
cadre_MdE = tk.Frame(fenetre, bg=ze_bg, relief=ze_relief, bd=ze_bd)
cadre_MdE.grid( row=0, column=0, padx, pady=5, ipadx, sticky='ew')
label = tk.Label( cadre_MdE, bg=ze_bg, fg=ze_fg, text = "Mode d'emploi :", font=ze_font)
label.grid( row=0, sticky='w')
label = tk.Label( cadre_MdE, bg=ze_bg, fg=ze_fg, text = " - il faut saisir longueur d'onde initiale et finale (en nanomètres) ;", font=ze_font)
label.grid( row=1, sticky='w')
label = tk.Label( cadre_MdE, bg=ze_bg, fg=ze_fg, text = " - largeur et hauteur de l'image contenant le spectre (en pixels) ;", font=ze_font)
label.grid( row=2, sticky='w')
label = tk.Label( cadre_MdE, bg=ze_bg, fg=ze_fg, text = " - le type de spectre : continu, émission ou absorption ;", font=ze_font)
label.grid( row=3, sticky='w')
label = tk.Label( cadre_MdE, bg=ze_bg, fg=ze_fg, text = " - éventuellement la liste des éléments chimiques ;", font=ze_font)
label.grid( row=4, sticky='w')
label = tk.Label( cadre_MdE, bg=ze_bg, fg=ze_fg, text = " - indiquer si on souhaite que le nom des éléments soit inscrit sur le spectre.", font=ze_font)
label.grid( row=5, sticky='w')
# frame pour la saisie des longueurs d'onde _ET_ les pixels (contient deux frames)
cadre_spectre_input = tk.Frame(fenetre, bg=ze_bg, relief=ze_relief, bd=ze_bd)
cadre_spectre_input.grid( row=1, column=0, padx, pady=5, ipadx, sticky='ew')
# (sous-)frame pour la saisie des longueurs d'onde
cadre_spectre_WL = tk.Frame(cadre_spectre_input, bg=ze_bg)
cadre_spectre_WL.grid( row=0, ipadx, ipady=0, sticky='w')
label = tk.Label( cadre_spectre_WL, bg=ze_bg, fg=ze_fg, text = "Longueur d'onde initiale :", font=ze_font)
label.grid( row=0, column=0, sticky='w')
WL_start_saisie = tk.StringVar()
WL_start_saisie.set("380")
saisie_WL_start = tk.Entry( cadre_spectre_WL, textvariable = WL_start_saisie, width=3, font=ze_font)
saisie_WL_start.grid( row=0, column=1)
label = tk.Label( cadre_spectre_WL, bg=ze_bg, fg=ze_fg, text = " (nm) ; longueur d'onde finale :", font=ze_font)
label.grid( row=0, column=2)
WL_end_saisie = tk.StringVar()
WL_end_saisie.set("800")
saisie_WL_end = tk.Entry( cadre_spectre_WL, textvariable = WL_end_saisie, width=3, font=ze_font)
saisie_WL_end.grid( row=0, column=3)
label = tk.Label( cadre_spectre_WL, bg=ze_bg, fg=ze_fg, text = " (nm).", font=ze_font)
label.grid( row=0, column=4)
# (sous-)frame pour la saisie des pixels
cadre_spectre_pixels = tk.Frame(cadre_spectre_input, bg=ze_bg)
cadre_spectre_pixels.grid( row=1, ipadx, ipady=0, sticky='ew')
label = tk.Label( cadre_spectre_pixels, bg=ze_bg, fg=ze_fg, text = "Dimensions de l'image du spectre, largeur :", font=ze_font)
label.grid( row=0, column=0, sticky='w')
nb_pixels_largeur_saisie = tk.StringVar()
nb_pixels_largeur_saisie.set("1260")
saisie_nb_pixels_largeur = tk.Entry( cadre_spectre_pixels, textvariable = nb_pixels_largeur_saisie, width=4, font=ze_font)
saisie_nb_pixels_largeur.grid( row=0, column=1)
label = tk.Label( cadre_spectre_pixels, bg=ze_bg, fg=ze_fg, text = " (pixels) ; hauteur : ", font=ze_font)
label.grid( row=0, column=2)
nb_pixels_hauteur_saisie = tk.StringVar()
nb_pixels_hauteur_saisie.set("160")
saisie_nb_pixels_hauteur = tk.Entry( cadre_spectre_pixels, textvariable = nb_pixels_hauteur_saisie, width=4, font=ze_font)
saisie_nb_pixels_hauteur.grid( row=0, column=3)
label = tk.Label( cadre_spectre_pixels, bg=ze_bg, fg=ze_fg, text = " (pixels) ", font=ze_font)
label.grid( row=0, column=4)
# frame pour le choix du type de spectre
cadre_choix_spectre = tk.Frame( fenetre, bg=ze_bg, relief=ze_relief, bd=ze_bd)
cadre_choix_spectre.grid( row=2, column=0, padx, pady=5, ipadx, sticky='ew')
texte_choix_spectre = tk.Label( cadre_choix_spectre, bg=ze_bg, fg=ze_fg, text = "Type de spectre :", font=ze_font)
texte_choix_spectre.grid( row=0, column=0, )
choix_spectre_value = tk.StringVar()
choix_spectre_value.set("2")
choix_spectre_continu = tk.Radiobutton(cadre_choix_spectre, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="continu", variable=choix_spectre_value, value = "1", highlightthickness=0, font=ze_font)
choix_spectre_emission = tk.Radiobutton(cadre_choix_spectre, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="émission", variable=choix_spectre_value, value = "2", highlightthickness=0, font=ze_font)
choix_spectre_absorption = tk.Radiobutton(cadre_choix_spectre, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="absorption", variable=choix_spectre_value, value = "3", highlightthickness=0, font=ze_font)
choix_spectre_continu.grid(row=0, column=1, padx, pady=0, sticky='ew')
choix_spectre_emission.grid(row=0, column=2, padx, pady=0, sticky='ew')
choix_spectre_absorption.grid(row=0, column=3, padx, pady=0, sticky='ew')
# frame pour le choix de l'impression des nanometres
cadre_imprime_nanometres = tk.Frame( fenetre, bg=ze_bg, relief=ze_relief, bd=ze_bd)
cadre_imprime_nanometres.grid( row=3, column=0, padx, pady=5, ipadx, sticky='ew')
texte = tk.Label( cadre_imprime_nanometres, bg=ze_bg, fg=ze_fg, text = "Écrire l'échelle en nanomètres sur l'image ?", font=ze_font)
texte.grid( row=0, column=0)
imprime_nanometres_value = tk.StringVar()
imprime_nanometres_value.set("o")
imprime_nanometres_oui = tk.Radiobutton(cadre_imprime_nanometres, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="oui", variable=imprime_nanometres_value, value="o", highlightthickness=0, font=ze_font)
imprime_nanometres_non = tk.Radiobutton(cadre_imprime_nanometres, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="non", variable=imprime_nanometres_value, value="n", highlightthickness=0, font=ze_font)
imprime_nanometres_oui.grid(row=0, column=1, padx, pady=0, sticky='ew')
imprime_nanometres_non.grid(row=0, column=2, padx, pady=0, sticky='ew')
# frame pour choisir les éléments chimiques
cadre_choix_elements = tk.Frame( fenetre, bg=ze_bg, relief=ze_relief, bd=ze_bd, cursor='pirate')
cadre_choix_elements.grid( row=4, column=0, padx, pady=5, ipadx, sticky='ew')
cadre_choix_elements.columnconfigure(0, weight=1)
cadre_choix_elements.columnconfigure(1, weight=1)
cadre_choix_elements.columnconfigure(2, weight=1)
cadre_choix_elements.columnconfigure(3, weight=1)
texte = tk.Label( cadre_choix_elements, bg=ze_bg, fg=ze_fg, text = "Éléments chimiques :", font=ze_font)
texte.grid( row=0, column=0, sticky='w')
ze_sticky = 'ew'
var_Hydrogene = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Hydrogène", anchor='w', variable=var_Hydrogene, highlightthickness=0, font=ze_font)
case.grid( row=1, column=0, sticky=ze_sticky)
# var_Hydrogene.get()
# Si la case est cochée, la valeur renvoyée par la variable sera la chaîne "1".
# Si elle n'est pas cochée, ce sera "0".
# Ça se teste avec if var_Hydrogene.get() == "1" (PAS == 1)
var_Helium = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Hélium", anchor='w', variable=var_Helium, highlightthickness=0, font=ze_font)
case.grid( row=1, column=1, sticky=ze_sticky)
var_Lithium = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Lithium", anchor='w', variable=var_Lithium, highlightthickness=0, font=ze_font)
case.grid( row=1, column=2, sticky=ze_sticky)
var_Sodium = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Sodium", anchor='w', variable=var_Sodium, highlightthickness=0, font=ze_font)
case.grid( row=1, column=3, sticky=ze_sticky)
var_Magnesium = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Magnésium", anchor='w', variable=var_Magnesium, highlightthickness=0, font=ze_font)
case.grid( row=2, column=0, sticky=ze_sticky)
var_Argon = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Argon", anchor='w', variable=var_Argon, highlightthickness=0, font=ze_font)
case.grid( row=2, column=1, sticky=ze_sticky)
var_Calcium = tk.StringVar()
# var_Calcium.set("1")
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Calcium", anchor='w', variable=var_Calcium, highlightthickness=0, font=ze_font)
case.grid( row=2, column=2, sticky=ze_sticky)
var_Titane = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Titane", anchor='w', variable=var_Titane, highlightthickness=0, font=ze_font)
case.grid( row=2, column=3, sticky=ze_sticky)
var_Manganese = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Manganèse", anchor='w', variable=var_Manganese, highlightthickness=0, font=ze_font)
case.grid( row=3, column=0, sticky=ze_sticky)
var_Fer = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Fer", anchor='w', variable=var_Fer, highlightthickness=0, font=ze_font)
case.grid( row=3, column=1, sticky=ze_sticky)
var_Hydrargyrum = tk.StringVar()
case = tk.Checkbutton(cadre_choix_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="Hydrargyrum", anchor='w', variable=var_Hydrargyrum, highlightthickness=0, font=ze_font)
case.grid( row=3, column=2, sticky=ze_sticky)
# frame pour le choix de l'impression des éléments
cadre_imprime_elements = tk.Frame( fenetre, bg=ze_bg, relief=ze_relief, bd=ze_bd)
cadre_imprime_elements.grid( row=5, column=0, padx, pady=5, ipadx, sticky='ew')
texte = tk.Label( cadre_imprime_elements, bg=ze_bg, fg=ze_fg, text = "Écrire les éléments chimiques sur l'image ?", font=ze_font)
texte.grid( row=0, column=0)
imprime_elements_value = tk.StringVar()
imprime_elements_value.set("o")
imprime_elements_oui = tk.Radiobutton(cadre_imprime_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="oui", variable=imprime_elements_value, value="o", highlightthickness=0, font=ze_font)
imprime_elements_non = tk.Radiobutton(cadre_imprime_elements, bg=ze_bg, fg=ze_fg, activebackground=ze_abg, text="non", variable=imprime_elements_value, value="n", highlightthickness=0, font=ze_font)
imprime_elements_oui.grid(row=0, column=1, padx, pady=0, sticky='ew')
imprime_elements_non.grid(row=0, column=2, padx, pady=0, sticky='ew')
# frame pour les boutons 'Quitter' et 'Dessiner le spectre'
cadre_boutons = tk.Frame( fenetre, bg=ze_bg, relief=ze_relief, bd=ze_bd)
cadre_boutons.grid( row=6, column=0, padx, pady=5, ipadx, ipady=0, sticky='ew')
cadre_boutons.columnconfigure(0, weight=1)
cadre_boutons.columnconfigure(1, weight=1)
cadre_boutons.columnconfigure(2, weight=1)
cadre_boutons.columnconfigure(3, weight=1)
button = tk.Button( cadre_boutons, text = "Quitter", bg=ze_bg, fg=ze_fg, activebackground=ze_abg, command = fenetre.quit, font=ze_font, anchor='w')
button.grid( row=0, column=0, padx, pady=5, sticky='w')
cadre_notice = tk.Frame( cadre_boutons, bg=ze_bg, relief='flat', bd=ze_bd)
cadre_notice.grid( row=0, column=1, columnspan=2, sticky='ew')
ze_font = font.Font(family='Helvetica', size='9')
label = tk.Label( cadre_notice, bg=ze_bg, fg=ze_fg, text = "Auteur : Hugues FERTIN, ", font=ze_font)
label.grid( row=0, column=0, columnspan=2, sticky='ew')
label = tk.Label( cadre_notice, bg=ze_bg, fg=ze_fg, text = "licence CC-BY-NC-SA : attribution, non-commercial, share alike", font=ze_font)
label.grid( row=1, column=0, columnspan=2, sticky='ew')
ze_font = font.Font(family='Helvetica', size='12')
button = tk.Button( cadre_boutons, text = "Dessiner le spectre", bg=ze_bg, fg=ze_fg, activebackground=ze_abg, command = dessiner_le_spectre, font=ze_font, anchor='e')
button.grid( row=0, column=3, padx, pady=5, sticky='e')
# vendredi 20 mars 2020, 11:59:02 (UTC+0100)
# pas encore compris comment ça marche...
#fenetre.bind_all('<Return>', dessiner_le_spectre)
fenetre.mainloop()