2017-10-16 22 views
2

Je voudrais savoir comment créer un widget de boutons dans Tkinter avec plusieurs étiquettes comme la figure suivante. Buttons with sub-label. Comme vous pouvez le voir, il existe dans certains boutons une sous-étiquette, par exemple, le bouton "X" a une autre petite étiquette "A". J'ai essayé de chercher la solution, mais n'en ai trouvé aucune.Comment créer plusieurs widget Label in Button de Tkinter?

Merci beaucoup d'avance.

Répondre

1

Vous pouvez placer vos étiquettes dans un Frame et avoir le Button comme parent de cette image. Cependant, vous aurez besoin d'être un peu intelligent et à résoudre des problèmes tels que:

  • incapacité de cliquer sur le bouton correctement (vous ne pouvez cliquer sur les bords, parce que le cadre contenant des étiquettes est au milieu) , ce qui signifie que vous devez effectuer une gestion d'événement (cliquer sur le cadre et les étiquettes à l'intérieur doivent déclencher le même événement que si le bouton a été cliqué)
  • couleurs non synchronisées en survolant le bouton lui-même
  • et quelques autres détails mineurs, comme la configuration correcte du bouton relief quand on clique dessus (n'oubliez pas, vous pouvez cliquer sur le cadre ou les étiquettes!), etc.

Voici un MCVE:

import sys 
import string 
import random 

try: 
    import tkinter as tk 
    from tkinter import ttk 
except ImportError: 
    import Tkinter as tk 
    import ttk 

CHARS = string.ascii_letters + string.digits 

class CustomButton(tk.Button): 
    """ 
    CustomButton class inherits from tk.Button, which means it 
    behaves just like an ordinary tk.Button widget, but it also 
    has some extended functionality. 
    """ 

    def __init__(self, parent, *args, **kwargs): 
     super().__init__() 
     self.command = kwargs.get('command') 
     self.frame = tk.Frame(self) 
     self.frame.pack(fill='none', expand=False, pady=(3, 0)) 
     self.upper_label = ttk.Label(self.frame, text=kwargs.get('upper_text')) 
     self.upper_label.grid(row=0, column=0) 
     self.bottom_label = ttk.Label(self.frame, text=kwargs.get('bottom_text')) 
     self.bottom_label.grid(row=1, column=1) 
     self.frame.pack_propagate(False) 
     self.configure(width=kwargs.get('width'), height=kwargs.get('height')) 
     self.pack_propagate(False) 
     self.clicked = tk.BooleanVar() 
     self.clicked.trace_add('write', self._button_cmd) 
     self.bind('<Enter>', self._on_enter) 
     self.bind('<Leave>', self._on_leave) 
     self.frame.bind('<Enter>', self._on_enter) 
     self.frame.bind('<Button-1>', self._on_click) 
     self.upper_label.bind('<Button-1>', self._on_click) 
     self.bottom_label.bind('<Button-1>', self._on_click) 

    def _button_cmd(self, *_): 
     """ 
     Callback helper method 
     """ 
     if self.clicked.get() and self.command is not None: 
      self.command() 

    def _on_enter(self, _): 
     """ 
     Callback helper method which is triggered 
     when the cursor enters the widget's 'territory' 
     """ 
     for widget in (self, self.frame, self.upper_label, self.bottom_label): 
      widget.configure(background=self.cget('activebackground')) 

    def _on_leave(self, _): 
     """ 
     Callback helper method which is triggered 
     when the cursor leaves the widget's 'territory' 
     """ 
     for widget in (self, self.frame, self.upper_label, self.bottom_label): 
      widget.configure(background=self.cget('highlightbackground')) 

    def _on_click(self, _): 
     """ 
     Callback helper method which is triggered 
     when the the widget is clicked 
     """ 
     self.clicked.set(True) 
     self.configure(relief='sunken') 
     self.after(100, lambda: [ 
      self.configure(relief='raised'), self.clicked.set(False) 
     ]) 


class KeyboardMCVE(tk.Tk): 
    """ 
    MCVE class for demonstration purposes 
    """ 
    def __init__(self): 
     super().__init__() 
     self.title('Keyboard') 
     self._widgets = [] 
     self._create_widgets() 

    def _create_widgets(self): 
     """ 
     Instantiating all the "keys" (buttons) on the fly while both 
     configuring and laying them out properly at the same time. 
     """ 
     for row in range(5): 
      current_row = [] 
      for column in range(15): 
       button = CustomButton(
        self, 
        width=1, height=2, 
        upper_text=random.choice(CHARS), 
        bottom_text=random.choice(CHARS) 
       ) 
       button.grid(row=row, column=column, sticky='nswe') 
       current_row.append(button) 
      self._widgets.append(current_row) 

if __name__ == '__main__': 
    sys.exit(KeyboardMCVE().mainloop()) 

Example

Alternativement, une solution simple serait d'utiliser Unicode/indices supérieurs indices.

+0

Merci beaucoup. Je n'ai jamais pensé que je pourrais avoir un cadre en tant qu'enfant d'un bouton. Comme vous l'avez dit, je dois être un peu prudent dans la gestion des événements. Maintenant, j'ai une nouvelle idée pour créer une image et la mettre sur des boutons. Merci beaucoup. – Hasan

+1

Excellente approche. Cette réponse mérite plus d'upvotes –