IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Exercice 8.14 Swinnen


Sujet :

Python

  1. #1
    Membre régulier
    Homme Profil pro
    Technicien
    Inscrit en
    Février 2010
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Février 2010
    Messages : 59
    Points : 113
    Points
    113
    Par défaut Exercice 8.14 Swinnen
    Bonjour,

    J'ai un probleme avec cet exo, message d'erreur : 'int' object is not callable.
    Sans compter le fait que c'est une usine à gaz. Je cherche à calculer et à afficher les 2 distances.
    Merci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    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
     
     
     
    # procédure générale de déplacement :
    def pointeur(event):
        i=0
        x[n.get()],y[n.get()]=event.x,event.y
        can1.coords(oval[n.get()], event.x,event.y, event.x+30,event.y+30)
     
        di[0] = distance(x[2], y[2],x[1],y[1])
        di[1] = distance(x[2], y[2],x[0],y[0])
        di[2] = distance(x[0], y[0],x[1],y[1])
        while i<len(di)():
            if i != n.get():
                valDis.configure(text="Distance "+str(i) +"= " +str(di[i]))
            i=i+1
     
     
    # gestionnaires d'événements :
     
     
    #------ Programme principal -------
    # les variables suivantes seront utilisées de manière globale :
    x=[0,100,200] # coordonnées initiales
    y=[100,100,100]
    oval=[0,0,0]
    di=[0,0,0]
     
    # Création du widget principal ("maître") :
    fen = Tk()
    fen.title("Exercice d'animation avec tkinter")
    n=IntVar()
    # création des widgets "esclaves" :
    can1 = Canvas(fen,bg='dark grey',height=300,width=300)
    oval[0] = can1.create_oval(x[0],y[0],x[0]+30,y[0]+30,width=2,fill='red')
    oval[1] = can1.create_oval(x[1],y[1],x[1]+30,y[1]+30,width=2,fill='blue')
    oval[2] = can1.create_oval(x[1],y[1],x[1]+30,y[1]+30,width=2,fill='yellow')
    can1.bind("<Button-1>",pointeur)
    can1.pack(side=TOP)
     
    valDis = Label(fen, text="Distance1")
    valDis.pack()
    valDis1 = Label(fen, text="Distance2")
    valDis1.pack()
     
    rButton=Radiobutton(fen,text='rouge',variable=n,value=0)
    rButton.pack()
    rButton1=Radiobutton(fen,text='bleu',variable=n,value=1)
    rButton1.pack()
    rButton2=Radiobutton(fen,text='jaune',variable=n,value=2)
    rButton2.pack()
    rButton.select()
     
     
     
    # démarrage du réceptionnaire d’évènements (boucle principale) :
    fen.mainloop()

  2. #2
    Membre éprouvé
    Homme Profil pro
    Aucune activité
    Inscrit en
    Novembre 2011
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Aucune activité

    Informations forums :
    Inscription : Novembre 2011
    Messages : 505
    Points : 926
    Points
    926
    Par défaut
    Bonsoir,
    En reprenant le code, ligne 20, est écrit:
    Que viennent fait les parenthèses terminales?

    PS: à part cela, le tout semble répondre aux attentes, non?

    Clodion

  3. #3
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    Oui , c'est bien l'erreur . Mais à quoi sert la variable n = IntVar() ? Ce serait les variables globales , non ? Ce n est utilisé comme commande , c'est assez bizarre .

    Aussi , pourquoi n'y a t-il de corrigés aux exercices du livre ?
    _""""Cats have a big heart ^^ unlike some bad people (whose will never change in their brain) """

  4. #4
    Membre éprouvé
    Homme Profil pro
    Aucune activité
    Inscrit en
    Novembre 2011
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Aucune activité

    Informations forums :
    Inscription : Novembre 2011
    Messages : 505
    Points : 926
    Points
    926
    Par défaut
    Bonsoir,
    La variable n dans n=IntVar() ligne 23 est une variable nécessaire pour le lien avec les Radiobuttons de tkinter.
    Oui, elle est globale.
    Il faut regarder dans le manuel de tkinter pour en aborder le fonctionnement.

    Clodion

  5. #5
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    Ok. Car le plus souvent , la variable commande est utilisée avec l'appel de fonctions genre "avance le rectangle" "en haut" "à gauche" . C'est intéressant de savoir cette fonctionnalité , mais ceci ne marche qu'avec des variables globales , donc je ne penses pas que lorsqu'il s'agit d'avancer ou de faire reculer un rectangle , ce soit possible ( les coordonnées du centre du clic ) .
    Cependant, tkinter montre certaines capacités à résoudre les problèmes géométriques .Est-ce que l'on peut utiliser tkinter pour créer des sites (enfin du moins certaines parties) ?
    _""""Cats have a big heart ^^ unlike some bad people (whose will never change in their brain) """

  6. #6
    Membre éprouvé
    Homme Profil pro
    Aucune activité
    Inscrit en
    Novembre 2011
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Aucune activité

    Informations forums :
    Inscription : Novembre 2011
    Messages : 505
    Points : 926
    Points
    926
    Par défaut
    Bonsoir,
    Pour l'utilisation de ces variables en tkinter:
    tkinter, p153, point 52
    Sinon, plus généralement, sur developpez.
    Quand à utiliser tkinter pour créer des sites, c'est sans doutes possible… Mais cela n'est vraiment pas fait pour cela.

    Clodion

  7. #7
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    Merci pour l'aide . Tu es un des premiers qui m'a aidé sur ce forum . Tu es super cool (mais Wiztricks est un peu méchant *.*).
    Faut dire que mes codes n'étaient pas parfaits

    Bonne coupe du monde (enfin si tu aimes le foot quoi )
    _""""Cats have a big heart ^^ unlike some bad people (whose will never change in their brain) """

  8. #8
    Membre régulier
    Homme Profil pro
    Technicien
    Inscrit en
    Février 2010
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Février 2010
    Messages : 59
    Points : 113
    Points
    113
    Par défaut
    Merci Clodion,
    Je vais aller faire un tour chez affelou
    Au final j'ai modifié le script pour afficher la distance entre l'objet qui est deplacé et les 2 autres, mais c'est bien compliqué. Il y a certainement plus simple.
    Une bonne âme pour m'orienter?
    Merci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    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
     
     
     
    # procédure générale de déplacement :
    def pointeur(event):
        i=0
        x[n.get()],y[n.get()]=event.x,event.y
        can1.coords(oval[n.get()], event.x,event.y, event.x+30,event.y+30)
     
        di[0] = distance(x[1], y[1],x[2],y[2]) #dist bleu-jaune
        di[1] = distance(x[2], y[2],x[0],y[0]) #dist rouge-jaune
        di[2] = distance(x[0], y[0],x[1],y[1]) #dist rouge-bleu
        while i<len(di):
            if i != n.get():
                valDis[i].configure(text="Distance "+str(i) +"= " +str(di[i]))
                print(x) # test
            i=i+1
     
     
    # gestionnaires d'événements :
     
     
    #------ Programme principal -------
     
    x=[0,100,200] # coordonnées initiales
    y=[100,100,100]
    oval=[0,0,0]
    di=[0,0,0]
    valDis=[0,0,0]
     
    # Création du widget principal ("maître") :
    fen = Tk()
    fen.title("Exercice d'animation avec tkinter")
    n=IntVar()
    # création des widgets "esclaves" :
    can1 = Canvas(fen,bg='dark grey',height=300,width=300)
    oval[0] = can1.create_oval(x[0],y[0],x[0]+30,y[0]+30,width=2,fill='red')
    oval[1] = can1.create_oval(x[1],y[1],x[1]+30,y[1]+30,width=2,fill='blue')
    oval[2] = can1.create_oval(x[1],y[1],x[1]+30,y[1]+30,width=2,fill='yellow')
    can1.bind("<Button-1>",pointeur)
    can1.pack(side=TOP)
     
    valDis[0] = Label(fen, text="Distance0")
    valDis[0].pack()
    valDis[1] = Label(fen, text="Distance1")
    valDis[1].pack()
    valDis[2] = Label(fen, text="Distance2")
    valDis[2].pack()
     
    rButton=Radiobutton(fen,text='rouge',variable=n,value=0)
    rButton.pack()
    rButton1=Radiobutton(fen,text='bleu',variable=n,value=1)
    rButton1.pack()
    rButton2=Radiobutton(fen,text='jaune',variable=n,value=2)
    rButton2.pack()
    rButton.select()
     
     
     
    # démarrage du réceptionnaire d’évènements (boucle principale) :
    fen.mainloop()

  9. #9
    Membre éprouvé
    Homme Profil pro
    Aucune activité
    Inscrit en
    Novembre 2011
    Messages
    505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Aucune activité

    Informations forums :
    Inscription : Novembre 2011
    Messages : 505
    Points : 926
    Points
    926
    Par défaut
    Bonjour,
    Je ne suis pas un spécialiste, mais…
    - lors de la création, c'est une bonne idée que d'utiliser une liste, cependant, pourquoi ne pas s'en servir dès que cela est possible?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    oval[0] = can1.create_oval(x[0],y[0],x[0]+30,y[0]+30,width=2,fill='red')
    oval[1] = can1.create_oval(x[1],y[1],x[1]+30,y[1]+30,width=2,fill='blue')
    oval[2] = can1.create_oval(x[1],y[1],x[1]+30,y[1]+30,width=2,fill='yellow')
    pourquoi pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    coul = ["red", "blue", "yellow"]
    for i in range(len(oval)):
        oval[i] = can1.create_oval(x[i],y[i],x[i]+30,y[i]+30,width=2,fill=coul[i])
    (qui de plus éviterait la petite erreur sur les indices de position)
    Idem pour les déclarations de valDis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for i in range(len(valDis)):
        valDis[i] = Label(fen, text="Distance" + str(i))
        valDis[i].pack()
    Idem pour les radiobutton (et pourquoi sauvegarder tous les noms s'ils ne sont pas réutilisés?)

    D'autre part:
    Je préfère:
    De même, à la place de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        while i<len(di):
            if i != n.get():
                valDis[i].configure(text="Distance "+str(i) +"= " +str(di[i]))
                print(x) # test
            i=i+1
    je préfère:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        for i in range(len(di)):
            if not i == rond:
                valDis[i].configure(text = "Distance " + str(i) + "= " + str(di[i]))
                print(x)
    Le formatage des distances serait, sans doutes, plus agréable si le nombre de chiffres significatifs était constant… Et alignés à droite, non?
    Enfin, je lancerais l'affichage des distances dès la création des labels (oui, cela implique une petite fonction qui serait réutilisée dans la fonction "pointeur)!!
    Sinon… Pourquoi ne pas regrouper les listes x et y dans une liste coords? (coords = [[0, 100], [100, 100], [200, 100]] ou [(…), (…), (…)]
    Voire regrouper aussi toutes les données correspondant à un objet "oval" dans une même petite structure, le tout contenu dans une liste… Ou un tuple!! ou encore dans un dictionnaire??

    En dernier, et pour l'aspect utilisateur, un clic de souris déterminant la position haut, gauche du carré contenant le rond, me semble améliorable (simplement).
    [puisque les ronds font 30 de diamètre, il suffit lors de la récupération de la position du curseur, de modifier (x, y) en conséquence. i.e.: leur ôter 15]

    Voilà… Bon courage (mais ce n'est pas si compliqué)!!
    Clodion
    PS: Il est généralement plus aisé de faire des modifications lorsque les choses sont bien séparées. Ce serait bien, par exemple, de pouvoir faire un boucle sur la partie "d[0]=…, d[1]…". Cela permettrait de l'intégrer dans la suivante. Le gros avantage serait de simplifier énormément l'ajout de "oval" supplémentaire!!
    PS2: penser à mettre résolu!!

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Pour vous (dés)orienter en vous proposant quelques techniques utiles mais auxquelles on ne pense pas toujours:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    import tkinter as tk
    import itertools
    from math import sqrt
     
    balles = {
        'red': [20, 100],
        'blue': [ 100, 100 ],
        'yellow': [ 200, 100],
        }
     
    colors = list(balles.keys())
    current_color = colors[0]
    combinations = list(itertools.combinations(colors, 2))
     
    def create_balle(x, y, color, R=15):
        return canvas.create_oval(x-R, y-R, x+R, y+R,
                                  fill=color, tag=color)
     
    def balle_moveto(balle, x, y):
        x0, y0 = balles[balle]
        dx, dy = x-x0, y-y0
        canvas.move(balle, dx, dy)
        balles[balle] = [ x, y ]
     
    def distance(a, b):
        return sqrt( (b[0]-a[0])**2 + (b[1]-a[1])**2 )
     
    def update_distances(all=False):
        frame = app.children.get('distances')
        for a, b in combinations:
            if all or current_color in (a, b):
                d = distance(balles[a], balles[b])
                print (a, b, d)
                label = frame.children.get('%s_%s' % (a, b))
                label['text'] = str(d)
     
    def on_mb1_click(x, y, color):
        balle_moveto(color, x, y)
        update_distances()
     
     
    app = tk.Tk()
     
    selected_color = tk.IntVar()
     
    canvas = tk.Canvas(app, bg='dark grey',height=300,width=300)
    for color, (x, y) in balles.items():
        create_balle(x, y, color)
    canvas.bind('<1>', lambda e: on_mb1_click(e.x, e.y, colors[selected_color.get()])
    canvas.pack()
     
    frame = tk.Frame(app, name="distances")
    for ix, (a, b) in enumerate(combinations):
        tk.Label(frame, text='%s <-> %s' % (a, b)).grid(row=ix, column=0) 
        tk.Label(frame, name='%s_%s' % (a, b)).grid(row=ix, column=1) 
    frame.pack()
    update_distances(all=True)
     
    frame = tk.Frame(app)
    for ix, color in enumerate(colors):
        btn = tk.Radiobutton(frame, text=color, 
                       variable=selected_color, 
                       value=ix)
        btn.grid(row=ix)
    btn = frame.grid_slaves(row=colors.index(current_color))[0]
    btn.select()
    tk.mainloop()
    - W
    edit: ajout d'une demo sur grid_slaves + une utilisation un peu sioux callback du bind.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Membre régulier
    Homme Profil pro
    Technicien
    Inscrit en
    Février 2010
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Février 2010
    Messages : 59
    Points : 113
    Points
    113
    Par défaut
    Super!
    Bon, beaucoup de choses me passent loin au dessus du crane, mais je me garde ça dans un coin au chaud.
    Je ne comprends pas la différence entre :

    di=[0,0,0]
    et
    di = [0] * 3


    Pour le reste merci.

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par loncle Voir le message
    Bon, beaucoup de choses me passent loin au dessus du crane, mais je me garde ça dans un coin au chaud.
    Ca veut juste dire que vous êtes un homme heureux qui a encore plein de choses à apprendre.

    Citation Envoyé par loncle Voir le message
    Je ne comprends pas la différence entre :

    di=[0,0,0]
    et
    di = [0] * 3
    Dans les deux cas, di sera associé à une liste de 3 entiers égaux à 0.
    La différence est qu'en écrivant [0] * 3 on ouvre la porte à la construction d'une liste qui pourrait contenir 1, 2, 3, ... N.
    Pour forcer le trait, on pourrait écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    x=[0,100,200] # coordonnées initiales
    y=[100,100,100]
    count = len(x)
     
    oval = [0] * count
    di = [0] * count
    valDis = [0] * count
    Dans votre cas, çà ne sert pas trop mais c'est à mettre dans un coin pour y penser le jour où.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Python 3.X] Exercice Python Gérard Swinnen
    Par werkos dans le forum Général Python
    Réponses: 2
    Dernier message: 02/05/2015, 21h16
  2. Exercice 8.26 Swinnen
    Par loncle dans le forum Général Python
    Réponses: 1
    Dernier message: 08/08/2014, 09h16
  3. Probleme exercice de Gerard Swinnen 8.13
    Par elnabo dans le forum Tkinter
    Réponses: 5
    Dernier message: 23/03/2011, 10h44
  4. Obtenir la solution exercices du bouquin Swinnen
    Par rlejeune dans le forum Général Python
    Réponses: 1
    Dernier message: 26/08/2007, 04h53
  5. [cours de G.Swinnen] exercice 66
    Par airod dans le forum Tkinter
    Réponses: 4
    Dernier message: 14/10/2005, 11h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo