1
votes

Pourquoi le rembourrage intérieur n'est-il appliqué qu'à droite?

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?


0 commentaires

3 Réponses :


-1
votes

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.


6 commentaires

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!



2
votes

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!

Ajout d'un remplissage interne au cadre dans son ensemble

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:

  • Une valeur, pour le remplissage de tous les côtés
  • Deux valeurs, pour x et y (dans cet ordre)
  • Quatre valeurs, pour le remplissage commençant à gauche et dans le sens des aiguilles d'une montre.


3 commentaires

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.



1
votes

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.

 capture d'écran de deux boutons

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:

 capture d'écran de l'étiquette à l'intérieur du bouton

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.


0 commentaires