Outils pour utilisateurs

Outils du site


issue181:python

During the creation of PAGE 7.4, I had created a widget demo that included almost every widget that PAGE supports. This includes the Tk widgets, the ttk themed widgets, the enhanced widgets, and even a demonstration of using the custom widget. I decided to use a TNotebook with four tabs, one for each type of widget, and one that has a few tricks. During my creation of the demo, I realized I really didn’t have a low-level grasp of Styles and Themes. The subject is poorly documented, even in the Tcl/Tk world, and where there is documentation, many times the documentation is incorrect. Many programmers who use Tkinter either love or hate the ttk widgets, styles and themes. Many, like me, avoid the ttk widgets unless it’s an absolute necessity. When I am designing a GUI, more times than not, I will use the “standard” Tk widgets and use only the TCombobox, TNotebook, TNotebook, and the Treeview. Dealing with themes and styles is just too time consuming, at least in my mind, to be productive. Part of the confusion for many programmers is what exactly are Themes and what are Styles.

Pendant la création de PAGE 7.4, j'avais créé une démo de widget qui incluait presque tous les widgets que PAGE supporte. Cela comprend les widgets Tk, les widgets à thème ttk, les widgets améliorés et même une démonstration de l'utilisation du widget personnalisé. J'ai décidé d'utiliser un TNotebook avec quatre onglets, un pour chaque type de widget, et un qui a quelques astuces.

Pendant la création de la démo, je me suis rendu compte que je ne maîtrisais pas vraiment les styles et les thèmes. Le sujet est peu documenté, même dans le monde Tcl/Tk, et lorsqu'il y a de la documentation, elle est souvent incorrecte.

De nombreux programmeurs qui utilisent Tkinter aiment ou détestent les widgets, styles et thèmes de ttk. Beaucoup, comme moi, évitent les widgets ttk à moins que ce ne soit une nécessité absolue. La plupart du temps, lorsque je conçois une interface graphique, j'utilise les widgets Tk « standard » et je n'utilise que les TCombobox, TNotebook et Treeview. La gestion des thèmes et des styles prend trop de temps, du moins dans mon esprit, pour être productive.

Pour de nombreux programmeurs, une partie de la difficulté vient de savoir ce que sont exactement les thèmes et les styles.

Styles concern the look and feel of a single widget. A Theme is a collection of Styles that share attributes like background colors and foreground colors, across many ttk widgets. While that is pretty easy to understand, for Linux, there are only four predefined Themes for the ttk widgets. They are Alt, Clam, Classic and Default. Those who use Windows have a couple of extra themes, but they aren’t available to Linux or Mac users, and the Mac has its own Themes that aren’t available to Linux or Windows users. And if you want to make your own, or at least modify one of the defaults, the documentation that exists is SO convoluted that it is often easier and more productive to just ignore the ttk widgets and deal with the Tk widgets. There are extra packages that a programmer can use to add more Themes, but many of them don’t seem to take many attributes of the widgets into consideration, so while they look good in general, things like the background of the TLabel doesn’t match the background of the container (or form) and there’s no obvious way to change it. To make matters worse, some of the containers, like the TFrame or TLabelframe, often don’t get a visible border. One of the most frustrating parts of creating the widget demo was fighting the TNotebook colors for the tabs. Take a look at this image:

Les Styles concernent l'aspect et la convivialité d'un seul widget. Un Thème est une collection de Styles qui partagent des attributs, tels que les couleurs d'arrière-plan et de premier plan, pour de nombreux widgets ttk.

Bien que cela soit assez facile à comprendre, pour Linux, il n'y a que quatre Thèmes prédéfinis pour les widgets ttk. Ce sont Alt, Clam, Classic et Default. Ceux qui utilisent Windows ont quelques thèmes supplémentaires, mais ils ne sont pas disponibles pour les utilisateurs de Linux ou de Mac, et Mac a ses propres thèmes qui ne sont pas disponibles pour les utilisateurs de Linux ou de Windows. Et si vous voulez créer le vôtre, ou au moins modifier l'un des thèmes par défaut, la documentation existante est TELLEMENT alambiquée qu'il est souvent plus facile et plus productif d'ignorer les widgets ttk et de s'occuper des widgets Tk. Il y a des paquets supplémentaires qu'un programmeur peut utiliser pour ajouter plus de thèmes, mais beaucoup d'entre eux ne semblent pas prendre en considération de nombreux attributs des widgets, donc bien qu'ils aient l'air bien en général, des choses comme l'arrière-plan du TLabel ne correspondent pas à l'arrière-plan du conteneur (ou du formulaire) et il n'y a pas de moyen évident de les changer. Pour aggraver les choses, certains conteneurs, comme le TFrame ou le TLabelframe, n'ont souvent pas de bordure visible.

L'une des parties les plus frustrantes de la création de la démo des widgets a été la lutte contre les couleurs pour les onglets de TNotebook. Jetez un coup d'œil à cette image :

You can see that Tab 2 is the current or selected tab, Tab 3 is sort of highlighted when the mouse is over the tab, and the other two are somewhat obvious that you aren’t dealing with them at the moment. But if you are color challenged, like me, it’s not always obvious. Wouldn’t it be better to be able to present your user with something like this: It is immediately obvious that Tab 1 is the current tab, Tabs 2, 4 and 5 are just “hanging out”, and Tab 3 is the one that the mouse is hovering over. You might not like the color selection, but it makes a big visual difference. But how to do it? Digging into the GUI.py file that PAGE creates gave me the first clue (see the code, next page, bottom right). The style.configure method allows you to set the basic background and foreground colors, but what does the style.map method do and why would I do it?

Vous pouvez voir que l'onglet 2 est l'onglet actuel ou sélectionné, que l'onglet 3 est en quelque sorte mis en évidence lorsque la souris passe sur l'onglet, et que les deux autres sont plus ou moins évidents du fait que vous ne les utilisez pas pour le moment. Mais si vous êtes daltonien, comme moi, ce n'est pas toujours évident. Ne serait-il pas préférable de pouvoir présenter à votre utilisateur quelque chose comme ceci ? :

Il est immédiatement évident que l'onglet 1 est l'onglet actuel, que les onglets 2, 4 et 5 sont juste « en attente » et que l'onglet 3 est celui sur lequel passe la souris. Vous n'aimez peut-être pas cette sélection de couleurs, mais elle fait une grande différence visuelle. Mais comment faire ?

En fouillant dans le fichier GUI.py créé par PAGE, j'ai trouvé le premier indice (voir le code, page suivante, en bas à droite).

La méthode style.configure permet de définir les couleurs de base de l'arrière-plan et de l'avant-plan, mais que fait la méthode style.map et pourquoi l'utiliserais-je ?

Well, with a bunch more digging around in various documentation and websites, I found out that the .map method allows you to set different colors to different states for the widget. So in the above code, the “selected” state is when the tab is actually selected and the “active” state is when the mouse is hovering over the tab. Notice that for the moment, we are only talking about the TNotebook tabs. But what about the other tabs that are “just hanging out”. That took some more digging to answer. It turns out that there is another state called “!active” that covers those tabs. Once I figured the hex codes for the colors I wanted I was ready. When I went to code it (shown top right), being the lazy programmer I am, I threw together a quick test program in PAGE with just a TNotebook on it and then created a startup function to set the colors and assign them to the widget. When I ran the program, I was disappointed. I quickly went back to the documentation and various websites to try to figure out what I was missing. It turns out that just setting the TNotebook map applies only to the actual Notebook portion. If I wanted to set the colors, I had to specify that the map was for the tabs (shown middle right). When I ran it this time, low and behold, it worked!

Eh bien, en creusant un peu plus dans diverses documentations et sites Web, j'ai découvert que la méthode .map vous permet de définir différentes couleurs pour différents états du widget. Ainsi, dans le code ci-dessus, l'état « sélectionné » est celui où l'onglet est effectivement sélectionné et l'état « actif » est celui où la souris passe sur l'onglet. Remarquez que pour l'instant, nous ne parlons que des onglets de TNotebook. Mais qu'en est-il des autres onglets qui sont « juste en attente » ? Il a fallu creuser un peu plus pour répondre à cette question. Il s'avère qu'il existe un autre état appelé « !active » qui couvre ces onglets. Une fois que j'ai trouvé les codes hexadécimaux pour les couleurs que je voulais, j'étais prêt.

Lorsque j'ai commencé à coder (en haut à droite), étant donné le programmeur paresseux que je suis, j'ai créé un programme de test rapide en PAGE avec juste un TNotebook dessus, puis j'ai créé une fonction de démarrage pour définir les couleurs et les affecter au widget.

Lorsque j'ai exécuté le programme, j'ai été déçu.

Je suis rapidement retourné dans la documentation et sur divers sites Web pour essayer de comprendre ce qui me manquait. Il s'est avéré que le simple fait de définir map de TNotebook ne s'applique qu'à la partie réelle de Notebook. Si je voulais définir les couleurs, je devais préciser que map concernait les onglets (voir au milieu à droite).

Lorsque je l'ai exécuté cette fois-ci, cela a fonctionné !

Then I tried to apply my new trick to other ttk widgets. Unfortunately, again, I was taking things for granted. For the most part, each ttk widget has its own set of attributes that the map can handle. For example, take the simple lowley TButton (next page, top right). The Tcl code shows that the TButton does have a map method, but the various states are far different from the TNotebook Tabs. There is an active state, a disabled state, and a readonly state. (Why would a TButton need a readonly state? I don’t know, but it apparently does.) So I reworked the code a bit for the TButton and came up with this (bottom right). When I then ran my program, I was disappointed again. The TButton had the default gray background and black text color set. When I moved the mouse over the TButton, it did change to background #2. I knew I was close, so I looked at the documentation a bit more closely. I remembered that I had to set the background and foreground separately from the map statement. _w1.TButton1.configure(background=bg1, foreground=fg1)

J'ai ensuite essayé d'appliquer ma nouvelle astuce à d'autres widgets ttk. Malheureusement, une fois encore, je prenais les choses pour acquises. Pour la plupart, chaque widget ttk a son propre ensemble d'attributs que map peut gérer. Par exemple, prenez le simple TButton de Lowley (page suivante, en haut à droite).

Le code Tcl montre que TButton possède une méthode map, mais les différents états sont très différents de ceux des onglets TNotebook. Il existe un état actif, un état désactivé et un état en lecture seule. (Pourquoi un TButton aurait-il besoin d'un état en lecture seule ? Je ne sais pas, mais apparemment c'est le cas). J'ai donc retravaillé un peu le code pour TButton et j'ai obtenu ceci (en bas à droite).

Lorsque j'ai exécuté mon programme, j'ai été de nouveau déçu. L'arrière-plan du TButton était gris par défaut et la couleur du texte était noire. Lorsque j'ai déplacé la souris sur le TButton, il est passé à l'arrière-plan n° 2. Je savais que j'étais proche, alors j'ai regardé la documentation d'un peu plus près. Je me suis souvenu que je devais définir l'arrière-plan et le premier plan en dehors de l'instruction map.

_w1.TButton1.configure(background=bg1, foreground=fg1)

That, however, didn’t do it either. Then I remembered that I have to override the style defaults (dull gray background and black foreground). This is “explained” (somewhat) in the New Mexico Tech Tkinter documentation. It turns out that I can create a special style and apply that to my button by using the style attribute (shown bottom left). That worked! For more on the “Trials and Tribble-ations” of my long and arduous journey learning how to master Styles and Themes with ttk widgets in Tkinter, please see next month’s article. I’ll save the code portions for then. Until next time, as always; stay safe, healthy, positive and creative!

Mais cela n'a pas fonctionné non plus. Je me suis alors souvenu que je devais remplacer les valeurs par défaut du style (arrière-plan gris terne et premier plan noir). Cela est « expliqué » (en quelque sorte) dans la documentation Tkinter de New Mexico Tech. Il s'avère que je peux créer un style spécial et l'appliquer à mon bouton en utilisant l'attribut style (montré en bas à gauche).

Cela a fonctionné !

Pour en savoir plus sur les tâtonnements dans mon long et ardu voyage pour apprendre à maîtriser les Styles et les Thèmes avec les widgets ttk dans Tkinter, veuillez consulter l'article du mois prochain. Je garderai les portions de code pour ce moment-là.

Jusqu'à la prochaine fois, comme toujours, restez en sécurité, en bonne santé, positif et créatif !

issue181/python.txt · Dernière modification : 2022/06/02 19:20 de andre_domenech