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 :

tkinter menus : pourquoi la commande est-elle exécutée au chargement du menu ? [Python 3.X]


Sujet :

Tkinter Python

  1. #1
    Membre régulier

    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Janvier 2010
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2010
    Messages : 120
    Points : 120
    Points
    120
    Billets dans le blog
    1
    Par défaut tkinter menus : pourquoi la commande est-elle exécutée au chargement du menu ?
    Comme le bug précédent est résolu , je poursuis mon application qui consiste à afficher une boîte de dialogue quand on clique sur un menu.
    Mon problème : la boîte de dialogue s'affiche avant que le menu n'apparaisse . Puis ne s'affiche plus quand je clique sur le menu "New Task" .

    voir ligne 12 quand je crée le menu puis lignes 16 et 17 que j'ai commentées.

    Voici le 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
    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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    import tkinter as tk
     
    class View:
        def __init__(self, master):
            master.title("Dialog Box") # et non master.title = "Dialog Box" !!!
     
            #Menu
            self.mainMenu = tk.Menu(master, tearoff=False)
     
            #MenuTasks
            self.menuTasks = tk.Menu(self.mainMenu, tearoff=False)
            self.menuTasks.add_command(label='New Task', command=self.newTask(master))
            self.mainMenu.add_cascade(label="Tasks", menu=self.menuTasks)
            master.config(menu=self.mainMenu)
     
        def newTask(self, master):
            nt = dialogBoxNewTask(master, "New Task", offx=-50, offy=-100) # cette ligne semble s'exécuter quand on crée une instance de la classe View !?
                #Ensuite quand on clique sur le menu 'New task', la boîte de dialogue ne s'affiche plus...
     
     
    class DialogBox(tk.Toplevel):
        def __init__(self, container, title=None, offx=250, offy=250):
            tk.Toplevel.__init__(self, container)
            self.protocol("WM_DELETE_WINDOW", self.cancel)
            self.transient(container)
     
            self.title("New Task")
     
            self.container = container
            self.result = None
     
            frame = tk.Frame(self)
            self.initial_focus = self.packing(frame)
            frame.pack(padx=10, pady=10)
     
            focusDefault = self.buttons()
     
            self.grab_set()
     
            if not self.initial_focus:
                self.initial_focus = focusDefault
     
            self.initial_focus.focus_set()
     
            self.wait_window(self)
     
        def packing(self, master):
            pass  # to be overloaded
     
        def buttons(self):
            buttonOK = tk.Button(self, text="OK", command=self.ok, default=tk.ACTIVE)
            buttonCancel = tk.Button(self, text="Cancel", command=self.cancel)
            buttonOK.pack(side=tk.LEFT, padx=5, pady=5)
            buttonCancel.pack(side=tk.LEFT, padx=5, pady=5)
     
            return buttonOK  # Pourquoi ??
     
        def ok(self, event=None):
            self.initial_focus.focus_set()
            self.withdraw()
            self.update_idletasks()
            self.apply()
            self.cancel()
     
        def cancel(self, event=None):
            self.container.focus_set()
            self.destroy()
     
        def apply(self):
            pass  # to be overloaded
     
     
    class dialogBoxNewTask(DialogBox):
        #je ne comprends pas pourquoi le tuto ne propose pas de constructeur :
        #def __init__(self, container, title=None, offx=250, offy=250):
            #DialogBox.__init__(self, container, title, offx, offy)
     
        def packing(self, master):
            tk.Label(master, text="Task :").grid (row=0, column=0)
            self.taskTask = tk.Entry(master)
            self.taskTask.grid(row=0, column=1)
            tk.Label(master, text="Due Date :").grid (row=0, column=2)
            self.taskDueDate = tk.Entry(master)
            self.taskDueDate.grid(row=0, column=3)
            return self.taskTask                             #Why ??
     
        def apply(self):
            self.result = "Result"
     
    class Controller:
        def __init__(self):
            self.root = tk.Tk()
            #self.model = Model()
            self.view = View(self.root)
     
        def run(self):
            self.root.mainloop()
     
    main = Controller()
    main.run()
    Merci d'avance...
    jdd deschamps
    RPL - VB6 - C# - Wordpress - Python3 - Xamarin

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 301
    Points : 6 781
    Points
    6 781
    Par défaut
    Salut,

    Lorsque tu écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            self.menuTasks.add_command(label='New Task', command=self.newTask(master))
    tu appelles newTask et command est le retour de cette fonction soit None.


    Garde une référence de ton master et utilise celle-ci dans ta fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        def newTask(self):
            nt = dialogBoxNewTask(self.master, "New Task", offx=-50, offy=-100)

  3. #3
    Membre régulier

    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Janvier 2010
    Messages
    120
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2010
    Messages : 120
    Points : 120
    Points
    120
    Billets dans le blog
    1
    Par défaut résolu
    Merci @VinsS

    code corrigé :
    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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    import tkinter as tk
     
    class View:
        def __init__(self, master):
            master.title("Dialog Box") # et non master.title = "Dialog Box" !!!
     
            # IL FAUT AJOUTER CELA :
            self.master = master
     
            #Menu
            self.mainMenu = tk.Menu(master, tearoff=False)
     
            #MenuTasks
            self.menuTasks = tk.Menu(self.mainMenu, tearoff=False)
            self.menuTasks.add_command(label='New Task', command=self.newTask)     # et non self.newTask(master)) !!!
            self.mainMenu.add_cascade(label="Tasks", menu=self.menuTasks)
            master.config(menu=self.mainMenu)
     
        def newTask(self):
            nt = dialogBoxNewTask(self.master, "New Task", offx=-50, offy=-100) # cette ligne semble s'exécuter quand on crée une instance de la classe View !?
                #Ensuite quand on clique sur le menu 'New task', la boîte de dialogue ne s'affiche plus...
     
     
    class DialogBox(tk.Toplevel):
        def __init__(self, container, title=None, offx=250, offy=250):
            tk.Toplevel.__init__(self, container)
            self.protocol("WM_DELETE_WINDOW", self.cancel)
            self.transient(container)
     
            self.title("New Task")
     
            self.container = container
            self.result = None
     
            frame = tk.Frame(self)
            self.initial_focus = self.packing(frame)
            frame.pack(padx=10, pady=10)
     
            focusDefault = self.buttons()
     
            self.grab_set()
     
            if not self.initial_focus:
                self.initial_focus = focusDefault
     
            self.initial_focus.focus_set()
     
            self.wait_window(self)
     
        def packing(self, master):
            pass  # to be overloaded
     
        def buttons(self):
            buttonOK = tk.Button(self, text="OK", command=self.ok, default=tk.ACTIVE)
            buttonCancel = tk.Button(self, text="Cancel", command=self.cancel)
            buttonOK.pack(side=tk.LEFT, padx=5, pady=5)
            buttonCancel.pack(side=tk.LEFT, padx=5, pady=5)
     
            return buttonOK  # Pourquoi ??
     
        def ok(self, event=None):
            self.initial_focus.focus_set()
            self.withdraw()
            self.update_idletasks()
            self.apply()
            self.cancel()
     
        def cancel(self, event=None):
            self.container.focus_set()
            self.destroy()
     
        def apply(self):
            pass  # to be overloaded
     
     
    class dialogBoxNewTask(DialogBox):
        #je ne comprends pas pourquoi le tuto ne propose pas de constructeur :
        #def __init__(self, container, title=None, offx=250, offy=250):
            #DialogBox.__init__(self, container, title, offx, offy)
     
        def packing(self, master):
            tk.Label(master, text="Task :").grid (row=0, column=0)
            self.taskTask = tk.Entry(master)
            self.taskTask.grid(row=0, column=1)
            tk.Label(master, text="Due Date :").grid (row=0, column=2)
            self.taskDueDate = tk.Entry(master)
            self.taskDueDate.grid(row=0, column=3)
            return self.taskTask                             #Why ??
     
        def apply(self):
            self.result = "Result"
     
    class Controller:
        def __init__(self):
            self.root = tk.Tk()
            #self.model = Model()
            self.view = View(self.root)
     
        def run(self):
            self.root.mainloop()
     
    main = Controller()
    main.run()
    jdd deschamps
    RPL - VB6 - C# - Wordpress - Python3 - Xamarin

  4. #4
    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 778
    Points
    36 778
    Par défaut
    Salut,

    Citation Envoyé par jdddeschamps Voir le message
    Mon problème : la boîte de dialogue s'affiche avant que le menu n'apparaisse . Puis ne s'affiche plus quand je clique sur le menu "New Task" .
    La question est de savoir lorsqu'une fonction g prend une autre fonction en paramètre comment forcer le paramètre de la fonction appelée:
    On a 'g'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> def g(func):
    ...     print('call func')
    ...     func()
    ...
    on a "f":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> def f(param):
    ...     print(param)
    ...
    Et si on fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> g(func=f('aaaa'))
    aaaa
    call func
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in g
    TypeError: 'NoneType' object is not callable
    >>>
    Ce n'est pas une fonction à appeler qu'on passe à g mais son résultat.

    Il y a plusieurs solutions qui consistent toutes à créer un nouvel objet fonction:
    "lambda":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> g(func=lambda s='aaa': f(s))
    call func
    aaa
    "closure":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> def closure(f, *args):
    ...     def callit():
    ...         return f(*args)
    ...     return callit
    ...
    >>> g(func=closure(f, 'xxx'))
    call func
    xxx
    __call__:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> class C:
    ...     def __init__(self, f, *args):
    ...         self.values = (f, args)
    ...     def __call__(self):
    ...         f, args = self.values
    ...         return f(*args)
    ...
    >>> g(func=C(f, 'xxx'))
    call func
    xxx
    >>>
    mais on peut aussi contourner le problème...

    - 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. Pourquoi cette variable est-elle vide ?
    Par yann18 dans le forum Langage
    Réponses: 2
    Dernier message: 14/03/2008, 10h36
  2. Réponses: 4
    Dernier message: 23/04/2007, 22h46
  3. Réponses: 3
    Dernier message: 04/03/2007, 09h34
  4. [8086] Pourquoi la taille de segment est-elle de 64 ko ?
    Par gza.gza dans le forum Assembleur
    Réponses: 3
    Dernier message: 28/02/2007, 21h24
  5. Réponses: 1
    Dernier message: 17/10/2006, 15h05

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