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 :

Bouton avec une fonction ayant en argument une autre fonction


Sujet :

Python

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 12
    Points : 13
    Points
    13
    Par défaut Bouton avec une fonction ayant en argument une autre fonction
    Bonjour,
    Je cherche à coder avec tkinter un bouton ayant pour commande une fonction avec comme argument une variable faisant référence à une fonction importée depuis un fichier extérieur.
    Voilà ce que ça donne:
    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
    from tkinter import *
    from PIL import Image,ImageTk
    from operations_image import *
     
     
    def ouvrir(event):
        photo=Image.open(entree.get())
        dico_image['photo']= photo
        (L,H)=photo.size
        can.configure(width=L, height=H)
        photo_tk = ImageTk.PhotoImage(photo) 
        dico_image['photo tk'] = photo_tk
        can.delete(fen,ALL)
        can.create_image(L//2,H//2,image =photo_tk)
        can.pack(side=RIGHT)
     
    def traitement(operation):
        traite=photo.operation
        dico_image['photo traitée']=traite
        traite_tk=ImageTk.PhotoImage(traite)
        dico_image['photo traitée tk']
        can.delete(fen,ALL)
        can.create_image(L//2,H//2,image=traite_tk)
     
     
     
    fen=Tk()
    can=Canvas(fen, width =5, height =5)
    dico_image = {}
     
    entree=Entry(fen)
    entree.bind('<Return>',ouvrir)
    entree.pack()
     
     
    Button(fen,text='Filtre rouge',command=traitement(filtrerouge(photo,L,H))).pack(side=RIGHT)
     
    fen.mainloop()
    Avec comme fonction importée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Traitement(object):
     
        def filtrerouge(self,image,Longueur,Hauteur):
            "Filtre ne laissant passer que le rouge"
            self.filtrerouge=Image.new('RGB', (Longueur,Hauteur))
            for x in range(Longueur):
                for y in range (Hauteur):
                    p=image.getpixel((x,y))
                    self.filtrerouge.putpixel((x,y), (p[0],0,0))
            return self.filtrerouge
    Et j'ai comme message d'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Traceback (most recent call last):
      File "C:\Users\HP\Documents\Prépa\PCSI\Informatique\Scripts\Projet traitement image\Traitement Image 2.0.py", line 47, in <module>
        Button(fen,text='Filtre rouge',comand=traitement(filtrerouge,photo,L,H)).pack(side=RIGHT)
    NameError: name 'filtrerouge' is not defined
    Quelqu'un pourrait-il m'aider s'il-vous-plaît ? Je pédale dans la semoule depuis un petit bout de temps

  2. #2
    Expert éminent

    Avatar de deusyss
    Homme Profil pro
    Expert Python
    Inscrit en
    Mars 2010
    Messages
    1 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Expert Python
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 659
    Points : 8 442
    Points
    8 442
    Par défaut
    Bonjour,

    afin de t'aider au mieux pourrais tu nous indiquer la version de python utilisée, l'OS, et pour le code donné, pourrais tu nous donné le nom de chaque fichier (<nom>.py). Pour l'instant, on ne peux pas identifier la façon dont le tout est importer.

    EDIT: Pourrais tu aussi nous mettre le code de C:\Users\HP\Documents\Prépa\PCSI\Informatique\Scripts\Projet traitement image\Traitement Image 2.0.py, car l'erreur vient de ce fichier, mais tu en nous l'a pas communiquer.

    Merci beaucoup.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 12
    Points : 13
    Points
    13
    Par défaut
    Mon ordi tourne sous Windows 7 64 bits, et j'utilise python 3.3.4
    Voilà Traitement Image 2.0.py (J'ai modifié légèrement, j'ai vu des erreurs que j'ai corrigé moi-même):
    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
    from tkinter import *
    from PIL import Image,ImageTk
    from operations_image import *
     
     
    def ouvrir(event):
        photo=Image.open(entree.get())
        dico_image['photo']= photo
        (L,H)=photo.size
        can.configure(width=L, height=H)
        photo_tk = ImageTk.PhotoImage(photo) 
        dico_image['photo tk'] = photo_tk
        can.delete(fen,ALL)
        can.create_image(L//2,H//2,image =photo_tk)
        can.pack(side=RIGHT)
     
    def traitement(operation):
        new=Traitement()
        traite=new.operation
        dico_image['photo traitée']=traite
        traite_tk=ImageTk.PhotoImage(traite)
        dico_image['photo traitée tk']
        can.delete(fen,ALL)
        can.create_image(L//2,H//2,image=traite_tk)
     
     
     
    fen=Tk()
    can=Canvas(fen, width =5, height =5)
    dico_image = {}
     
    entree=Entry(fen)
    entree.bind('<Return>',ouvrir)
    entree.pack()
     
     
    Button(fen,text='Filtre rouge',command=traitement(filtrerouge(photo,L,H))).pack(side=RIGHT)
     
    fen.mainloop()
    J'avais donné le message d'erreur d'une version antérieur, cependant le message d'erreur reste le même :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Traceback (most recent call last):
      File "C:\Users\HP\Documents\Prépa\PCSI\Informatique\Scripts\Projet traitement image\Traitement Image 2.0.py", line 37, in <module>
        Button(fen,text='Filtre rouge',command=traitement(filtrerouge(photo,L,H))).pack(side=RIGHT)
    NameError: name 'filtrerouge' is not defined
    Et voilà opérations_image.py :
    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
    class Traitement(object):
     
        def filtrerouge(self,image,Longueur,Hauteur):
            "Filtre ne laissant passer que le rouge"
            self.filtrerouge=Image.new('RGB', (Longueur,Hauteur))
            for x in range(Longueur):
                for y in range (Hauteur):
                    p=image.getpixel((x,y))
                    self.filtrerouge.putpixel((x,y), (p[0],0,0))
            return self.filtrerouge
     
        def filtrevert(self,image,Longueur,Hauteur):
            "Filtre ne laissant passer que le vert"
            self.filtrevert=Image.new('RGB', (Longueur,Hauteur))
            for x in range(Longueur):
                for y in range (Hauteur):
                    p=image.getpixel((x,y))
                    self.filtrevert.putpixel((x,y), (0,p[1],0))
            return self.filtrevert
     
        def filtrebleu(self,image,Longueur,Hauteur):
            "Filtre ne laissant passer que le bleu"
            self.filtrebleu=Image.new('RGB', (Longueur,Hauteur))
            for x in range(Longueur):
                for y in range (Hauteur):
                    p=image.getpixel((x,y))
                    self.filtrebleu.putpixel((x,y), (0,0,p[2]))
            return self.filtrebleu
     
    from PIL import Image
    Je veux avoir la possibilité d'utiliser différentes fonctions d'opération sur les images avec la fonction traitement, en fait.
    Merci à vous.

  4. #4
    Expert éminent

    Avatar de deusyss
    Homme Profil pro
    Expert Python
    Inscrit en
    Mars 2010
    Messages
    1 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Expert Python
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 659
    Points : 8 442
    Points
    8 442
    Par défaut
    Salut !!!

    Alors je comprend l'erreur. Ligne 37, quand tu effectue ton appel, tu dis d'utiliser la fonction filtrerouge. Hors au moment de l'appel, comme tu n'as pas encore créé d'objet Traitement, la fonction filtrerouge n'est pas connue.

    Pour y palier, je te proposerais plutot ce qui suit:
    =>L37, effectuer l'appel de la façon suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Button(fen,text='Filtre rouge',command=traitement("filtrerouge",photo,L,H)).pack(side=RIGHT)
    =>De definir ta fonction traitement ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def traitement(operation,image,Longueur,Hauteur):
        new=Traitement()
        if operation == "filtrerouge":
    		traite=new.filtrerouge(image,Longueur,Hauteur)
    	elif operation == "filtrebleu":
    		traite=new.filtrebleu(image,Longueur,Hauteur)
    	elif operation == "filtrevert":
    		traite=new.filtrevert(image,Longueur,Hauteur)
     
        dico_image['photo traitee']=traite
        traite_tk=ImageTk.PhotoImage(traite)
        dico_image['photo traitee tk']
        can.delete(fen,ALL)
        can.create_image(L//2,H//2,image=traite_tk)
    en tout donc:
    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
    from Tkinter import *
    from PIL import Image, ImageTk
    from operations_image import *
     
     
    def ouvrir(event):
        photo=Image.open(entree.get())
        dico_image['photo']= photo
        (L,H)=photo.size
        can.configure(width=L, height=H)
        photo_tk = ImageTk.PhotoImage(photo) 
        dico_image['photo tk'] = photo_tk
        can.delete(fen,ALL)
        can.create_image(L//2,H//2,image =photo_tk)
        can.pack(side=RIGHT)
     
    def traitement(operation,image,Longueur,Hauteur):
        new=Traitement()
        if operation == "filtrerouge":
            traite=new.filtrerouge(image,Longueur,Hauteur)
        elif operation == "filtrebleu":
            traite=new.filtrebleu(image,Longueur,Hauteur)
        elif operation == "filtrevert":
            traite=new.filtrevert(image,Longueur,Hauteur)
     
        dico_image['photo traitee']=traite
        traite_tk=ImageTk.PhotoImage(traite)
        dico_image['photo traitee tk']
        can.delete(fen,ALL)
        can.create_image(L//2,H//2,image=traite_tk)
     
     
     
    if __name__ == "__main__":
    	fen=Tk()
    	can=Canvas(fen, width =5, height =5)
    	dico_image = {}
     
    	entree=Entry(fen)
    	entree.bind('<Return>',ouvrir)
    	entree.pack()
     
     
    	Button(fen,text='Filtre rouge',command=traitement("filtrerouge",photo,L,H)).pack(side=RIGHT)
     
    	fen.mainloop()

    De cette façon, ton bug lié à filte rouge disparait. Il ne te reste plus qu'à chercher pour les bugs suivant lié à l'IHM. L'erreur est toujours dans la meme veine. Utilisation de variable avant déclaration.

    Une dernière chose, dans operations_image.py, l'import, il est preferable de le mettre en tout debut de code, par convention

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 12
    Points : 13
    Points
    13
    Par défaut
    Merci beaucoup !
    Je comprends l'astuce, cependant j'ai à présent comme message d'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Traceback (most recent call last):
      File "C:\Users\HP\Documents\Prépa\PCSI\Informatique\Scripts\Projet traitement image\Traitement Image 2.0.py", line 44, in <module>
        Button(fen,text='Filtre rouge',command=traitement("filtrerouge",photo,L,H)).pack(side=RIGHT)
    NameError: name 'photo' is not defined
    Je ne vois comme solution que de créer au départ une variable photo avec quelque chose sans importance dedans, mais auriez vous une autre idée ?
    J'ai aussi une autre question : à quoi sert le if __name__ == "__main__": ? Je l'ai déjà remarqué dans différent programmes mais sans jamais comprendre son utilité ....

  6. #6
    Expert éminent

    Avatar de deusyss
    Homme Profil pro
    Expert Python
    Inscrit en
    Mars 2010
    Messages
    1 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Expert Python
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 659
    Points : 8 442
    Points
    8 442
    Par défaut
    Salut!!

    Tres bonne question jeune padawan.

    Alors toute variable encadré par des doubles underscore(__), en python, est une variable environnement python (pour faire simple). Par exemple, quand tu abordera les classe en python, tu verra __init__ pour le code a executé à la creation de l'objet ou encore __del__ pour sa suppression.

    Dans notre cas il s'agit de __name__. Cette variable est importante en python. Si tu execute un module en direct (python <mon_module>.py), alors __name__ vaut "__main__".Si tu effectue un import de ce mêm module dans un autre code python, __name__ ne vaudra pas "__main__".

    if __name__ == "__main__": sert ainsi à savoir si on execute un code en direct ou non. Par convention, un code bien conçu sera toujours codé avec cette ligne, même s'il s'agit d'un tout petit script tel que le tient.

    Si on reprend l'exemple au dessus, ou on importe le module dans un autre code, cette fonction pourra permettre un test rapide. Je m'explique. Quand tu lancera le module en direct, tu pourra ainsi demander à tester une/plusieurs fonction(s) de ton code avec des valeurs type (par exemple). Lors d'un import, ces tests ne seront pas effectués. Tu peux ainsi effectuer des modifications et voir aisément leur résultat.

    J'espère que cela est un peu plus clair, sinon n'hesite pas, je tacherais de re expliquer en mieux.

    Sinon, l'erreur que tu indique, je l'ai effectivement remarqué. Comme je l'ai indiqué dans mon post précédent, cela est le même type d'erreur qu'avant ou presque. Au moment ou tu t'en sert, il ne connaît pas la variables photo. Dans ce cas plusieurs solutions. Mais vu que tu commence à apprendre le python aparemment, on va se contenter de la version basique: utilisation de variable globale (explication complete ICI). Pour faire simple, une variable déclaré en global sera accessible et la même à travers tout ton code. Sinon on dira qu'elle est locale (ton cas actuel).

    Je t'ai modifié un peu ton code pour que tu voit mieux:
    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
    from Tkinter import *
    from PIL import Image, ImageTk
    from operations_image import *
     
    global photo, L, H, dico_image
    photo, L, H = 0, 0, 0
    dico_image = {}
     
    def ouvrir(event):
    	global photo, L, H, dico_image
    	photo=Image.open(entree.get())
    	dico_image['photo']= photo
    	(L,H)=photo.size
    	can.configure(width=L, height=H)
    	photo_tk = ImageTk.PhotoImage(photo) 
    	dico_image['photo tk'] = photo_tk
    	can.delete(fen,ALL)
    	can.create_image(L//2,H//2,image =photo_tk)
    	can.pack(side=RIGHT)
     
     
     
    def traitement(operation):
    	global photo, L, H, dico_image
    	new=Traitement()
    	if operation == "filtrerouge":
    		traite=new.filtrerouge(photo,L,H)
    	elif operation == "filtrebleu":
    		traite=new.filtrebleu(photo,L,H)
    	elif operation == "filtrevert":
    		traite=new.filtrevert(photo,L,H)
     
    	dico_image['photo traite']=traite
    	traite_tk=ImageTk.PhotoImage(traite)
    	dico_image['photo traite tk'] = traite_tk
    	can.delete(fen,ALL)
    	can.create_image(L//2,H//2,image=traite_tk)
     
     
    if __name__ == "__main__":
    	fen=Tk()
    	can=Canvas(fen, width =5, height =5)
    	dico_image = {}
     
    	entree=Entry(fen)
    	entree.bind('<Return>',ouvrir)
    	entree.pack()
     
    	Button(fen,text='Filtre rouge',command=traitement("filtrerouge")).pack(side=RIGHT)
     
    	fen.mainloop()
    Tu constatera qu'avec le mot clé "global", tes erreurs ont disparus. Par la suite tu verras qu'il est très mauvais d'utiliser global, car si une variable est globale, tu ne peux toujours savoir quelle partie de ton code à modifier la variable et le debuggage est donc complexifié. Mais tu verras cela plus tard. Je te l'indiquais juste pour info. Apprend à utiliser global en premier lieu.

    Je t'invite egalement à lire les PEP et le principe d'encodage/debut de code (tout est ICI). Cela te permettra ainsi d'utiliser un socle commun dans tes codes avec le reste de la communauté.

    A dispo si tu desires plus d'info

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 12
    Points : 13
    Points
    13
    Par défaut
    OK, je comprends très bien.
    Pour les variables globales j'avais déjà intégré le principe et que c'était peu recommandable (j'ai le bouquin Apprendre a programmer avec python3 de Swinen)
    Merci beaucoup pour ton aide !

    Petite dernière question, est-ce qu'on ne pourrait pas mettre dès le début du programme new=Traitement() ? Comme ça on pourrait entrer directement :
    Button(fen,text='Filtre rouge',command=traitement(filtrerouge(photo,L,H))).pack(side=RIGHT)

    Évitant ainsi les lourdeurs de la fonction traitement()

  8. #8
    Expert éminent

    Avatar de deusyss
    Homme Profil pro
    Expert Python
    Inscrit en
    Mars 2010
    Messages
    1 659
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Expert Python
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 659
    Points : 8 442
    Points
    8 442
    Par défaut
    C'est eventuellement envisageable en effet.

    Il ne faut pas oublier qu'il n'existe pas qu'une seule façon de coder. Ce que tu trouveras logique ou optimiser de ton côté ne sera pas vu tel que par un autre developpeur. Il faut aussi savoir s'adapter au besoin, très important. Si tu pense que cela ne genera ni le fonctionnement, ni le debuggage, que cela respecte les PEP, alors il n'y a aucune raison

    Toi seul decide de ton code.

    En plus du livre de Swinnen, qui reste une reference, je te recommande le mien (lien dans la signature), non pas pour l'apprentissage du python (tu as deja le livre de reference pour ça), mais pour la presentation/utilisation de module complementaire qui pourrais t'interesser ou t'etre utile. Ce n'est pas exhaustif, loin de là, mais ça peut depanner.

    A ta dispo si tu as d'autre questions

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 12
    Points : 13
    Points
    13
    Par défaut
    Super,
    Merci beaucoup pour toute ton aide et ta disponibilité !
    Merci aussi pour le bouquin : maintenant j'ai de quoi m'occuper

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

Discussions similaires

  1. [XL-2007] appel d'une fonction ayant comme argument l'objet Range
    Par boguista1985 dans le forum Macros et VBA Excel
    Réponses: 15
    Dernier message: 24/07/2011, 23h26
  2. Réponses: 24
    Dernier message: 26/08/2010, 23h34
  3. Réponses: 3
    Dernier message: 12/12/2008, 10h47
  4. Création d'une Prodédure ayant pour arguments les contrôles Data
    Par Blunet dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 23/06/2006, 10h55
  5. Réponses: 1
    Dernier message: 03/06/2006, 13h59

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