Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 18/02/2019, à 13:54

piter42

[ RESOLU] modification script python dans tkinter

bonjour,
toujours en rapport avec les éxercices de g swinnen,j' ai modifié le scrip pour enlever tout les boutons (gauche ,droit,haut ,bas,)dédiés à chaque planetes,par contre je bloque sur la distance à inscrire après chaque clic de déplacement de la planète,la distance de départ s affiche mais je n est plus rien une fois une des 2 planètes déplacées

from tkinter import *
from math import sqrt

def distance(x1,y1,x2,y2):
    "distance séparant les points (x1,y1)et (x2,y2)" 
    d=sqrt((x2-x1)**2+(y2-y1)**2)   # théorème de pythagore
    return d
    
def forceG(m1,m2,di):
    "force de gravitation s exercant entre m1 et m2 pour une distance di"
    return m1*m2*6.67e-11/di*2 # loi de newton
    
def pointeur(event):
    global x,y,choix
    if choix==1:
        can.coords(astreT,event.x,event.y,event.x+20,event.y+20)
    elif choix==2:
        can.coords(astreL,event.x,event.y,event.x+20,event.y+20)
        
        chaine.configure(text="clic détecté en X="+str(event.x)+" Y="+str(event.y))

    # calcul de nouvelle interdistance
    di=distance(x[0],y[0],x[1],y[1])
    # conversion de la distance écran en distance astronomique
    diA=di*1e6  # 1 pixel = 1 million de kms
    # calcul de la force de gravitation correspondante
    f=forceG(m1,m2,diA)
    # affichage de nouvelles distances et force
    valdis.configure(text="distance="+str(diA)+"kms")
    valfor.configure(text="force="+str(f)+"N")
    # adaptation du pas de déplacement en fonction de la distance
    step=di/10
    
def choix_terre():
    global choix
    choix=1
    
def choix_lune():
    global choix
    choix=2

# masses des 2 astres
m1=6e24 # valeur de la masse de la terre en kg
m2=6e24 
astre=[0]*2 # liste servant à memoriser les références des desssins
x=[50.,350.] # liste des coordonnées X de chaque astre à l'écran
y=[100.,100.] # liste des coordonnées Y de chaque astre
step=10     # pas de déplacement initial
choix=0


fen=Tk()
fen.title("exercice de planètes")

# libellés fixe en haut du canevas
valM1=Label(fen,text="M1="+str(m1)+"kg")
valM1.grid(row=1,column=0)
valM2=Label(fen,text="M2="+str(m2)+"kg")
valM2.grid(row=1,column=1)
valdis=Label(fen,text="Distance")
valdis.grid(row=3,column=0)
valfor=Label(fen,text="Force")
valfor.grid(row=3,column=1)

# canevas avec les 2 astres
can=Canvas(fen,bg="white",height=200,width=400)
can.bind("<Button-1>",pointeur)
can.grid(row=2,column=0,columnspan=2)
 #  création des 2 astres
astreL=can.create_oval(x[0]-10,y[0]-10,x[0]+10,y[0]+10,width=2,outline="black")
astreT=can.create_oval(x[1]-10,y[1]-10,x[1]+10,y[1]+10,fill="blue")

#  création de 2 boutons pour enclencher le dpl et les coords de l'astre concerné
Button(fen,text="terre",command=choix_terre).grid(row=4,column=1)
Button(fen,text="lune",command=choix_lune).grid(row=4,column=0)
#  affichage coord des clics de souris
chaine=Label(fen)
chaine.grid(row=5,column=0)





fen.mainloop()

si vous pouviez m aiguiller merci,pierre

Dernière modification par piter42 (Le 19/02/2019, à 09:44)

Hors ligne

#2 Le 18/02/2019, à 17:50

kholo

Re : [ RESOLU] modification script python dans tkinter

salut,
tu te lances dans le rétro engineering...

piter42 a écrit :

je bloque sur la distance à inscrire après chaque clic de déplacement de la planète,la distance de départ s affiche mais je n est plus rien une fois une des 2 planètes déplacées

alors, ... ça va être un peu compliqué de trouver ce que tu ne cherches pas...
si tu as virer des boutons, comment vas tu déplacer les planètes ? ... en Drag and Drop...
les fonctions de tes boutons t'apporteraient la réponse si les valeurs que tu cherches sont les même que celles données au départ... chaque clic devait représenter une modification donnée de ta valeur ainsi que de se représentation graphique....
non ?
si c'est le cas une règle de 3 te permettrait de passer en full graphique...

je ne comprends pas cette ligne :

astre=[0]*2 # liste servant à mémoriser les références des dessins

pour avoir

astre=[0, 0]

je vois des coordonnées avec des x et des y...
un dico ferait peut être plus l'affaire

coordonnées = {"terre":(xterre, yterre), "lune":(xlune, ylune) }

NB : j'ai mis des tuples mais tu peux mettre des listes à la place

ensuite, je vois des variables en "global"... mais pas déclarée au début du code...
et, entre nous, je trouve l'utilisation de global imbitable...
=> les recherches des valeurs suivent la règle... euh je sais plus (mais, pour faire simple, ça va en remontant si tu vois ce que je veux dire...)

et, si je peux me permettre (sans contrepèterie), la déclaration de tkinter est plus lisible quand elle est explicite.
dis autrement évite ce genre de ligne :

from tkinter import *

oui, je sais, on trouve ça de partout,... mais c'est pas parce que les autres écrivent du code pourri qu'il faut faire la même chose ; avec ça tu vois des instances arriver de nul part genre les N, S, E, W, END... beurk !
là tu as 2 choix :
soit tu déclares bien tout :

from tkinter import Tk, Canvas, Label, Button, ...

les ... pour en mettre tant que tu veux séparés par des virgules
puis tu peux créer tes instances comme elles sont dans ton code (mais, perso, j'aime pas !)

ou

import tkinter

voire, mon préféré :

import tkinter as tk

qui se fait beaucoup
et tu reprend tes instances avec soit
tkinter.module
ou
tk.module
selon comme tu as fais ta déclaration
par exemple :

un_bouton = tkinter.Button(les arguments ici)

ou (donc, mon préféré)

un_bouton = tk.Button(les arguments ici)

le code n'en sera que plus lisible sans beaucoup d'effort
(pour moi qui apprend tout comme toi, ça m'aide beaucoup de faire ces corrections quand je reprend les codes dans les tutos
c'est tout de suite plus parlant)

et, tant qu'à parler de lisibilité, mets des espaces en suivant à peu près les même règles qu'avec un traitement de texte...

je te "corrige" ton code pour être plus explicite :
edit : les docstrings, c'est 3 quottes ou doubles quottes

""" du texte ici  """

perso je met des doubles et me garde les simple si je veux isoler du code provisoirement qui contiendrait des doubles

#!/usr/bin/env python3
# -*- coding: UTF8 -*-
"""

"""

import tkinter as tk
from math import sqrt

global x, y, choix

def distance(x1, y1, x2, y2):
    """distance séparant les points (x1,y1)et (x2,y2)"""
    d=sqrt((x2 - x1)**2 + (y2 - y1)**2)   # théorème de pythagore
    return d 

def forceG(m1, m2, di):
    """force de gravitation s exercant entre m1 et m2 pour une distance di"""
    return m1 * m2 * 6.67e - 11 / di * 2 # loi de newton

def pointeur(event):
    if choix==1:
        can.coords(astreT, event.x, event.y, event.x + 20, event.y + 20)
    elif choix==2:
        can.coords(astreL, event.x, event.y, event.x + 20, event.y + 20)

        chaine.configure(text="clic détecté en X=" + str(event.x) + " Y=" + str(event.y))

    # calcul de nouvelle interdistance
    di = distance(x[0], y[0], x[1], y[1])
    # conversion de la distance écran en distance astronomique
    diA = di * 1e6  # 1 pixel = 1 million de kms
    # calcul de la force de gravitation correspondante
    f = forceG(m1, m2, diA)
    # affichage de nouvelles distances et force
    valdis.configure(text="distance=" + str(diA) + "kms")
    valfor.configure(text="force=" + str(f) + "N")
    # adaptation du pas de déplacement en fonction de la distance
    step = di / 10
    
def choix_terre():
    choix = 1
    
def choix_lune():
    choix = 2

# masses des 2 astres
m1 = 6e24 # valeur de la masse de la terre en kg
m2 = 6e24 
astre = [0] * 2 # liste servant à memoriser les références des dessins
x = [50., 350.] # liste des coordonnées X de chaque astre à l'écran
y = [100., 100.] # liste des coordonnées Y de chaque astre
step = 10     # pas de déplacement initial
choix = 0


fen = tk.Tk()
fen.title("exercice de planètes")

# libellés fixe en haut du canevas
valM1 = tk.Label(fen, text="M1=" + str(m1) + "kg")
valM1.grid(row=1, column=0)
valM2 = tk.Label(fen, text="M2=" + str(m2) + "kg")
valM2.grid(row=1, column=1)
valdis = tk.Label(fen, text="Distance")
valdis.grid(row=3, column=0)
valfor = tk.Label(fen, text="Force")
valfor.grid(row=3, column=1)

# canevas avec les 2 astres
can = tk.Canvas(fen, bg="white", height=200, width=400)
can.bind("<Button-1>", pointeur)
can.grid(row=2, column=0, columnspan=2)
# création des 2 astres
astreL = can.create_oval(x[0]-10, y[0]-10, x[0]+10, y[0]+10, width=2, outline="black")
astreT = can.create_oval(x[1]-10, y[1]-10, x[1]+10, y[1]+10, fill="blue")

# création de 2 boutons pour enclencher le dpl et les coords de l'astre concerné
tk.Button(fen, text="terre", command=choix_terre).grid(row=4, column=1)
tk.Button(fen, text="lune", command=choix_lune).grid(row=4, column=0)
# affichage coord des clics de souris
chaine = tk.Label(fen)
chaine.grid(row=5, column=0)

fen.mainloop()

même sans coloration syntaxique, ça respire un peu plus, non ?

bon, ensuite... alors tu veux faire bouger des bouboules ?
d'abord qu'est ce qui se passe quand on clic sur un objet ?

#!/usr/bin/env python
# -*- coding: UTF8 -*-

import tkinter as tk

def Clic(event):
    # position du pointeur de la souris
    X = event.x
    Y = event.y
    print("Position du clic -> ", X, Y)

    # coordonnées de l'objet
    # [xmin, ymin, xmax, ymax] = Canevas.coords(Carre)
    # print("Position objet -> ", xmin, ymin, xmax, ymax)

# Création de la fenêtre principale
Mafenetre = tk.Tk()
Mafenetre.title("Drag and drop")

# Création d'un widget Canvas
Largeur = 480
Hauteur = 160
TailleCarre = 20
Canevas = tk.Canvas(Mafenetre, width=Largeur, height=Hauteur, bg ='white')
# Création d'un objet graphique
Carre = Canevas.create_rectangle(0, 0, TailleCarre * 2, TailleCarre * 2, fill='maroon')

# La méthode bind() permet de lier un événement avec une fonction
Canevas.bind('<Button-1>', Clic) # évévement clic gauche (press)

Canevas.focus_set()
Canevas.pack(padx=10, pady=10)

Mafenetre.mainloop()

ensuite le drag and drop (le code n'est pas corrigé !)

#!/usr/bin/env python
# -*- coding: UTF8 -*-

# script drag_and_drop.py
#(C) Fabrice Sincère
from tkinter import *

def Clic(event):
    """ Gestion de l'événement Clic gauche """
    global DETECTION_CLIC_SUR_OBJET

    # position du pointeur de la souris
    X = event.x
    Y = event.y
    print("Position du clic -> ",X,Y)

    # coordonnées de l'objet
    [xmin,ymin,xmax,ymax] = Canevas.coords(Carre)

    print("Position objet -> ",xmin,ymin,xmax,ymax)
    if xmin<=X<=xmax and ymin<=Y<=ymax: DETECTION_CLIC_SUR_OBJET = True
    else: DETECTION_CLIC_SUR_OBJET = False
    print("DETECTION CLIC SUR OBJET -> ",DETECTION_CLIC_SUR_OBJET)

def Drag(event):
    """ Gestion de l'événement bouton gauche enfoncé """
    X = event.x
    Y = event.y
    print("Position du pointeur -> ",X,Y)

    if DETECTION_CLIC_SUR_OBJET == True:
        # limite de l'objet dans la zone graphique
        if X<0: X=0
        if X>Largeur: X=Largeur
        if Y<0: Y=0
        if Y>Hauteur: Y=Hauteur
        # mise à jour de la position de l'objet (drag)
        Canevas.coords(Carre,X-TailleCarre,Y-TailleCarre,X+TailleCarre,Y+TailleCarre)

DETECTION_CLIC_SUR_OBJET = False

# Création de la fenêtre principale
Mafenetre = Tk()
Mafenetre.title("Drag and drop")

# Création d'un widget Canvas
Largeur = 480
Hauteur = 160
TailleCarre = 20
Canevas = Canvas(Mafenetre,width=Largeur,height=Hauteur,bg ='white')
# Création d'un objet graphique
Carre = Canevas.create_rectangle(0,0,TailleCarre*2,TailleCarre*2,fill='maroon')

# La méthode bind() permet de lier un événement avec une fonction
Canevas.bind('<Button-1>',Clic) # évévement clic gauche (press)
Canevas.bind('<B1-Motion>',Drag) # événement bouton gauche enfoncé (hold down)

Canevas.focus_set()
Canevas.pack(padx=10,pady=10)

Mafenetre.mainloop()

ensuite il y a cette interaction entre ta représentation graphique, tes données et une valeur que tu veux voir apparaître... et se modifier...
quand on a des valeurs qui se modifient en temps réel dans tkinter on utilise les machinVar (intvar(), strVar(),...)
ce sont des objets que l'on colle à un objet en tant que valeur...
une démo, parce que là je m'embrouille moi même :
voilà un code très simple :

#!/usr/bin/env python3
# -*- coding: UTF8 -*-
"""
module qui écrit dans un Label au fur et à mesure qu'on tape dans un Entry
"""
import tkinter as tk

fenetre = tk.Tk()

# entrée
value = tk.StringVar() 
value.set("texte par défaut")

label = tk.Label(fenetre, textvariable=value)
label.pack()

entree = tk.Entry(fenetre, textvariable=value, width=30)
entree.pack()

fenetre.mainloop()

pour le reste je te laisse digérer tout ça !
accroche toi !

Dernière modification par kholo (Le 18/02/2019, à 18:03)

Hors ligne

#3 Le 18/02/2019, à 19:58

pingouinux

Re : [ RESOLU] modification script python dans tkinter

Bonsoir,
Si j'ai bien compris ce que tu veux faire, dans la fonction pointeur, en plus de déplacer le dessin de la planète, il faut aussi mettre à jour ses coordonnées (tableaux x et y).

Hors ligne

#4 Le 18/02/2019, à 20:23

piter42

Re : [ RESOLU] modification script python dans tkinter

pingouinux a écrit :

Bonsoir,
Si j'ai bien compris ce que tu veux faire, dans la fonction pointeur, en plus de déplacer le dessin de la planète, il faut aussi mettre à jour ses coordonnées (tableaux x et y).

oui ce que je veux,c est comme j avais avec les boutons ,c est afficher la nouvelle distance et la nouvelle force d attraction une fois que j ai déplacé une des 2 planètes avec le pointeur .

pour kholo,merci de ta reponse,je peux déplacer les planètes avec le script ainsi modifier avec le pointeur,mais voir le probleme que je rencontre  dans ma phrase ci dessus. Tout marchait avec les boutons,je remplace les boutons par le pointeur tout marche sauf distance et force alors que les nouvelles coordonnées du pointeur s affiche,je pensais que c était juste un problèmes de variables ou d'arguments,c est vrai que j ai été un peu plus loin que l exercice demandé,il demandait juste de remplacer les boutons par le pointeur donc pour le reste je n ai peut être pas encore appris la méthode pour le résoudre..

Dernière modification par piter42 (Le 18/02/2019, à 20:42)

Hors ligne

#5 Le 18/02/2019, à 22:46

piter42

Re : [ RESOLU] modification script python dans tkinter

Apres maintes essai j ai progressé...

#!/usr/bin/env python 3
# -*- coding: UTF8 -*-

from tkinter import *
from math import sqrt

global x,y,choix

def distance(x1, y1, x2, y2):
    "distance séparant les points (x1,y1)et (x2,y2)"
    d=sqrt((x2-x1)**2 + (y2-y1)**2)   # théorème de pythagore
    return d
    
    
def forceG(m1,m2,di):
    "force de gravitation s exercant entre m1 et m2 pour une distance di"
    return m1*m2*6.67e-11 / di*2 # loi de newton
    
    
def pointeur(event):
    
    if choix==1:
        x[1], y[1] = x[1] + event.x, y[1] + event.y  # nouvelles coordonnées
        can.coords(astreT, event.x, event.y, event.x+20, event.y+20) # déplacement de la planète dans le canevas
        chaine.configure(text="clic détecté en X=" +str(event.x) + " Y=" + str(event.y))
        
    elif choix==2:
        x[0], y[0] = x[0] + event.x, y[0] + event.y 
        can.coords(astreL, event.x, event.y, event.x+20, event.y+20)
        chaine.configure(text="clic détecté en X=" +str(event.x) + " Y=" + str(event.y))
        
        

    # calcul de nouvelle interdistance
    di=distance(x[0], y[0], x[1], y[1])
    # conversion de la distance écran en distance astronomique
    diA=di*1e6  # 1 pixel = 1 million de kms
    # calcul de la force de gravitation correspondante
    f=forceG(m1, m2, diA)
    # affichage de nouvelles distances et force
    valdis.configure(text="distance=" + str(diA) + "kms")
    valfor.configure(text="force=" + str(f) + "N")
    # adaptation du pas de déplacement en fonction de la distance
    step=di/10
    
def choix_terre():
    global choix
    choix=1
    
def choix_lune():
    global choix
    choix=2


    
    



# masses des 2 astres
m1=6e24 # valeur de la masse de la terre en kg
m2=6e24 
astre=[0]*2 # liste servant à memoriser les références des desssins
x=[50., 350.] # liste des coordonnées X de chaque astre à l'écran
y=[100., 100.] # liste des coordonnées Y de chaque astre
step=10     # pas de déplacement initial
choix=0


fen=Tk()
fen.title("exercice de planètes")

# libellés fixe en haut du canevas
valM1=Label(fen, text="M1=" + str(m1) + "kg")
valM1.grid(row=1, column=0)
valM2=Label(fen, text="M2=" + str(m2) + "kg")
valM2.grid(row=1, column=1)
valdis=Label(fen, text="Distance")
valdis.grid(row=3, column=0)
valfor=Label(fen, text="Force")
valfor.grid(row=3, column=1)

# canevas avec les 2 astres
can=Canvas(fen, bg="white", height=200, width=400)
can.bind("<Button-1>", pointeur)
can.grid(row=2, column=0, columnspan=2)
 #  création des 2 astres
astreL=can.create_oval(x[0]-10, y[0]-10, x[0]+10, y[0]+10, width=2, outline="black")
astreT=can.create_oval(x[1]-10, y[1]-10, x[1]+10, y[1]+10, fill="blue")

#  création de 2 boutons pour enclencher le dpl et les coords de l'astre concerné
Button(fen, text="terre", command=choix_terre).grid(row=4, column=1)
Button(fen, text="lune", command=choix_lune).grid(row=4, column=0)
#  affichage coord des clics de souris
chaine=Label(fen)
chaine.grid(row=5, column=0)





fen.mainloop()

Par contre il doit y avoir encore une petite erreur car , même quand les planètes sont l une sur l autre j ai toujours beaucoup de kms,je recherche...,kholo j ai amelioré la netteté wink par contre si je met 2" pour la docstring ça ne marche pas..?

Dernière modification par piter42 (Le 18/02/2019, à 22:55)

Hors ligne

#6 Le 18/02/2019, à 23:09

pingouinux

Re : [ RESOLU] modification script python dans tkinter

Pour la mise à jour des coordonnées, ne serait-ce pas plutôt ceci ?
J'ai aussi un peu simplifié text=....

def pointeur(event):

    if choix==1:
        x[1], y[1] = event.x, event.y
        can.coords(astreT, event.x, event.y, event.x+20, event.y+20)
        chaine.configure(text="clic détecté en X=%d Y=%d"%(event.x,event.y))

    elif choix==2:
        x[0], y[0] = event.x, event.y
        can.coords(astreL, event.x, event.y, event.x+20, event.y+20)
        chaine.configure(text="clic détecté en X=%d Y=%d"%(event.x,event.y))
.............................................................;

Pour calculer la distance, il existe la fonction hypot, dans le module math :

    d=hypot(x2-x1, y2-y1)

Ajouté :
- Dans forceG, la distance au dénominateur doit être élevée au carré.
- Les deux planètes ont même masse, est-ce volontaire ?

Dernière modification par pingouinux (Le 19/02/2019, à 08:34)

Hors ligne

#7 Le 19/02/2019, à 09:36

piter42

Re : [ RESOLU] modification script python dans tkinter

merci pingouix,
Effectivement avec tes nouvelles coordonnées ,ça marche,je ne sais pas pourquoi je me compliquais la vie ?preuve que je n ai pas tout assimilé,mais ça rentre à force de programmer.Oui les 2 planètes ont la même masse

Hors ligne

#8 Le 19/02/2019, à 10:23

kholo

Re : [ RESOLU] modification script python dans tkinter

salut,
les docstrings, c'est 3 quottes

""" du texte ici """

DEMO :

#!/usr/bin/env python3
# -*- coding: UTF8 -*-

"""
module Démo pour clic sur des objets
utilisation des tags de Canvas
"""

import tkinter as tk
from math import sqrt

global x , y, choix

fen = tk.Tk()
fen.geometry("+200+200")
fen.title("exercice de planètes")

# masses des 2 astres
m1 = 6e24 # valeur de la masse de la terre en kg
m2 = 6e24 
astre = [0] * 2 # liste servant à mémoriser les références des dessins
x = [50., 350.] # liste des coordonnées X de chaque astre à l'écran
y = [100., 100.] # liste des coordonnées Y de chaque astre
step = 10     # pas de déplacement initial
choix = None

# canevas avec les 2 astres
can = tk.Canvas(fen, bg="white", height=200, width=400)
can.grid(row=2, column=0, columnspan=2)

#  création des 2 astres
""" AJOUT DE fill="white" pour astreL """
astreL = can.create_oval(x[0]-10, y[0]-10, x[0]+10, y[0]+10, width=2, fill="white", outline="black")
astreT = can.create_oval(x[1]-10, y[1]-10, x[1]+10, y[1]+10, fill="blue")

# possibilité 1
# def quelle_planete(event):
    # """ indique l'objet clické """
    # print('objet clické', event.x, event.y)
    # print(event.widget.find_closest(event.x, event.y))
# can.tag_bind(astreL, '<ButtonPress-1>', quelle_planete)       
# can.tag_bind(astreT, '<ButtonPress-1>', quelle_planete) 

""" possibilité 2 """
def choix_terre(event):
    global choix
    choix = 1
    print("c'est la terre")
    # ...

def choix_lune(event):
    global choix
    choix = 2
    print("c'est la lune")
    # ...

can.tag_bind(astreL, '<ButtonPress-1>', choix_lune)
can.tag_bind(astreT, '<ButtonPress-1>', choix_terre) 

fen.mainloop()

Hors ligne