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

Tkinter Python Discussion :

enregistrer mon interface graphique dans un dossier


Sujet :

Tkinter Python

  1. #1
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2012
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2012
    Messages : 39
    Par défaut enregistrer mon interface graphique dans un dossier
    Bonjour à tous.
    J'essaye de trouver comment je pourrais enregistrer mon interface graphique (pas la page de code mais la fenêtre avec les bouttons etc) dans un dossier.
    J'ai chercher ce weekend et toute cette journée mais en vain et çà commence à me décourager.

    Voici mon code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    button=tkinter.Button(self,bg='violet',text='Sauvegarder') #création d'un bouton pour sauvegarder
            button.grid(column=0, row=30) #emplacement du bouton
            button.bind('<Button-1>',self.enregistre) # on associe le fait d'appuyer sur le bouton à la méthode sauvegarder
     
    def sauvegarder(mesFormats,interface): #création de la méthode sauvegarder
            import tkinter.filedialog #on importe le module nécessaire pour enregistrer qqch
            mesFormats = [('python','*.py'),('Document Microsoft Word','*.org'),('OpenOffice','*.docx'),('JPEG / JFIF','*.jpg'),('CompuServer GIF','*.gif')] #on choisis les formats de fichiers
            root=tkinter.tk()
            nomFichier=tkinter.filedialog.asksaveasfile(parent=root,filetypes=mesFormats,title="Sauvez l'image sous...")
     
     
            if len(nomFichier) > 0:
                print ("Sauvegarde en cours dans %s" % nomFichier)
    Le problème c'est que quand je clique sur le bouton sauvegarder j'ai bien une fenêtre qui s'ouvre pour enregistrer ma fenêtre mais après quand je ouvre le fichier, celui-ci est vide...

    D'où vient mon erreur??

  2. #2
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir,

    Je n'ai rien compris à votre code mais en gros c'est une copie partielle d'écran.
    Vu les extensions de fichiers je pense que vous devez être sous Windows et dans ce cas cela passe habituellement par PIL et ImageGrab (bbox >The bounding box argument can be used to copy only a part of the screen, Ce que vous retrouvez avec les winfo_* de tkinter).
    Souci: Vous programmez avec Python 3.x (tkinter et non Tkinter) et PIL n'est pas encore porté sous Python 3... Un exemple ici.
    Sauf d'installer une version 'pré' Python 3 de PIL je ne vois qu'une solution ce soir: Traduire ImageGrab pour Python 3 ou passer par l'api win32... Soit en gros jouer avec du code du style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def getpixelcolor(x, y):
        desktop_id = win32gui.GetDesktopWindow()
        desktop_dc = win32gui.GetWindowDC(desktop_id)
        long_colour = win32gui.GetPixel(desktop_dc, x, y)
        colour = int(long_colour)
        return (colour & 0xff), ((colour >> 8) & 0xff), ((colour >> 16) & 0xff)
    Pour parcourir la zone donnée par les winfo_* tkinter afin de recréer une image...
    Et là quel est le format le plus intéressent/simple ?

    Au fait :
    Pourquoi faire des copies d'écran à partir du code ?
    Que voulez vous en faire ? Impression, juste pour en garder un copie, etc...

    @+

  3. #3
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2012
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2012
    Messages : 39
    Par défaut
    Ah oui çà à l'air un peu galère de jouer avec du code comme çà.
    Je voulais faire une copie de l'interface graphique pour enregistrer les données que les utilisateurs auront mis dans les widgets entry.
    J'avais pensé à mettre tous les contenus des widgets dans un dictionnaire. Et mettre ceci dans un nouveau fichier qui sera enregistrer. Et à partir de ce fichier, regénérer l'interface graphique. J'ai créer mon interface graphique dans une classe nommée interface et que ma fonction pour sauvegarder est appelée quand l'utilisateur appuie sur la touche sauvegarder.
    Le problème est que quand j'essaye de lire mon dictionnaire dans ma fonction pour sauvegarder il me met ce message d'erreur:

    Exception in Tkinter callback
    Traceback (most recent call last):
    File "C:\Python32\lib\tkinter\__init__.py", line 1399, in __call__
    return self.func(*args)
    File "C:\Users\Desktop\interface_maison.py", line 518, in enregistre
    for i in dico:
    TypeError: 'Event' object is not iterable

    Voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    button=tkinter.Button(self,bg='violet',text='Sauvegarder') #création d'un bouton pour sauvegarder
            button.grid(column=0, row=30) #emplacement du bouton
            button.bind('<Button-1>',self.enregistre) # on associe le fait d'appuyer sur le bouton à la méthode sauvegarder
     
        def enregistre(self,dico):
     
            import tkinter.filedialog
            ofi=tkinter.filedialog.asksaveasfile(filetypes=[("Texte",".txt"),("Tous","*")])
            for i in dico:
                ofi.write("%s%s\n"%(clef,valeur))
                ofi.close()
    Je ne vois pas comment dire à python lit le contenu de dico et met le dans le nouveau fichier...
    Merci de votre aide

  4. #4
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir,

    Vous avez vraiment un gros souci avec bind et la portée des variables...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    button.bind('<Button-1>',self.enregistre) # on associe le fait d'appuyer sur le bouton à la méthode sauvegarder
     
        def enregistre(self,dico):
    .bind donne les information sur l’événement via la classe Event (déjà dit il me semble dans vos posts ... ) donc ce que reçoit 'enregistre' sous le nom de 'dico' c'est une instance de la classe Event Tkinter.
    A quel moment passez vous votre objet 'dico' ? Comment voulez vous que 'enregistre' connaisse 'dico' ?
    .........
    Vous allez droit au mur. Suivez un tuto. (Ce n'est pas de la mauvaise volonté mais il vous manque trop de bases et vous partez en électron libre)

    @+

  5. #5
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2012
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2012
    Messages : 39
    Par défaut
    Je cherche dans les tutoriels mais lequel me conseillez vous pour faire ce genre de chose????

  6. #6
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Il est coutume d'orienter le lecteur qui utilise Tkinter vers le tuto de Swinnen car celui ci aborde très vite Tkinter. Mais comme vous ne vous battez pas contre Tkinter (si ce n'est le .get() d'un de vos précédents post) mais contre Python je dirais qu'importe, du moment que vous accrochez.

    L'erreur qui reviens dans tous vos posts c'est que vous ne comprenez pas ce qui est visible dans une fonction. Pour résumer vous avez trois niveaux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Le niveau d'espace de nom global
    def Foo(les arguments):
        Le niveau d'espace de nom local
    En dehors de cela rien d'autre n'est visible (pour résumer) et une variable nommée 'dico' définie dans un autre espace de nom si elle n'est pas passer en argument ne le seras pas.
    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
    >>> a = 1 # Global
    >>> def Foo():
    ...     b = 0 # Local
    ... 
    >>> def foo1():
    ...     print(b) # b est une variable locale de Foo
    ... 
    >>> foo1() # Donc non visible dans Foo1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 2, in foo1
    NameError: global name 'b' is not defined
    >>> def foo1():
    ...     print(a) # a appartiens a l'espace de nom global de Foo1
    ... 
    >>> foo1() # donc cela 'fonctionne'
    1
    >>> def foo1(v): # Ici v est un argument
    ...     print(v)
    ... 
    >>> def foo2():
    ...     c = 2 # c est local
    ...     foo1(c) # mais on le donne en arguments
    ... 
    >>> foo2() # et cela 'fonctionne'
    2
    Vous allez me dire mais cela c'est les bases ? Oui.
    Là ou cela se complique c'est avec les classes car on y rajoute self: C'est quoi self ?
    3 Le premier argument de chaque méthode de classe, y compris __init__, est toujours une référence à l'instance actuelle de la classe. Par convention, cet argument est toujours nommé self. Dans la méthode __init__, self fait référence* à l'objet nouvellement créé, dans les autres méthodes de classe, il fait référence à l'instance dont la méthode a été appelée.
    Mais revenons en à votre code et considérons les bases sur les classes acquises.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            button.bind('<Button-1>',self.enregistre) # on associe le fait d'appuyer sur le bouton à la méthode sauvegarder
     
        def enregistre(self,dico):
    button.bind se trouve dans un bloc d'instructions ou vous devez (normalement) avoir une variable locale nommée 'dico'.
    def enregistre(self,dico): est la définition d'une fonction et cela commence un autre bloc d'instructions.
    On a donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def foo(self):
        # Espace de nom local de foo
        dico = {}
        button.bind('<Button-1>',self.enregistre)
    def enregistre(self):
        # Espace de nom local d'enregistre
        # Nous devons récupérer dico ici.
    La première difficulté c'est de savoir que .bind() donne en arguments à la fonction qui lui est donnée en callback (ici self.enregistre) une instance Event, contenant les informations sur ce qui a déclencher l'appel de la fonction, en argument.
    Une fois cela compris on en arrive à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def foo(self):
        # Espace de nom local de foo
        dico = {}
        button.bind('<Button-1>',self.enregistre)
    def enregistre(self, event):
        # Espace de nom local d'enregistre
        # Nous devons récupérer dico ici.
    Reste le cas de 'dico': Nous avons deux possibilités (de base).
    Soit nous passons en argument 'dico', soit celui ci est visible.

    Pour que dico soit 'visible' nous pouvons utiliser self pour en faire un attribut d'instance. Du moment ou nous aurons défini self.dico = 'dico' seras 'visible' de toute l'instance via self.dico.
    Cela donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def foo(self):
        # Espace de nom local de foo
        self.dico = {}
        button.bind('<Button-1>', self.enregistre)
    def enregistre(self, event):
        # Espace de nom local d'enregistre
        # Nous récupérer self.dico ici.
    La question est, avons nous besoin de self.dico dans toute notre instance ?
    La difficulté est que self.dico doit être 'défini' avant d'y faire référence (dans __init__ par exemple).

    Pour passer 'dico' en argument nous pouvons utiliser la fonction donnée à .bind()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def foo(self):
        # Espace de nom local de foo
        dico = {}
        button.bind('<Button-1>', self.enregistre(dico))
    def enregistre(self, event, dico):
        # Espace de nom local d'enregistre
        # Nous devons récupérer dico ici.
    Sauf le code ci dessus ne fonctionneras pas.
    Pourquoi ? Tout simplement du fait de self.enregistre(dico). A la lecture de ce code Python interpréteras self.enregistre(dico) et le remplaceras par que retourne la fonction self.enregistre, soit, si cela n'est pas explicitement signifier par un return quelquechose dans la fonction, None. En fait cela donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    button.bind('<Button-1>', None)
    Ballot non ?
    Comment s'en sortir ? Avec une fonction lambda.
    Cela donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def foo(self):
        # Espace de nom local de foo
        dico = {}
        button.bind('<Button-1>', lambda evt, dico: self.enregistre(evt, dico))
    def enregistre(self, event, dico):
        # Espace de nom local d'enregistre
        # Nous récupère dico en argument.
    La fonction lambda ne sera évaluée (()) que lors de l’événement. Elle reçoit de bind l'instance Event (Ici evt. Qu'importe le nom, seul le contenu compte) et on lui donne en second argument 'dico'.
    Pourquoi ne pas écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    button.bind('<Button-1>', lambda: self.enregistre(evt, dico))
    ?
    Pour la bonne raison que bind donne l'instance en argument à la fonction lambda, d’où lambda arguments:.

    Maintenant le sujet de votre post.
    Un exemple simple:
    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
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    #
    #
    import sys
    running_python3 = sys.version_info[0] > 2
    if running_python3:
          import tkinter
          import tkinter.filedialog as tkfiledialog
    else:
          import Tkinter as tkinter
          import tkFileDialog as tkfiledialog
     
     
    class Demo(tkinter.Tk):
        def __init__(self):
            tkinter.Tk.__init__(self)
            pkvalues = {'padx': 5, 'pady': 5, 'ipadx': 2,
                        'ipady': 2, 'fill': 'both'}
            self.e1 = tkinter.Entry(self)
            self.e2 = tkinter.Entry(self)
            self.e3 = tkinter.Entry(self)
            self.e4 = tkinter.Entry(self)
            self.e1.pack(pkvalues)
            self.e2.pack(pkvalues)
            self.e3.pack(pkvalues)
            self.e4.pack(pkvalues)
            tkinter.Button(self, text='Read',
                           command=self.readconfig).pack(pkvalues)
            tkinter.Button(self, text='Write',
                           command=self.writeconfig).pack(pkvalues)
            self.file_opt = options = {}
            options['defaultextension'] = ''
            options['filetypes'] = [('all files', '.*'), ('config files', '.cfg')]
            options['initialfile'] = 'conf.cfg'
            options['parent'] = self
            options['title'] = 'Configuration'
            self.widgets = (self.e1, self.e2, self.e3, self.e4)
     
        def readconfig(self):
            conffile = tkfiledialog.askopenfile(mode='r', **self.file_opt)
            if conffile:
                for l in conffile.readlines():
                     v = l.split()
                     t = v[1]
                     w = self.widgets[int(v[0])]
                     if t == 'None':
                         t = ''
                     w.delete(0, tkinter.END)
                     w.insert(0, t)
     
        def writeconfig(self):
            conffile = tkfiledialog.asksaveasfilename(**self.file_opt)
            if conffile:
                with open(conffile, 'w') as f:
                    for i, w in enumerate(self.widgets):
                        val = w.get()
                        if val == '':
                            val = 'None'
                        f.write("%d %s\n" % (i, val))
     
    if __name__ == "__main__":
        root = Demo()
        root.mainloop()
    Pour simplifier la chose nous utilisons ici un simple fichier texte pour conserver les valeurs des Entry. Il existe des modules pour cela.
    Vu vos autres posts vous allez me dire 'cela ne me vas pas car j'utilise for pour créer mes Widgets et je n'en garde pas la référence sous Python'.
    C'est de cela dont je vous mets en garde depuis un moment en fait.
    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
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    #
    #
    import sys
    running_python3 = sys.version_info[0] > 2
    if running_python3:
          import tkinter
          import tkinter.filedialog as tkfiledialog
    else:
          import Tkinter as tkinter
          import tkFileDialog as tkfiledialog
     
     
    class Demo(tkinter.Tk):
        def __init__(self):
            tkinter.Tk.__init__(self)
            pkvalues = {'padx': 5, 'pady': 5, 'ipadx': 2,
                        'ipady': 2, 'fill': 'both'}
     
            self.widgets = []
            for i in range(4):
                e = tkinter.Entry(self)
                e.pack(pkvalues)
                self.widgets.append(e)
     
            tkinter.Button(self, text='Read',
                           command=self.readconfig).pack(pkvalues)
            tkinter.Button(self, text='Write',
                           command=self.writeconfig).pack(pkvalues)
            self.file_opt = options = {}
            options['defaultextension'] = ''
            options['filetypes'] = [('all files', '.*'), ('config files', '.cfg')]
            options['initialfile'] = 'conf.cfg'
            options['parent'] = self
            options['title'] = 'Configuration'
     
        def readconfig(self):
            conffile = tkfiledialog.askopenfile(mode='r', **self.file_opt)
            if conffile:
                for l in conffile.readlines():
                     v = l.split()
                     t = v[1]
                     w = self.widgets[int(v[0])]
                     if t == 'None':
                         t = ''
                     w.delete(0, tkinter.END)
                     w.insert(0, t)
     
        def writeconfig(self):
            conffile = tkfiledialog.asksaveasfilename(**self.file_opt)
            if conffile:
                with open(conffile, 'w') as f:
                    for i, w in enumerate(self.widgets):
                        val = w.get()
                        if val == '':
                            val = 'None'
                        f.write("%d %s\n" % (i, val))
     
    if __name__ == "__main__":
        root = Demo()
        root.mainloop()
    @+

    *
    Note rapide: Cette référence est toujours présente
    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
    >>> class C:
    ...     def __init__(self):
    ...         pass
    ...     def foo():
    ...         print('foo')
    ... 
    >>> c = C()
    >>> c.foo()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: foo() takes no arguments (1 given)
    >>> class C:
    ...     def __init__(self):
    ...         pass
    ...     def foo(*args):
    ...         print(args)
    ... 
    >>> c = C()
    >>> c.foo()
    (<__main__.C instance at 0xb76d2e6c>,)
    Il n'y a pourtant pas d'argument pour foo, mais Python le rajoute de lui 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
    >>> class C:
    ...     def __init__(self):
    ...         foo()
    ...     def foo(self):
    ...         print('foo')
    ... 
    >>> c = C()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in __init__
    NameError: global name 'foo' is not defined
    >>> class C:
    ...     def __init__(self):
    ...         self.foo()
    ...     def foo(self):
    ...         print('foo')
    ... 
    >>> c = C()
    foo

Discussions similaires

  1. Problème d'insertion d'images dans mon interface graphique
    Par nini_python dans le forum Tkinter
    Réponses: 8
    Dernier message: 03/08/2012, 19h59
  2. Quel langage pour mon interface graphique.
    Par Kafiland dans le forum Choisir un environnement de développement
    Réponses: 5
    Dernier message: 22/03/2007, 21h48
  3. Réponses: 10
    Dernier message: 15/05/2006, 10h57
  4. quel langage choisir pour mon interface graphique
    Par mrom34 dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 09/03/2004, 19h12

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