Les réponses actuelles fournissent une solution de contournement en utilisant l'argument de mot clé padding
. Une explication POURQUOI l'utilisation de ipadx
échoue est toujours nécessaire.
MCVE
import Tkinter as tk import ttk root = tk.Tk() root.minsize(200, 100) inner_frame = ttk.LabelFrame(root, text='inner_frame') inner_frame.grid(row=0, column=0) button = ttk.Button(inner_frame, text='this is a button') button.grid(row=0, column=0) # this does not work as expected inner_frame.grid_configure(ipadx=20) root.mainloop()
Résultat
Question
Pourquoi le remplissage interne de inner_frame
est-il appliqué uniquement à droite? Comment l'appliquer des deux côtés?
3 Réponses :
Jusqu'à présent, j'ai compris que l'utilisation de padding = ...
dans le constructeur LabelFrame
produit le résultat correct.
Si vous supprimez la ligne p >
inner_frame['padding'] = [20, 0]
et utilisez
inner_frame = ttk.LabelFrame(root, text='inner_frame', padding=[20, 0])
ou bien
inner_frame.grid_configure(ipadx=20)
le résultat ressemble à ceci:
Je n'ai aucune idée de pourquoi utiliser ipadx
à grid_configure
ne fonctionne pas comme prévu.
Les rembourrages internes et externes fonctionnent différemment. Lorsque vous utilisez un remplissage externe, par exemple, aucune couleur d'arrière-plan ou style du cadre ne sera appliqué à la zone de remplissage externe. Vous pouvez le considérer comme une bordure transparente.
@JoseSalvatierra oui, mais padding = ...
semble remplir en interne, comme souhaité. Non?
Ce n'est pas un rembourrage interne, c'est une bordure sur le côté gauche du cadre. Cela a le même aspect ici, mais essayez d'ajouter une couleur d'arrière-plan au cadre et vous verrez la différence!
En fait, mes excuses - le paramètre padding
que vous avez utilisé ici n'est pas lié à grid
. Donc vous avez raison, c'est un rembourrage interne, mais sur le cadre lui-même et pas dans une colonne particulière.
@JoseSalvatierra oui, j'ai vérifié en ajoutant une couleur de fond. Pourtant, ce serait bien de savoir quel est le problème avec ipadx
/ grid ici.
Oui, je ne sais pas pourquoi il faut changer de poids pour appliquer un rembourrage interne!
Fait intéressant, et je ne sais pas s'il s'agit d'un bogue, votre problème est résolu en augmentant la colonne contenant le bouton au-delà de sa taille horizontale minimale.
La taille horizontale minimale de la colonne 0 dans le cadre intérieur est la taille horizontale de son contenu, qui est le bouton.
Si vous ajoutez un inner_frame.columnconfigure (0, weight = 1)
, alors le remplissage interne fonctionne comme prévu:
ttk.LabelFrame(root, text="inner", padding=(20, 0))
Notez que grid_configure
modifie la colonne 0 par défaut, nous ajoutons donc ici un remplissage interne aux cellules de la colonne 0.
Je ne sais pas exactement pourquoi cela se produit. Il n'est pas mentionné dans la documentation de la grille Tcl ( http: // tcl. tk / man / tcl8.5 / TkCmd / grid.htm # M13 ).
Fait intéressant, ce lien mentionne un cas particulier concernant la taille du cadre en utilisant un rembourrage interne (en bas de la page , dans la section "Rembourrage interne"): https://tkdocs.com/tutorial/grid.html
La différence peut être subtile. Supposons que vous ayez un cadre de 20x20 et que vous spécifiez un remplissage normal (externe) de 5 pixels de chaque côté. Le cadre demandera un rectangle 20x20 (sa taille naturelle) au gestionnaire de géométrie. Normalement, c'est ce qui lui sera accordé, donc il obtiendra un rectangle 20x20 pour le cadre, entouré d'une bordure de 5 pixels.
Avec le remplissage interne, le gestionnaire de géométrie ajoutera effectivement le remplissage supplémentaire au widget lors de la détermination de sa taille naturelle, comme si le widget avait demandé un rectangle 30x30. Si le cadre est centré, ou attaché à un seul côté ou coin (en utilisant "collant"), vous vous retrouverez avec un cadre 20x20 avec un espace supplémentaire autour de lui. Si toutefois le cadre est défini pour s'étirer (c'est-à-dire une valeur "collante" de "we", "ns" ou "nwes"), il remplira l'espace supplémentaire, ce qui donnera un cadre 30x30, sans bordure.
Mais c'est écrit de manière confuse, et je ne peux pas comprendre pleinement ce qu'ils signifient (ou même s'ils sont corrects en Python moderne). Si quelqu'un sait ce que signifie ce paragraphe ci-dessus, faites un commentaire ci-dessous et faites-le nous savoir!
Vous pouvez ajouter un remplissage interne en utilisant des styles ou en le passant directement comme argument au constructeur du cadre:
import tkinter as tk from tkinter import ttk root = tk.Tk() inner_frame = ttk.LabelFrame(root_frame, text="inner_frame") inner_frame.grid(row=0, column=0) inner_frame.columnconfigure(0, weight=1) button = ttk.Button(inner_frame, text="this is a button") button.grid(row=0, column=0) # this works expected: inner_frame.grid_configure(ipadx=20) root.mainloop()
La valeur de remplissage peut prendre soit:
Merci d'avoir creusé! J'ai lu ce paragraphe aussi et cela m'a laissé perplexe. Et si inner_frame
a plusieurs colonnes, cependant? (De plus, j'ai simplifié le code dans ma question, vous voudrez peut-être ajuster votre réponse.)
grid_configure
change la colonne 0 par défaut, donc en faisant grid_configure (ipadx = 20)
vous avez configuré le remplissage interne de la colonne 0. Si vous souhaitez ajouter plus de remplissage de colonne, vous devrez le faire pour chacun et ajuster le poids pour qu'il soit différent de zéro.
@JoseSalvatierra: non, grid_configure
ne change pas la colonne 0. Vous devez penser si grid_columnconfigure
. grid_configure
ne configure pas une ligne ou une colonne, il configure un esclave. Vous avez écrit "donc ici nous ajoutons un remplissage interne aux cellules de la colonne 0." ce qui n'est pas correct. Il ajoute un remplissage interne au widget dans son ensemble, pas à une colonne spécifique.
Dans votre cas, ipadx
n'échoue pas. Il fonctionne comme prévu, c'est juste que son fonctionnement n'est pas très intuitif, surtout lorsque vous l'appliquez à un cadre.
Pour mieux visualiser ce qui se passe, appliquons la valeur ipadx
au bouton plutôt qu'au cadre. De cette façon, nous pouvons voir le remplissage par rapport à l'étiquette sur le bouton.
Par exemple, ajoutez deux boutons au lieu d'un. Donnez à l'un un ipadx
de 20, et donnez à l'autre un ipadx
de 0.
button1.grid_propagate(False) label = ttk.Label(button1, text="x") label.grid(row=0, column=0)
Notez que le bouton avec ipadx = 20
est plus large et l'espace supplémentaire est à l'intérieur du bouton plutôt que comme une marge entourant le bouton.
La même chose se passe avec inner_frame
: quand il est ajouté à son parent, l'espace supplémentaire est ajouté à l'intérieur du cadre, faisant effectivement inner_frame
plus large. Vous ne pouvez pas le voir car il est ajouté à l'espace vide déjà à l'intérieur du cadre.
Voici la partie importante: si vous ajoutez un widget à inner_frame
, grid
ne sait rien de l ' ipadx
valeurs appliquées à inner_frame
- cette option ipadx
s'applique uniquement à inner_frame
et à son parent , pas à ses enfants. Au moment d'ajouter des widgets à l'intérieur de inner_frame
, grid
sait seulement que inner_frame
a une largeur de X pixels.
Pour illustrer, nous pouvons ajouter une étiquette au bouton, de la même manière que votre code d'origine ajoute un bouton au cadre. (note: nous désactiverons la propagation de la géométrie pour qu'elle ne rétrécisse pas le bouton).
button1 = ttk.Button(inner_frame, text='this is a button') button2 = ttk.Button(inner_frame, text='this is a button') button1.grid(row=0, column=0, ipadx=20) button2.grid(row=1, column=0, ipadx=0)
Vous devriez voir une fenêtre qui ressemble à ceci:
Voyez comment le" x "est à l'extrême gauche du bouton? C'est parce qu'il ne sait rien de la valeur ipadx
appliquée à son parent. Tout ce qu'il sait, c'est que le bouton est un widget X pixels, et qu'il est censé être sur le bord gauche du bouton.
C'est ce qui se passe avec le cadre et le bouton d'origine - le bouton est ajouté à l'intérieur le cadre, en utilisant tout l'espace à l'intérieur du cadre.