issue194:python
Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
issue194:python [2023/07/01 06:46] – créée d52fr | issue194:python [2023/07/03 14:42] (Version actuelle) – auntiee | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | **Last month, we looked at playing some tricks on the ttk TNotebook widget with the style manipulation Python module that I wrote called “mystyles_dark.py”. I also promised that I would focus more on that module to provide some insight on how it all works. | ||
- | Last month, we looked at playing some tricks on the ttk TNotebook widget with the style manipulation Python module | + | Since then, I’ve modified |
- | Since then, I’ve modified the theme file so it isn’t quite as dark, and to do some other things that the original couldn’t. The new file is called “mystyles_notsodark.py”, and that’s what we’ll concentrate on in this month’s article. The files will be available in my repository, which I will share with you at the end of the article. | + | Le mois dernier, nous avons essayé de jouer quelques tours sur le widget TNotebook de ttk avec le module Python de manipulation de style que j'ai écrit et qui s' |
- | The original code was the starting point of my notsodark Tcl theme. I use the styling module as my testbed to make sure that I could make things work using Python, since my knowledge of Tcl/Tk was and still is limited. I looked at almost every Tcl theme I could, including the source for the four Linux “default” themes alt, clam, classic and of course default. I have to admit, it took me a while to figure out how to convert much of the Tcl code into Python. I had various copies of my beginning Tcl books open at the same time as I was trying to code the Python file and I had many false starts, but I eventually figured it all out. Eventually, I got the color schemes all worked out to something that I liked. | + | Depuis, j'ai modifié le fichier du thème pour qu'il ne soit pas aussi sombre, et pour qu'il puisse faire d' |
- | That’s enough history, now let’s get started. | + | **The original code was the starting point of my notsodark Tcl theme. I use the styling module as my testbed to make sure that I could make things work using Python, since my knowledge of Tcl/Tk was and still is limited. I looked at almost every Tcl theme I could, including the source for the four Linux “default” themes alt, clam, classic and of course default. I have to admit, it took me a while to figure out how to convert much of the Tcl code into Python. I had various copies of my beginning Tcl books open at the same time as I was trying to code the Python file and I had many false starts, but I eventually figured it all out. Eventually, I got the color schemes all worked out to something that I liked. |
- | The first thing we’ll look at is the styling module, “mystyles_notsodark.py”. The imports section is where I always start when examining a python module, so that’s where we’ll begin today. | + | That’s enough history, now let’s get started.** |
+ | |||
+ | Le code original est le point de départ de mon thème Tcl notsodark. J'ai utilisé le module de style comme banc d' | ||
+ | |||
+ | Assez d' | ||
+ | |||
+ | |||
+ | **The first thing we’ll look at is the styling module, “mystyles_notsodark.py”. The imports section is where I always start when examining a python module, so that’s where we’ll begin today. | ||
import sys | import sys | ||
Ligne 18: | Ligne 26: | ||
import os.path | import os.path | ||
- | Since we are making a “standalone” module, we need to import sys and tkinter. The use of os.path is needed since we are going to make the module operating system agnostic (able to run on Windows, Linux, and Mac), and we want to be able to get to the Assets folder no matter where the user has installed our module; we can use the os.path.join method to concatenate the correct directory separator (“/” or “\”) in the correct places. The other thing we need to import is an empty file called shared.py. We normally use this to enable various modules of a program to communicate between each other. However, there is a secondary benefit of this, which will become clear in a little bit. | + | Since we are making a “standalone” module, we need to import sys and tkinter. The use of os.path is needed since we are going to make the module operating system agnostic (able to run on Windows, Linux, and Mac), and we want to be able to get to the Assets folder no matter where the user has installed our module; we can use the os.path.join method to concatenate the correct directory separator (“/” or “\”) in the correct places. The other thing we need to import is an empty file called shared.py. We normally use this to enable various modules of a program to communicate between each other. However, there is a secondary benefit of this, which will become clear in a little bit.** |
- | We put the next three lines just after the import section so that the values are, by scope, implicity global. This means that they are available to any functions with the module as long as they aren’t changed within any of the functions. We have to be careful of this (see below). | + | La première chose que nous allons examiner est le module de style, « mystyles_notsodark.py ». Je commence toujours par la section des importations lorsque j' |
+ | |||
+ | import sys | ||
+ | |||
+ | import shared | ||
+ | |||
+ | import tkinter as tk | ||
+ | |||
+ | import os.path | ||
+ | |||
+ | Puisque nous créons un module « autonome », nous devons importer sys et tkinter. L' | ||
+ | |||
+ | |||
+ | **We put the next three lines just after the import section so that the values are, by scope, implicity global. This means that they are available to any functions with the module as long as they aren’t changed within any of the functions. We have to be careful of this (see below). | ||
+ | |||
+ | We can use the location variable to provide the proper base path when we call the os.path.join statements later on.** | ||
+ | |||
+ | Nous plaçons les trois lignes suivantes juste après la section import afin que les valeurs soient implicitement | ||
+ | |||
+ | Nous pouvons utiliser la variable location pour fournir le chemin de base approprié lorsque nous appelons les instructions os.path.join plus tard. | ||
- | We can use the location variable to provide the proper base path when we call the os.path.join statements later on. | ||
- | Next, we need to do some definitions of color variables that we will need in our various functions. I’ll show only a few of the definitions, | + | **Next, we need to do some definitions of color variables that we will need in our various functions. I’ll show only a few of the definitions, |
_bgcolor stands for background color, _fgcolor is the foreground color. | _bgcolor stands for background color, _fgcolor is the foreground color. | ||
Ligne 31: | Ligne 57: | ||
The create_styles function takes just one parameter, an instance of ttk.Style(). Since I like to save as many keystrokes as I can, I named that instance sty. | The create_styles function takes just one parameter, an instance of ttk.Style(). Since I like to save as many keystrokes as I can, I named that instance sty. | ||
- | The first configure statement creates a set of color definitions that are duplicated from the global definitions. These, however, are supposed to be used for the root style of the theme, which sets the color sets for every ttk widget used in the Toplevel form. It doesn’t seem to actually work in Python like this and the actual colors that can be used are those from the global definition. | + | The first configure statement creates a set of color definitions that are duplicated from the global definitions. These, however, are supposed to be used for the root style of the theme, which sets the color sets for every ttk widget used in the Toplevel form. It doesn’t seem to actually work in Python like this and the actual colors that can be used are those from the global definition.** |
- | The next thing is to declare a map for the root style that controls how the widget colors will react to the various states like disabled, active, in focus, not in focus, and so on. Each item must be a list of tuples containing the state followed by the color, even if there is only one state that you are defining (bottom right). | + | Ensuite, nous devons définir les variables de couleur dont nous aurons besoin dans nos différentes fonctions. Je ne montrerai que quelques-unes des définitions, mais vous pouvez consulter le module lui-même. _bgcolor signifie couleur d' |
- | Now we can start defining the styles for each widget | + | Maintenant que toutes nos définitions globales sont faites, nous pouvons commencer avec notre première fonction |
- | As before, there can be a section for the map of the state to color, and then a section for the “normal” look. If you want to create a style for all the widgets of a particular class, as in the above snippet, you must use the default style name. That almost always begins with a “T”. | + | La fonction create_styles ne prend qu'un seul paramètre, une instance de ttk.Style(). Comme j'aime économiser autant de frappes que possible, j'ai nommé cette instance sty. |
+ | |||
+ | La première instruction configure crée un ensemble de définitions de couleurs qui sont dupliquées à partir des définitions globales. Celles-ci sont cependant censées être utilisées pour le style racine du thème, qui définit les jeux de couleurs pour chaque widget ttk utilisé dans le formulaire Toplevel. Cela ne semble pas fonctionner de cette manière en Python et les couleurs qui peuvent être utilisées sont celles de la définition globale. | ||
+ | |||
+ | |||
+ | **The next thing is to declare a map for the root style that controls how the widget colors will react to the various states like disabled, active, in focus, not in focus, and so on. Each item must be a list of tuples containing the state followed by the color, even if there is only one state that you are defining (bottom right). | ||
+ | |||
+ | Now we can start defining the styles for each widget (middle). I’ll show you only a few choice definitions to give you an idea how it’s done. Here’s the style for the Tbutton.** | ||
+ | |||
+ | La prochaine étape consiste à déclarer une carte pour le style racine qui contrôle la façon dont les couleurs des widgets réagiront aux différents états tels que désactivé, | ||
+ | |||
+ | Nous pouvons maintenant commencer à définir les styles pour chaque widget (au milieu). Je ne vous montrerai que quelques définitions de choix pour vous donner une idée de la façon de procéder. Voici le style du Tbutton (bouton T). | ||
+ | |||
+ | |||
+ | **As before, there can be a section for the map of the state to color, and then a section for the “normal” look. If you want to create a style for all the widgets of a particular class, as in the above snippet, you must use the default style name. That almost always begins with a “T”. | ||
When we want to set the attributes that we can’t normally set, we need to use the style.configure method. This allows us to set things like background and foreground colors, the padding (a list containing up to four integers for left, top, right and bottom in that order), font and so on. | When we want to set the attributes that we can’t normally set, we need to use the style.configure method. This allows us to set things like background and foreground colors, the padding (a list containing up to four integers for left, top, right and bottom in that order), font and so on. | ||
- | The TButton also has a special style built in called Toolbutton. This, as well, can be overridden by using the same configure and map settings (top right). | + | The TButton also has a special style built in called Toolbutton. This, as well, can be overridden by using the same configure and map settings (top right).** |
- | As always, when using images, we have to keep a “temporary” copy of the image object, so Python’s garbage collection doesn’t happily delete it. Now you can see how we use the os.path.join function to define the location of the image we want and the need to use the shared.py file. | + | Comme précédemment, |
+ | |||
+ | Lorsque nous voulons définir des attributs que nous ne pouvons pas définir normalement, | ||
+ | |||
+ | Le TButton possède également un style spécial appelé Toolbutton. Ce style peut également être remplacé en utilisant les mêmes paramètres de configuration et de carte (en haut à droite). | ||
+ | |||
+ | |||
+ | **As always, when using images, we have to keep a “temporary” copy of the image object, so Python’s garbage collection doesn’t happily delete it. Now you can see how we use the os.path.join function to define the location of the image we want and the need to use the shared.py file. | ||
Next, we need to create a custom element that holds the information on which image is used for which state. This, of course, will change for different widgets and for various element parts. You can create images that will be used to control the shape of the widget and so on (next page, top right). | Next, we need to create a custom element that holds the information on which image is used for which state. This, of course, will change for different widgets and for various element parts. You can create images that will be used to control the shape of the widget and so on (next page, top right). | ||
- | Finally, we have to define the layout. This is the REALLY difficult part. Typically, a widget consists of one or more elements. For the TCheckbutton, | + | Finally, we have to define the layout. This is the REALLY difficult part. Typically, a widget consists of one or more elements. For the TCheckbutton, |
+ | |||
+ | Comme toujours, lorsque nous utilisons des images, nous devons conserver une copie « temporaire » de l' | ||
+ | |||
+ | Ensuite, nous devons créer un élément personnalisé qui contient les informations sur l' | ||
+ | |||
+ | Enfin, nous devons définir la mise en page. C'est la partie VRAIMENT difficile. En général, un widget se compose d'un ou plusieurs éléments. Pour le bouton TCheckbutton, | ||
- | Finally, we can provide the map for the colors for each state (top left). | + | **Finally, we can provide the map for the colors for each state (top left). |
The styling module also provides a custom TRadiobutton definition. | The styling module also provides a custom TRadiobutton definition. | ||
Ligne 54: | Ligne 108: | ||
I won’t go through all the various ttk widgets that the styling module handles. I tried to deal with every standard ttk widget available. | I won’t go through all the various ttk widgets that the styling module handles. I tried to deal with every standard ttk widget available. | ||
- | In the process of creating the actual Tcl theme, I added a function that looked important, but I didn’t really know what it did. It didn’t cause anything to throw any errors, so I just left it in. Eventually, I was trying to clean out some of the unneeded code and I came back to the function that I didn’t know what it did. It wasn’t in all the themes that I looked at in my learning process so I decided to look up what it was for. Here is the code (top right). | + | In the process of creating the actual Tcl theme, I added a function that looked important, but I didn’t really know what it did. It didn’t cause anything to throw any errors, so I just left it in. Eventually, I was trying to clean out some of the unneeded code and I came back to the function that I didn’t know what it did. It wasn’t in all the themes that I looked at in my learning process so I decided to look up what it was for. Here is the code (top right).** |
- | It turns out that the tk_setPalette function was created to allow for the normally non-themeable Tk widgets to get a pseudo theme applied by letting the tk_setPalette function override the normal database for the Tk widgets. We’ll see more about this when we get into the demo program code, which we’ll do now. | + | Enfin, nous pouvons fournir la carte des couleurs pour chaque état (en haut à gauche). |
+ | |||
+ | Le module de style fournit également une définition personnalisée du bouton TRadiobutton. | ||
+ | |||
+ | Je ne vais pas passer en revue tous les widgets ttk gérés par le module de style. J'ai essayé de traiter tous les widgets ttk standard disponibles. | ||
+ | |||
+ | Lors de la création du thème Tcl, j'ai ajouté une fonction qui semblait importante, mais je ne savais pas vraiment ce qu' | ||
+ | |||
+ | |||
+ | **It turns out that the tk_setPalette function was created to allow for the normally non-themeable Tk widgets to get a pseudo theme applied by letting the tk_setPalette function override the normal database for the Tk widgets. We’ll see more about this when we get into the demo program code, which we’ll do now. | ||
Below is what the PAGE designer version of the demo program looks like. | Below is what the PAGE designer version of the demo program looks like. | ||
Ligne 62: | Ligne 125: | ||
You can see that I’ve created the program to use two Labelframes, | You can see that I’ve created the program to use two Labelframes, | ||
+ | In our demo program, we will skip all the normal imports and jump right into the startup function (bottom right).** | ||
- | In our demo program, we will skip all the normal imports and jump right into the startup function (bottom right). | + | Il s' |
- | You can see, we define our sty instance of the ttk.Style object, then we call the create_styles function of the styling module. Unfortunately, | + | Voici à quoi ressemble la version sur PAGE designer du programme de démonstration. |
- | Here is the fix_TLabels function. I get the background color from the styling module, then create a list of all the TLabel aliases. Then I simply walk through the list, applying the background color (next page, top right). | + | Vous pouvez voir que j'ai créé le programme pour utiliser deux Labelframes, l'un pour certains widgets Tk « génériques » et l' |
- | If you look back at the image of the program in the PAGE designer, you will notice two checkboxes near the top of the form near the left side. One is labeled “Show the surprise” and the other “Disable Widgets”. We’ll deal with the “Disable Widgets” callback first (bottom right). | + | Dans notre programme de démonstration, nous allons sauter toutes les importations normales et passer directement à la fonction de démarrage |
- | Again, I’m going to show only a portion of the widget list. Just like I did in the fix_Tlabels function, I created a list of the aliases of the widgets that I want to be able to control the disabled and normal states. This way, I can demonstrate the way the widgets respond in the different states. The actual list contains both the Tk and ttk widgets that respond to being disabled. I use variable che56, which PAGE assigned for me to find out if the checkbox is checked or not. Based on that, I walk through the widget list and set each widget to the proper disabled or normal state. | ||
- | Below is the program running. | + | **You can see, we define our sty instance of the ttk.Style object, then we call the create_styles function of the styling module. Unfortunately, |
+ | |||
+ | Here is the fix_TLabels function. I get the background color from the styling module, then create a list of all the TLabel aliases. Then I simply walk through the list, applying the background color (next page, top right).** | ||
+ | |||
+ | Comme vous pouvez le voir, nous définissons notre instance sty de l' | ||
+ | |||
+ | Voici la fonction fix_TLabels. Je récupère la couleur d' | ||
+ | |||
+ | |||
+ | **If you look back at the image of the program in the PAGE designer, you will notice two checkboxes near the top of the form near the left side. One is labeled “Show the surprise” and the other “Disable Widgets”. We’ll deal with the “Disable Widgets” callback first (bottom right). | ||
+ | |||
+ | Again, I’m going to show only a portion of the widget list. Just like I did in the fix_Tlabels function, I created a list of the aliases of the widgets that I want to be able to control the disabled and normal states. This way, I can demonstrate the way the widgets respond in the different states. The actual list contains both the Tk and ttk widgets that respond to being disabled. I use variable che56, which PAGE assigned for me to find out if the checkbox is checked or not. Based on that, I walk through the widget list and set each widget to the proper disabled or normal state.** | ||
+ | |||
+ | Si vous regardez l' | ||
+ | |||
+ | A nouveau, je ne vais afficher qu'une partie de la liste des widgets. Comme je l'ai fait dans la fonction fix_Tlabels, | ||
+ | |||
+ | |||
+ | **Below is the program running. | ||
Now you can see the styling module in “action”. The TCheckbuttons and the TRadiobuttons are using the custom graphics, and the other ttk widgets now have the common style. I set the TCombobox, the TEntry widget, and the TSpinbox to have a complimentary background color that isn’t the standard bright white. | Now you can see the styling module in “action”. The TCheckbuttons and the TRadiobuttons are using the custom graphics, and the other ttk widgets now have the common style. I set the TCombobox, the TEntry widget, and the TSpinbox to have a complimentary background color that isn’t the standard bright white. | ||
Ligne 79: | Ligne 160: | ||
Now we can look at the “Show The Surprise” checkbutton callback. The idea here is to call the tk_setPalette function to show the ability to use the style on the Tk widgets (next page, top right). | Now we can look at the “Show The Surprise” checkbutton callback. The idea here is to call the tk_setPalette function to show the ability to use the style on the Tk widgets (next page, top right). | ||
- | To be able to set the palette back to the “normal” Tk colors, I had to duplicate the set_palette function and then I set the colors back to the standard colors. | + | To be able to set the palette back to the “normal” Tk colors, I had to duplicate the set_palette function and then I set the colors back to the standard colors.** |
+ | Ci-dessous, voici le programme en cours d' | ||
- | Below is what it looks like when we have the “Show The Surprise” checkbutton and the “Disable Widgets” checkbutton selected at the same time. | + | Vous pouvez maintenant voir le module de style en action. Les boutons TCheckbuttons et TRadiobuttons utilisent les graphiques personnalisés et les autres widgets ttk ont maintenant le style commun. J'ai paramétré le TCombobox, le widget TEntry et le TSpinbox pour qu'ils aient une couleur d' |
+ | |||
+ | Nous pouvons maintenant examiner le rappel du bouton « Afficher la surprise ». L' | ||
+ | |||
+ | Pour pouvoir remettre la palette aux couleurs « normales » de Tk, j'ai dû dupliquer la fonction set_palette, | ||
+ | |||
+ | |||
+ | **Below is what it looks like when we have the “Show The Surprise” checkbutton and the “Disable Widgets” checkbutton selected at the same time. | ||
All the widgets now are not only themed, but disabled, and you can see that it’s pretty obvious that the widgets are disabled. Even if the Radiobutton or Checkbuttons are selected, you can still tell those that are selected. | All the widgets now are not only themed, but disabled, and you can see that it’s pretty obvious that the widgets are disabled. Even if the Radiobutton or Checkbuttons are selected, you can still tell those that are selected. | ||
Ligne 91: | Ligne 180: | ||
All the files for this project are located in my repository at https:// | All the files for this project are located in my repository at https:// | ||
- | Until next time, as always; stay safe, healthy, positive and creative! | + | Until next time, as always; stay safe, healthy, positive and creative!** |
+ | |||
+ | Voici ce qui se passe lorsque le bouton « Show The Surprise » (Afficher la surprise) et le bouton « Disable Wedgets » (Désactiver les widgets) sont cochés en même temps. | ||
+ | |||
+ | Tous les widgets sont maintenant non seulement thématisés, | ||
+ | |||
+ | La fonction set_Palette permet également de définir la couleur de la barre de menus. | ||
+ | |||
+ | Tous les fichiers de ce projet se trouvent dans mon dépôt à l' | ||
+ | |||
+ | Jusqu' | ||
+ | |||
+ | // Traduction des lignes noires de l' | ||
+ | |||
+ | **It took me a while to figure out how to get the whole custom image thing to work. | ||
+ | First, we need to define the images we want to use.** | ||
+ | |||
+ | Ça m'a pris du temps pour comprendre comment faire fonctionner toute la personnalisation d'une image. | ||
+ | D' | ||
+ | |||
+ | |||
+ | // Traduction de la ligne noire de l' | ||
+ | |||
+ | **Then we can handle the basic widget configuration of colors and so on.** | ||
+ | |||
+ | Ensuite, nous pouvons gérer la configuration des couleurs du widget de base et ainsi de suite. |
issue194/python.1688186808.txt.gz · Dernière modification : 2023/07/01 06:46 de d52fr