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 :

Widget ComboBox (demande d'avis)


Sujet :

Tkinter Python

  1. #1
    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 Widget ComboBox (demande d'avis)
    Bonjour,

    Dans le cadre d'éviter les imports d'autres bibliothèques je me fais mes petits widgets.
    Dans un souci d'avoir un code universel (principalement au niveau géométrie) je me permet de vous soumettre celui ci.

    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
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    try: from tkinter import *
    except: from Tkinter import *
     
    # Class TkComboBox
    # ComboBox en pur Tkinter
    #
    # Options:
    # width, height, border, background (bg) , foreground (fg), font, relief, cursor,
    # exportselection, selectbackgroun, selectforeground
    #
    # Methodes:
    # activate(int index)
    # focus_set()
    # focus()
    # curselection()
    # delete(ALL ou int)
    # start (int)
    # end (END ou int)
    # insert(index, valeur)
    # get()
    # pack(padx=int, pady=int, fill(X, Y, BOTH), expand=bool, side=LEFT, RIGHT, TOP, BOTTOM, CENTER)
    # grid(row=int, column=int, columnspan=int, rowspan=int, sticky=NSEW, padx=int, pady=int)
    # place(relheight=int, relwidth=int, relx=int, rely=int, width=int, height=int, anchor=NSEW, x=int, y=int)
    # config/configure(Option=Valeur)
    #
    class TkComboBox(Toplevel):
        listeobjets = []
     
        # Positionnement
        def widgetstate(self, event=None):
            # True : Visible
            # False : Cache la listbox
            self.geometry('+%d+%d'%(self.zoneselection.winfo_rootx(),self.zoneselection.winfo_rooty()))
            if self.valeur_widget_state == True:
                self.valeur_widget_state = False
                self.withdraw()
            elif self.valeur_widget_state == False:
                self.valeur_widget_state = True
                self.deiconify()
     
        # Gestionnaires de geometrie
        def pack(self, padx=None, pady=None, fill=None, expand=None, side=None):
            self.zoneselection.pack(padx=padx, pady=pady, fill=fill, expand=expand, side=side)
     
        def grid(self, row=None, column=None, columnspan=None, rowspan=None, sticky=None, padx=None, pady=None):
            self.zoneselection.grid(row=row, column=column, columnspan=columnspan, rowspan=rowspan, sticky=sticky, padx=padx, pady=pady)
     
        def place(self, relheight=None, relwidth=None, relx=None, rely=None, width=None, height=None, anchor=None, x=None, y=None):
            self.zoneselection.place(relheight=relheight, relwidth=relwidth, relx=relx, rely=rely, width=width, height=height, anchor=anchor, x=x, y=y)
     
        # Configuration
        def configure(self, **kw):
            for cle in kw:
                option=cle
                valeur=kw[cle]
                self.zoneselection[option]=valeur
                self.cache[option]=valeur
                self.selection[option]=valeur
     
        config=configure
     
        # Methodes
        def activate(self, index):
            self.selection.activate(index)
     
        def size(self):
            return self.selection.size()
     
     
        def focus(self):
            self.zoneselection.get_focus()
     
        def get_focus(self):
            self.zoneselection.get_focus()
     
        def curselection(self):
            return map(int, self.selection.curselection())[0]
     
        def delete(self, objet=None, start=None, end=None):
            if objet=='ALL':
                self.selection.delete(0, END)
            elif start == None and end == None:
                self.selection.delete(objet)
            else:
                self.selection.delete(start, end)
     
        def get(self):
            return self.zoneselection.get()
     
        def insert(self, start, objet):
            self.listeobjets.append(objet)
            self.selection.insert(start, objet)
            self.selection.select_set(0)
            self.zoneselection.delete(0, END)
            self.zoneselection.insert(0, self.selection.get(self.selection.curselection()))
            self.cache.delete(0, END)
            self.cache.insert(0, self.selection.get(self.selection.curselection()))
     
        def selectionner(self, event):
            def index(event):
                try:
                    self.zoneselection.delete(0, END)
                    self.zoneselection.insert(0, self.selection.get(self.selection.curselection()))
                    self.cache.delete(0, END)
                    self.cache.insert(0, self.selection.get(self.selection.curselection()))
                except:
                    pass
                self.widgetstate()
            self.selection.bind("<ButtonRelease-1>", index)
     
        # Init 
        def __init__(self, parent=None, width=None, border=1, background=None, foreground=None, fg=None, bg=None, font=None, relief=None, cursor=None, exportselection=None, selectbackgroun=None, selectforeground=None, height=None):
            Toplevel.__init__(self, parent, bd=0)
            self.withdraw()
            self.parent = parent
            self.zoneselection = Entry(parent, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackgroun=selectbackgroun, selectforeground=selectforeground, height=height, width=width, background=background, foreground=foreground)
            self.overrideredirect(1)
            self.transient()
            self.cache = Entry(self, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackgroun=selectbackgroun, selectforeground=selectforeground, height=height, width=width, background=background, foreground=foreground)
            self.cache.pack()
            self.listescroll = Scrollbar(self)
            self.listescroll.pack(side=RIGHT, fill=Y)
            self.selection = Listbox(self, yscrollcommand=self.listescroll.set, width=width-1, border=border, background=background, foreground=foreground, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackgroun=selectbackgroun, selectforeground=selectforeground, height=height)
            self.selection.pack(side=LEFT)
            self.listescroll.config(command=self.selection.yview)
            self.selection.bind("<ButtonPress-1>", self.selectionner)
            self.cache.bind("<ButtonPress-1>", self.widgetstate)
            self.zoneselection.bind("<ButtonPress-1>", self.widgetstate)
            self.valeur_widget_state = True
            self.widgetstate()
            self.parent.bind("<Unmap>", lambda event: self.withdraw())
            self.parent.bind("<Configure>", lambda event: self.withdraw())
            # Le widget ne disparait pas si une fenetre passe au premier plan.
            # A revoir.
            # self.bind("<Leave>", lambda event: self.withdraw())
     
    # Demo
    class test(Tk):
        def __init__(self):
            Tk.__init__(self)
            monexplication = """Sample: Tk.__init__(self)
            self.explication = Text(self, bg='white')
            self.explication.insert(END, monexplication)
            self.explication.pack(side=TOP)
            self.listeMini = TkComboBox(self, width=10, bg='black', fg='white')
            self.listeMini.pack(side=TOP, pady=20)
            self.listeMini.config(bg='white', fg='black')
            for index in range(0,100):
                self.listeMini.insert(index, index)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)"""
            self.explication = Text(self, bg='white')
            self.explication.insert(END, monexplication)
            self.explication.pack(side=TOP)
            self.listeMini = TkComboBox(self, width=10, bg='black', fg='white')
            self.listeMini.pack(side=TOP, pady=20)
            self.listeMini.config(bg='white', fg='black')
            for index in range(0,100):
                self.listeMini.insert(index, index)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)
     
    if __name__ == '__main__':
        app = test()
        app.mainloop()
    Tout avis est le bienvenu.

  2. #2
    Membre confirmé
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Par défaut
    hello ! j'ai fait le beta testeur.

    Voici les petits détails que j'ai remarqué :

    - dans ton code, il manque le 'd' à ton paramètre 'selectbackground'

    - si on déplace le root alors que la liste est développée, elle disparait (pas trop grave en soit) mais il faut cliquer ensuite 2 fois au lieu d'une pour la faire réapparaitre.

    - une bordure noire apparait dans l'Entry avec le cycle suivant :
    . bordure absente après les 1er et 4èmes clics dans l'entry
    . bordure présente après les 2èmes et 3èmes clics dans l'entry
    le mieux serait de faire apparaitre la bordure au 1er et 3ème clics

    - il y a un décalage (par modif du relief ?) de l'entry quand la liste est déroulée, que personnellement je ne trouve pas très esthétique.

    - plus embêtant : si on tape manuellement une chaine dans l'entry, puis qu'on sélectionne un élément dans la liste, et qu'enfin on clique plusieurs fois de suite dans l'entry, le pauvre ne sait plus quoi afficher : c'est alternativement l'élément choisi dans la liste quand elle est déroulée, et la chaine entrée manuellement quand la liste est masquée.

    Voilà, mon rôle s'arrête là car contrairement à toi quand tu me réponds, je ne suis pas en mesure de te donner les soluces

  3. #3
    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
    Merci spirzouf,

    Deux, trois trucs à revoir pour cet après midi donc, rien de bien grave

    Pour le décalage je pense que c'est la bd en pixel de la Scrollbar. Sous Linux j'aurais bien mis un -1 mais cela ne fonctionne pas sous win... A cadrer donc.

    Pour ce qui est du double clic et de la bordure je ne l'avais pas dans mon précédent code (du 04/02): Donc facile.

    Pour la valeur c'est normal, j'ai des ascendants courges par moment...

    'Y'a plus qu'a'

  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
    Bon, je n'ai pas eu le temps de tout voir cet après midi (c'est fou ce qu'il y a à faire le dimanche ^^) mais voici pour une bonne partie de tes remarques spirzouf.

    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
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    try: from tkinter import *
    except: from Tkinter import *
     
    # Class TkComboBox
    # ComboBox en pur Tkinter
    #
    # Options:
    # width, height, border, background (bg) , foreground (fg), font, relief, cursor,
    # exportselection, selectbackground, selectforeground
    #
    # Methodes:
    # activate(int index)
    # focus_set()
    # focus()
    # curselection()
    # delete(ALL ou int)
    # start (int)
    # end (END ou int)
    # insert(index, valeur)
    # get()
    # pack(padx=int, pady=int, fill(X, Y, BOTH), expand=bool, side=LEFT, RIGHT, TOP, BOTTOM, CENTER)
    # grid(row=int, column=int, columnspan=int, rowspan=int, sticky=NSEW, padx=int, pady=int)
    # place(relheight=int, relwidth=int, relx=int, rely=int, width=int, height=int, anchor=NSEW, x=int, y=int)
    # config/configure(Option=Valeur)
    # defaultvalue(int)
    #
    class TkComboBox(Toplevel):
        listeobjets = []
     
        # Positionnement
        def widgetstate(self, event=None):
            # True : Visible
            # False : Cache la listbox
            self.geometry('+%d+%d'%(self.zoneselection.winfo_rootx(),self.zoneselection.winfo_rooty()))
            if self.valeur_widget_state == True:
                self.valeur_widget_state = False
                self.withdraw()
            elif self.valeur_widget_state == False:
                self.valeur_widget_state = True
                self.deiconify()
     
        def reposition(self, event):
            self.valeur_widget_state = True
            self.withdraw()
     
        # Gestionnaires de geometrie
        def pack(self, padx=None, pady=None, fill=None, expand=None, side=None):
            self.zoneselection.pack(padx=padx, pady=pady, fill=fill, expand=expand, side=side)
     
        def grid(self, row=None, column=None, columnspan=None, rowspan=None, sticky=None, padx=None, pady=None):
            self.zoneselection.grid(row=row, column=column, columnspan=columnspan, rowspan=rowspan, sticky=sticky, padx=padx, pady=pady)
     
        def place(self, relheight=None, relwidth=None, relx=None, rely=None, width=None, height=None, anchor=None, x=None, y=None):
            self.zoneselection.place(relheight=relheight, relwidth=relwidth, relx=relx, rely=rely, width=width, height=height, anchor=anchor, x=x, y=y)
     
        # Configuration
        def configure(self, **kw):
            for cle in kw:
                option=cle
                valeur=kw[cle]
                self.zoneselection[option]=valeur
                self.cache[option]=valeur
                self.selection[option]=valeur
     
        config=configure
     
        # Methodes
        def activate(self, index):
            self.selection.activate(index)
     
        def size(self):
            return self.selection.size()
     
        def focus(self):
            self.zoneselection.get_focus()
     
        def get_focus(self):
            self.zoneselection.get_focus()
     
        def curselection(self):
            print map(int, self.selection.curselection())[0]
            return map(int, self.selection.curselection())[0]
     
        def delete(self, objet=None, start=None, end=None):
            if objet=='ALL':
                self.selection.delete(0, END)
            elif start == None and end == None:
                self.selection.delete(objet)
            else:
                self.selection.delete(start, end)
     
        def get(self):
            return self.zoneselection.get()
     
        def insert(self, start, objet):
            self.listeobjets.append(objet)
            self.selection.insert(start, objet)
            self.selection.select_set(0)
            self.v_zoneselection.set(objet)
            self.v_cache.set(objet)
     
        def selectionner(self, event):
            def index(event):
                self.selection.curselection()[0]
                self.v_zoneselection.set(self.selection.curselection()[0])
                self.v_cache.set(self.selection.curselection()[0])
                self.widgetstate()
            self.selection.bind("<ButtonRelease-1>", index)
     
        def v_cache_Callback(self, varName, index, mode):
            self.v_zoneselection.set(self.v_cache.get())
     
        def v_zoneselection_Callback(self, varName, index, mode):
            self.v_cache.set(self.v_zoneselection.get())
     
        def defaultvalue(self, objet):
            if objet < self.selection.size():
                self.selection.select_set(objet)
                self.v_zoneselection.set(self.selection.get(objet))
                self.v_cache.set(self.selection.get(objet))
     
        # Init 
        def __init__(self, parent=None, width=None, border=1, background=None, foreground=None, fg=None, bg=None, font=None, relief=None, cursor=None, exportselection=None, selectbackground=None, selectforeground=None, height=None):
            Toplevel.__init__(self, parent, bd=0)
            self.withdraw()
            self.parent = parent
            self.overrideredirect(1)
            # Inutile ?
            self.transient()
            # StringVar()
            self.v_zoneselection = StringVar()
            self.v_cache = StringVar()
            # Interface
            self.zoneselection = Entry(parent, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, height=height, width=width, background=background, foreground=foreground, highlightthickness=0, textvariable=self.v_zoneselection)
            self.cache = Entry(self, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, width=width, height=height, background=background, foreground=foreground, highlightthickness=0, textvariable=self.v_cache)
            self.cache.pack(fill=X)
            self.listescroll = Scrollbar(self)
            self.listescroll.pack(side=RIGHT, fill=Y)
            self.selection = Listbox(self, yscrollcommand=self.listescroll.set, width=width, border=border, background=background, foreground=foreground, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, height=height)
            self.selection.pack(side=LEFT, fill=X)
            self.listescroll.config(command=self.selection.yview)
            # Binds
            self.selection.bind("<ButtonPress-1>", self.selectionner)
            self.cache.bind("<ButtonPress-1>", self.widgetstate)
            self.zoneselection.bind("<ButtonPress-1>", self.widgetstate)
            # withdraw le toplevel si la fenetre est reduite
            self.parent.bind("<Unmap>", self.reposition)
            # withdraw le toplevel si on deplace la fenetre
            self.parent.bind("<Configure>", self.reposition)
            # Pour eviter que le toplevel reste afficher si une autre fenetre est selectionnee.
            # A revoir
            # self.parent.bind("<FocusOut>", self.reposition)
            # Trace des StringVar()
            self.v_zoneselection_StringVar_traceName = self.v_zoneselection.trace_variable("w", self.v_zoneselection_Callback)
            self.v_cache_StringVar_traceName = self.v_cache.trace_variable("w", self.v_cache_Callback)
            self.zoneselection.icursor(0)
            # Init de self.valeur_widget_state
            self.valeur_widget_state = True
            self.widgetstate()
     
    # Demo
    class test(Tk):
        def __init__(self):
            Tk.__init__(self)
            monexplication = """Sample: Tk.__init__(self)
            self.explication = Text(self, bg='white')
            self.explication.insert(END, monexplication)
            self.explication.pack(side=TOP)
            self.listemini = TkComboBox(self, width=10, bg='black', fg='white')
            self.listemini.pack(side=TOP, pady=20)
            self.listemini.config(bg='white', fg='black')
            for index in range(0,100):
                self.listemini.insert(index, index)
            self.listemini.defaultvalue(50)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)"""
            self.explication = Text(self, bg='white')
            self.explication.insert(END, monexplication)
            self.explication.pack(side=TOP)
            self.listemini = TkComboBox(self, width=10, bg='black', fg='white')
            self.listemini.pack(side=TOP, pady=20)
            self.listemini.config(bg='white', fg='black')
            for index in range(0,100):
                self.listemini.insert(index, index)
            self.listemini.defaultvalue(50)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)
     
    if __name__ == '__main__':
        app = test()
        app.mainloop()
    Si je ne suis pas trop passer à coté de la plaque il ne reste plus que le cadrage.

  5. #5
    Membre confirmé
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Par défaut
    salut,

    le bug de bordure a bien disparu ;
    idem pour l'entry renseigné sans faire appel à la liste ;
    et en fait, c'est aussi ok pour le décalage qui était présent lors du déroulement de la liste.

    par contre, au lancement et après un déplacement de fenêtre, il faut 2 clics dans l'entry pour afficher la liste au lieu d'un seul en temps normal.

    tu t'approches de la perfection

  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,

    Citation Envoyé par spirzouf Voir le message
    par contre, au lancement et après un déplacement de fenêtre, il faut 2 clics dans l'entry pour afficher la liste au lieu d'un seul en temps normal.
    Corrigé (def reposition)

    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
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    try: from tkinter import *
    except: from Tkinter import *
     
    # Class TkComboBox
    # ComboBox en pur Tkinter
    #
    # Options:
    # width, height, border, background (bg) , foreground (fg), font, relief, cursor,
    # exportselection, selectbackground, selectforeground
    #
    # Methodes:
    # activate(int index)
    # focus_set()
    # focus()
    # curselection()
    # delete(ALL ou int)
    # start (int)
    # end (END ou int)
    # insert(index, valeur)
    # get()
    # pack(padx=int, pady=int, fill(X, Y, BOTH), expand=bool, side=LEFT, RIGHT, TOP, BOTTOM, CENTER)
    # grid(row=int, column=int, columnspan=int, rowspan=int, sticky=NSEW, padx=int, pady=int)
    # place(relheight=int, relwidth=int, relx=int, rely=int, width=int, height=int, anchor=NSEW, x=int, y=int)
    # config/configure(Option=Valeur)
    # defaultvalue(int)
    #
    class TkComboBox(Toplevel):
        listeobjets = []
     
        # Positionnement
        def widgetstate(self, event=None):
            # True : Visible
            # False : Cache la listbox
            self.geometry('+%d+%d'%(self.zoneselection.winfo_rootx(),self.zoneselection.winfo_rooty()))
            if self.valeur_widget_state == True:
                self.valeur_widget_state = False
                self.withdraw()
            elif self.valeur_widget_state == False:
                self.valeur_widget_state = True
                self.deiconify()
     
        # Gestionnaires de geometrie
        def pack(self, padx=None, pady=None, fill=None, expand=None, side=None):
            self.zoneselection.pack(padx=padx, pady=pady, fill=fill, expand=expand, side=side)
     
        def grid(self, row=None, column=None, columnspan=None, rowspan=None, sticky=None, padx=None, pady=None):
            self.zoneselection.grid(row=row, column=column, columnspan=columnspan, rowspan=rowspan, sticky=sticky, padx=padx, pady=pady)
     
        def place(self, relheight=None, relwidth=None, relx=None, rely=None, width=None, height=None, anchor=None, x=None, y=None):
            self.zoneselection.place(relheight=relheight, relwidth=relwidth, relx=relx, rely=rely, width=width, height=height, anchor=anchor, x=x, y=y)
     
        # Configuration
        def configure(self, **kw):
            for cle in kw:
                option=cle
                valeur=kw[cle]
                self.zoneselection[option]=valeur
                self.cache[option]=valeur
                self.selection[option]=valeur
     
        config=configure
     
        # Methodes
        def activate(self, index):
            self.selection.activate(index)
     
        def size(self):
            return self.selection.size()
     
        def focus(self):
            self.zoneselection.get_focus()
     
        def get_focus(self):
            self.zoneselection.get_focus()
     
        def curselection(self):
            print map(int, self.selection.curselection())[0]
            return map(int, self.selection.curselection())[0]
     
        def delete(self, objet=None, start=None, end=None):
            if objet=='ALL':
                self.selection.delete(0, END)
            elif start == None and end == None:
                self.selection.delete(objet)
            else:
                self.selection.delete(start, end)
     
        def get(self):
            return self.zoneselection.get()
     
        def insert(self, start, objet):
            self.listeobjets.append(objet)
            self.selection.insert(start, objet)
            self.selection.select_set(0)
            self.v_zoneselection.set(objet)
            self.v_cache.set(objet)
     
        def selectionner(self, event):
            def index(event):
                self.selection.curselection()[0]
                self.v_zoneselection.set(self.selection.curselection()[0])
                self.v_cache.set(self.selection.curselection()[0])
                self.zoneselection.focus_set()
                self.widgetstate()
            self.selection.bind("<ButtonRelease-1>", index)
     
        def v_cache_Callback(self, varName, index, mode):
            self.v_zoneselection.set(self.v_cache.get())
     
        def v_zoneselection_Callback(self, varName, index, mode):
            self.v_cache.set(self.v_zoneselection.get())
     
        def defaultvalue(self, objet):
            if type(objet) == int and objet < self.selection.size() and self.selection.size() > 0:
                self.selection.select_set(objet)
                self.v_zoneselection.set(self.selection.get(objet))
                self.v_cache.set(self.selection.get(objet))
            elif self.selection.size() == 0:
                raise Exception('defaultvalue before values')
            elif type(objet) != int:
                raise TypeError('index must be an integer')
            elif type(objet) == int and objet >= self.selection.size():
                raise ValueError('index out of range')
            else:
                raise Exception('error on defaultvalue')
     
        # Init 
        def __init__(self, parent=None, width=None, border=1, background=None, foreground=None, fg=None, bg=None, font=None, relief=None, cursor=None, exportselection=None, selectbackground=None, selectforeground=None, height=None):
            Toplevel.__init__(self, parent, bd=0)
            self.withdraw()
            self.parent = parent
            self.overrideredirect(1)
            # Inutile ?
            self.transient()
            # StringVar()
            self.v_zoneselection = StringVar()
            self.v_cache = StringVar()
            # Interface
            self.zoneselection = Entry(parent, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, height=height, width=width, background=background, foreground=foreground, highlightthickness=0, textvariable=self.v_zoneselection)
            self.cache = Entry(self, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, width=width, height=height, background=background, foreground=foreground, highlightthickness=0, textvariable=self.v_cache)
            self.cache.pack(fill=X)
            self.listescroll = Scrollbar(self)
            self.listescroll.pack(side=RIGHT, fill=Y)
            self.selection = Listbox(self, yscrollcommand=self.listescroll.set, width=width, border=border, background=background, foreground=foreground, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, height=height)
            self.selection.pack(side=LEFT, fill=X)
            self.listescroll.config(command=self.selection.yview)
            # Binds
            self.selection.bind("<ButtonPress-1>", self.selectionner)
            self.cache.bind("<ButtonPress-1>", self.widgetstate)
            self.zoneselection.bind("<ButtonPress-1>", self.widgetstate)
            # withdraw le toplevel si la fenetre est reduite
            self.parent.bind("<Unmap>", lambda event: self.withdraw())
            # withdraw le toplevel si on deplace la fenetre
            self.parent.bind("<Configure>", lambda event: self.withdraw())
            # Pour eviter que le toplevel reste afficher si une autre fenetre est selectionnee.
            # A revoir
            # self.parent.bind("<FocusOut>", self.reposition)
            # Trace des StringVar()
            self.v_zoneselection_StringVar_traceName = self.v_zoneselection.trace_variable("w", self.v_zoneselection_Callback)
            self.v_cache_StringVar_traceName = self.v_cache.trace_variable("w", self.v_cache_Callback)
            # Init de self.valeur_widget_state
            self.valeur_widget_state = True
            self.widgetstate()
     
    # Demo
    class test(Tk):
        def __init__(self):
            Tk.__init__(self)
            monexplication = """Sample: Tk.__init__(self)
            self.explication = Text(self, bg='white')
            self.explication.insert(END, monexplication)
            self.explication.pack(side=TOP)
            self.listemini = TkComboBox(self, width=10, bg='black', fg='white')
            self.listemini.pack(side=TOP, pady=20)
            self.listemini.config(bg='white', fg='black')
            for index in range(0,100):
                self.listemini.insert(index, index)
            self.listemini.defaultvalue(50)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)"""
            self.explication = Text(self, bg='white')
            self.explication.insert(END, monexplication)
            self.explication.pack(side=TOP)
            self.listemini = TkComboBox(self, width=10, bg='black', fg='white')
            self.listemini.pack(side=TOP, pady=20)
            self.listemini.config(bg='white', fg='black')
            for index in range(0,100):
                self.listemini.insert(index, index)
            self.listemini.defaultvalue(50)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)
     
    if __name__ == '__main__':
        app = test()
        app.mainloop()
    Merci de ton aide

  7. #7
    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,

    Oups ! Grosse erreur de sélection

    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
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    try: from tkinter import *
    except: from Tkinter import *
     
    # Class TkComboBox
    # ComboBox en pur Tkinter
    #
    # Options:
    # width, height, border, background (bg) , foreground (fg), font, relief, cursor,
    # exportselection, selectbackground, selectforeground
    #
    # Methodes:
    # activate(int=index)
    # focus_set()
    # focus()
    # curselection()
    # delete(ALL ou int)
    # start (int)
    # end (END ou int)
    # insert(index, valeur)
    # get()
    # pack(padx=int, pady=int, fill(X, Y, BOTH), expand=bool, side=LEFT, RIGHT, TOP, BOTTOM, CENTER)
    # grid(row=int, column=int, columnspan=int, rowspan=int, sticky=NSEW, padx=int, pady=int)
    # place(relheight=int, relwidth=int, relx=int, rely=int, width=int, height=int, anchor=NSEW, x=int, y=int)
    # config/configure(Option=Valeur)
    # defaultvalue(int=index)
    #
    class TkComboBox(Toplevel):
        listeobjets = []
     
        # Positionnement
        def widgetstate(self, event=None):
            # True : Visible
            # False : Cache la listbox
            self.geometry('+%d+%d'%(self.zoneselection.winfo_rootx(),self.zoneselection.winfo_rooty()))
            if self.valeur_widget_state == True:
                self.valeur_widget_state = False
                self.withdraw()
            elif self.valeur_widget_state == False:
                self.valeur_widget_state = True
                self.deiconify()
     
        # Gestionnaires de geometrie
        def pack(self, padx=None, pady=None, fill=None, expand=None, side=None):
            self.zoneselection.pack(padx=padx, pady=pady, fill=fill, expand=expand, side=side)
     
        def grid(self, row=None, column=None, columnspan=None, rowspan=None, sticky=None, padx=None, pady=None):
            self.zoneselection.grid(row=row, column=column, columnspan=columnspan, rowspan=rowspan, sticky=sticky, padx=padx, pady=pady)
     
        def place(self, relheight=None, relwidth=None, relx=None, rely=None, width=None, height=None, anchor=None, x=None, y=None):
            self.zoneselection.place(relheight=relheight, relwidth=relwidth, relx=relx, rely=rely, width=width, height=height, anchor=anchor, x=x, y=y)
     
        # Configuration
        def configure(self, **kw):
            for cle in kw:
                option=cle
                valeur=kw[cle]
                self.zoneselection[option]=valeur
                self.cache[option]=valeur
                self.selection[option]=valeur
     
        config=configure
     
        # Methodes
        def activate(self, index):
            self.selection.activate(index)
     
        def size(self):
            return self.selection.size()
     
        def focus(self):
            self.zoneselection.get_focus()
     
        def get_focus(self):
            self.zoneselection.get_focus()
     
        def curselection(self):
            print map(int, self.selection.curselection())[0]
            return map(int, self.selection.curselection())[0]
     
        def delete(self, objet=None, start=None, end=None):
            if objet=='ALL':
                self.selection.delete(0, END)
            elif start == None and end == None:
                self.selection.delete(objet)
            else:
                self.selection.delete(start, end)
     
        def get(self):
            return self.zoneselection.get()
     
        def insert(self, start, objet):
            self.listeobjets.append(objet)
            self.selection.insert(start, objet)
            self.selection.select_set(0)
            self.v_zoneselection.set(objet)
            self.v_cache.set(objet)
     
        def selectionner(self, event):
            def index(event):
                items = self.selection.curselection()
                self.v_zoneselection.set(self.selection.get(items))
                self.v_cache.set(self.selection.get(items))
                self.zoneselection.focus_set()
                self.widgetstate()
            self.selection.bind("<ButtonRelease-1>", index)
     
        def v_cache_Callback(self, varName, index, mode):
            self.v_zoneselection.set(self.v_cache.get())
     
        def v_zoneselection_Callback(self, varName, index, mode):
            self.v_cache.set(self.v_zoneselection.get())
     
        def defaultvalue(self, objet):
            if type(objet) == int and objet < self.selection.size() and self.selection.size() > 0:
                self.selection.select_set(objet)
                self.v_zoneselection.set(self.selection.get(objet))
                self.v_cache.set(self.selection.get(objet))
            elif self.selection.size() == 0:
                raise Exception('defaultvalue before values')
            elif type(objet) != int:
                raise TypeError('index must be an integer')
            elif type(objet) == int and objet >= self.selection.size():
                raise ValueError('index out of range')
            else:
                raise Exception('error on defaultvalue')
     
        # Init 
        def __init__(self, parent=None, width=None, border=1, background=None, foreground=None, fg=None, bg=None, font=None, relief=None, cursor=None, exportselection=None, selectbackground=None, selectforeground=None, height=None):
            Toplevel.__init__(self, parent, bd=0)
            self.withdraw()
            self.parent = parent
            self.overrideredirect(1)
            # Inutile ?
            self.transient()
            # StringVar()
            self.v_zoneselection = StringVar()
            self.v_cache = StringVar()
            # Interface
            self.zoneselection = Entry(parent, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, height=height, width=width, background=background, foreground=foreground, highlightthickness=0, textvariable=self.v_zoneselection)
            self.cache = Entry(self, border=border, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, width=width, height=height, background=background, foreground=foreground, highlightthickness=0, textvariable=self.v_cache)
            self.cache.pack(fill=X)
            self.listescroll = Scrollbar(self)
            self.listescroll.pack(side=RIGHT, fill=Y)
            self.selection = Listbox(self, yscrollcommand=self.listescroll.set, width=width, border=border, background=background, foreground=foreground, fg=fg, bg=bg, font=font, relief=relief, cursor=cursor, exportselection=exportselection, selectbackground=selectbackground, selectforeground=selectforeground, height=height)
            self.selection.pack(side=LEFT, fill=X)
            self.listescroll.config(command=self.selection.yview)
            # Binds
            self.selection.bind("<ButtonPress-1>", self.selectionner)
            self.cache.bind("<ButtonPress-1>", self.widgetstate)
            self.zoneselection.bind("<ButtonPress-1>", self.widgetstate)
            # withdraw le toplevel si la fenetre est reduite
            self.parent.bind("<Unmap>", lambda event: self.withdraw())
            # withdraw le toplevel si on deplace la fenetre
            self.parent.bind("<Configure>", lambda event: self.withdraw())
            # Pour eviter que le toplevel reste afficher si une autre fenetre est selectionnee.
            # A revoir
            # self.parent.bind("<FocusOut>", self.reposition)
            # Trace des StringVar()
            self.v_zoneselection_StringVar_traceName = self.v_zoneselection.trace_variable("w", self.v_zoneselection_Callback)
            self.v_cache_StringVar_traceName = self.v_cache.trace_variable("w", self.v_cache_Callback)
            # Init de self.valeur_widget_state
            self.valeur_widget_state = True
            self.widgetstate()
     
    # Demo
    class test(Tk):
        def clic(self, event):
            if self.tkcb2.get() == 'Widget':
                self.txt.delete(1.0, END)
                self.txt.insert(END, self.Widget)
            elif self.tkcb2.get() == 'Sample':
                self.txt.delete(1.0, END)
                self.txt.insert(END, self.Sample)
     
        def __init__(self):
            Tk.__init__(self)
            self.Widget = """# Class TkComboBox
    #
    # Options:
    # width, height, border, background (bg) , foreground (fg), font, relief,
    # cursor,exportselection, selectbackground, selectforeground
    #
    # Methodes:
    # activate(int=index)
    # focus_set()
    # focus()
    # curselection()
    # delete(ALL ou int)
    # start (int)
    # end (END ou int)
    # insert(index, valeur)
    # get()
    # pack(padx=int, pady=int, fill(X, Y, BOTH), expand=bool, side=LEFT, RIGHT,
    # TOP, BOTTOM, CENTER)
    # grid(row=int, column=int, columnspan=int, rowspan=int, sticky=NSEW, padx=int,
    # pady=int)
    # place(relheight=int, relwidth=int, relx=int, rely=int, width=int, height=int,
    # anchor=NSEW, x=int, y=int)
    # config/configure(Option=Valeur)
    # defaultvalue(int=index)"""
            self.Sample = """Sample:
        def clic(self, event):
            if self.tkcb2.get() == 'Widget':
                self.txt.delete(1.0, END)
                self.txt.insert(END, self.Widget)
            elif self.tkcb2.get() == 'Sample':
                self.txt.delete(1.0, END)
                self.txt.insert(END, self.Sample)
     
        def __init__(self):
            Tk.__init__(self)
            self.txt = Text(self, bg='white')
            self.txt.insert(END, self.Widget)
            self.txt.pack(side=TOP)
            #
            self.tkcb1 = TkComboBox(self, width=10, bg='black', fg='white')
            self.tkcb1.pack(side=LEFT, pady=20, padx=20)
            self.tkcb1.config(bg='white', fg='black')
            for index in range(0,100):
                self.tkcb1.insert(index, index)
            self.tkcb1.defaultvalue(50)
            #
            self.tkcb2 = TkComboBox(self, width=20, bg='black', fg='white')
            self.tkcb2.pack(side=RIGHT, pady=20, padx=20)
            self.tkcb2.insert(END, 'Sample')
            self.tkcb2.insert(END, 'Widget')
            # Event
            self.tkcb2.bind('<ButtonRelease-1>', self.clic)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)"""
            self.txt = Text(self, bg='white')
            self.txt.insert(END, self.Widget)
            self.txt.pack(side=TOP)
            #
            self.tkcb1 = TkComboBox(self, width=10, bg='black', fg='white')
            self.tkcb1.pack(side=LEFT, pady=20, padx=20)
            self.tkcb1.config(bg='white', fg='black')
            for index in range(0,100):
                self.tkcb1.insert(index, index)
            self.tkcb1.defaultvalue(50)
            #
            self.tkcb2 = TkComboBox(self, width=20, bg='black', fg='white')
            self.tkcb2.pack(side=RIGHT, pady=20, padx=20)
            self.tkcb2.insert(END, 'Sample')
            self.tkcb2.insert(END, 'Widget')
            # Event
            self.tkcb2.bind('<ButtonRelease-1>', self.clic)
            Button(self, text='QUIT', command=self.quit).pack(side=TOP, pady=20)
     
    if __name__ == '__main__':
        app = test()
        app.mainloop()

  8. #8
    Membre confirmé
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Par défaut
    Bonsoir,

    dans mes tests, tous les bugs que j'avais signalés sont corrigés.

    reste le problème que tu signalais dans ton code : la toplevel reste toujours visible en 1er plan, même devant une autre fenetre que celle de ton programme qui l'a appelé.

    autre chose aussi, la toplevel ne disparait plus si on déplace le root

  9. #9
    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,

    Citation Envoyé par spirzouf Voir le message
    autre chose aussi, la toplevel ne disparait plus si on déplace le root
    Sous quel WM ? J'ai testé sous Vista, Xp, Ubuntu et je n'ai pas du tout cet effet...

    Merci

  10. #10
    Membre confirmé
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Par défaut
    je suis sous kubuntu 9.04
    testé avec python 2.6 et python 3

    (à noter pour python3 les parenthèses à rajouter au print ligne 78)

Discussions similaires

  1. Demande d'avis sur un bouquin (Deitel)
    Par oodini dans le forum C++
    Réponses: 7
    Dernier message: 26/02/2005, 01h50

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