web-dev-qa-db-fra.com

Comment changer le style de police d'un widget sans connaître la famille/taille de police du widget?

Existe-t-il un moyen de changer le style de police d'un widget Tkinter sans connaître la famille et la taille de la police du widget?

Cas d'utilisation: Nous créons notre interface utilisateur à l'aide des widgets standard Tkinter (Label, Entry, Text, etc.). Pendant que notre application s'exécute, nous souhaitons modifier dynamiquement le style de police de ces widgets en gras et/ou en italique à l'aide de la méthode .config(). Malheureusement, il semble n'y avoir aucun moyen de spécifier une spécification de police sans spécifier la famille et la taille de la police.

Voici des exemples de ce que nous aimerions faire, mais aucun de ces exemples ne fonctionne:

widget.config(font='bold')

ou

widget.config(font=( None, None, 'bold' ))
41
Malcolm

Il existe un moyen bien meilleur que d'utiliser .config() pour modifier la police de votre application, en particulier si votre objectif est de modifier la police de tout un groupe de widgets (ou de tous les widgets).

Une des fonctionnalités vraiment géniales de Tk est la notion de "polices nommées". La beauté des polices nommées est que, si vous mettez à jour la police, tous les widgets utilisant cette police seront automatiquement mis à jour. Donc, configurez vos widgets une fois pour utiliser ces polices personnalisées, puis la modification des attributs est simple.

Voici un exemple rapide:

try:
    import Tkinter as tk
    import tkFont
#    import ttk  # not used here
except ImportError:  # Python 3
    import tkinter as tk
    import tkinter.font as tkFont
#    import tkinter.ttk as ttk  # not used here

class App:
    def __init__(self):
        root=tk.Tk()
        # create a custom font
        self.customFont = tkFont.Font(family="Helvetica", size=12)

        # create a couple widgets that use that font
        buttonframe = tk.Frame()
        label = tk.Label(root, text="Hello, world", font=self.customFont)
        text = tk.Text(root, width=20, height=2, font=self.customFont)
        buttonframe.pack(side="top", fill="x")
        label.pack()
        text.pack()
        text.insert("end","press +/- buttons to change\nfont size")

        # create buttons to adjust the font
        bigger = tk.Button(root, text="+", command=self.OnBigger)
        smaller = tk.Button(root, text="-", command=self.OnSmaller)
        bigger.pack(in_=buttonframe, side="left")
        smaller.pack(in_=buttonframe, side="left")

        root.mainloop()

    def OnBigger(self):
        '''Make the font 2 points bigger'''
        size = self.customFont['size']
        self.customFont.configure(size=size+2)

    def OnSmaller(self):
        '''Make the font 2 points smaller'''
        size = self.customFont['size']
        self.customFont.configure(size=size-2)

app=App()

Si vous n'aimez pas cette approche, ou si vous souhaitez baser votre police personnalisée sur la police par défaut, ou si vous modifiez simplement une ou deux polices pour indiquer leur état, vous pouvez utiliser font.actual pour obtenir la taille réelle d'une police. pour un widget donné. Par exemple:

import Tkinter as tk
import tkFont

root = tk.Tk()
label = tk.Label(root, text="Hello, world")
font = tkFont.Font(font=label['font'])
print font.actual()

Lorsque je lance ce qui précède, je reçois la sortie suivante:

{'family': 'Lucida Grande', 
 'weight': 'normal', 
 'slant': 'roman', 
 'overstrike': False, 
 'underline': False, 
 'size': 13}
49
Bryan Oakley

Encore plus court pour un seul label:

from Tkinter import *
import Tkinter as tk
root = tk.Tk()

# font="-weight bold" does your thing
example = Label(root, text="This is a bold example.", font="-weight bold")
example.pack()

root.mainloop()
23
user4226334

utilisez simplement les attributs de base d'un widget particulier, supposons que vous souhaitiez changer la police d'une étiquette. Vous pouvez utiliser la syntaxe suivante:

mlabel = Label(text="Your text", font=("Name of your font",size))

ce code fonctionne pour python 3.4

4
kybrdbnd

Si vous utilisez une police nommée, vous pouvez utiliser quelques instructions pour obtenir ce que vous voulez:

import tkFont
wfont = tkFont.nametofont(widget['font'])
wfont.config(weight='bold')

Édité pour incorporer le commentaire de B. Oakley. 

4
Brandon

Pour obtenir la police par défaut sans toucher ou avoir un widget, vous pouvez utiliser le nom générique de la police par défaut.

#!/usr/bin/env python3
import tkinter
import tkinter.font  # Python3!

tkinter.Tk()
default_font = tkinter.font.Font(font='TkDefaultFont')
print(default_font.actual())
0
buhtz

Bien que cela fasse longtemps que l'on n'interroge pas ce Q, j'ai récemment dû mettre en œuvre une solution, que je pensais utile de partager. La fonction widget_font_config (...) s’exécute sur Python 2 et 3.

En substance, la "valeur actuelle" de la police du widget est récupérée, modifiée puis remise à zéro. Les polices nommées sont prises en charge et la valeur par défaut inplace_f valeur de True signifie que les polices nommées seront conservées et modifiées à la place. Mais l'indicateur peut également être défini sur False , ce qui provoquera le remplacement d'une police nommée par une police nommée différente, au cas où l'utilisateur ne souhaite pas que les modifications apportées à la police du widget se répercutent sur toutes les autres widgets qui utilisent la police nommée.

def widget_font_config(widget, inplace_f = True, **kwargs):
    import sys
    if sys.version_info[0] is 2:
        import tkFont
    else:
        import tkinter.font as tkFont
    inplace_f = kwargs.pop('inplace', inplace_f)
    font = None    
    if widget and 'font' in widget.config():
        font_config = widget.config()['font']
        current_font = font_config[4] #grabs current value
        namedfont_f = False
        try:
            font = tkFont.nametofont(current_font)
            namedfont_f = True
        except:
            font = current_font
        if namedfont_f and inplace_f:
            font.config(**kwargs)
        else:
            font_d = tkFont.Font(font=font).actual()
            font_d.update(**kwargs)
            font = tkFont.Font(**font_d)
            widget.config(font=font)
        widget.update_idletasks()
    return font

if __== '__main__':
    import sys
    pyVers = sys.version_info.major
    if pyVers is 2:
        import Tkinter as Tk, tkFont
    else:
        import tkinter as Tk, tkinter.font as tkFont
    def go():
        print(widget_font_config(root.label,  slant='roman', underline=1).actual())
        print(widget_font_config(root.button, overstrike=1).actual())
    root = Tk.Tk()
    font_s = 'Courier 20 italic'
    font_d = dict(family='Courier', size=10, weight='normal', slant='italic')
    font = tkFont.Font(**font_d)
    root.label = Tk.Label(text='Label {}'.format(font_s), font=font_s)
    root.label.pack()
    root.button = Tk.Button(text='Button {}'.format(font), font=font, command=go)
    root.button.pack()
    root.mainloop()
0
Gary02127

Pour résumer une grande partie des informations ci-dessus en un seul extrait de code:

lbl = ttk.Label(blah, blah)   # Make a label
font = tkFont(lbl['font'])    # Get its font
font.config(weight='bold')    # Modify font attributes
lbl['font'] = font            # Tell the label to use the modified font

Cela permet aux attributs de police d'être modifiés indépendamment de la police utilisée (tant que la police prend en charge cet attribut).

Vous pouvez également le faire à la volée pour créer des effets de police vraiment écoeurants.

0
user3712955