Outils pour utilisateurs

Outils du site


issue183:python

Sorry about not being able to continue the topic last month, but we are back. Let’s jump right into the project where we left on in issue #181. Here is what the latest version of the program looks like (image shown bottom right) Just to remind you, there are three possible color settings for most widgets. A Selected Background color, an Active Background color, and an Inactive Background color. Here is how they work… For the most part, this all pertains to the TNotebook Tabs, but have “carry overs” into most other widgets as well. Select Background Color - The background color of the tab (widget) you are currently on Active Background Color - The background of the tab (widget) the mouse is hovering over Inactive Background Color - The background of all other tabs (widgets) Most of the action happens within the TNotebook. There are three main panels (all TLableframes (ttk::Labelframes)) that hold the widgets that we will need to make the project work. From left to right, we have the background colors, the foreground colors, and a small sampling of various widgets that will act as a preview, showing how the colors will look.

Désolé de ne pas avoir pu poursuivre le sujet le mois dernier, mais nous sommes de retour. Reprenons le projet là où nous l'avons laissé dans le numéro 181. Voici à quoi ressemble la dernière version du programme (image en bas à droite).

Juste pour vous rappeler qu'il y a trois paramètres de couleurs possibles pour la plupart des widgets. Une couleur de fond sélectionnée, une couleur de fond active et une couleur de fond inactive. Voici comment ils fonctionnent…

Pour l'essentiel, cela concerne les onglets de TNotebook, mais il y a aussi des « reports » dans la plupart des autres widgets. Couleur d'arrière-plan sélectionné - La couleur d'arrière-plan de l'onglet (widget) sur lequel vous vous trouvez actuellement. Couleur d'arrière-plan actif - La couleur d'arrière-plan de l'onglet (widget) sur lequel la souris se trouve. Couleur d'arrière-plan inactif - L'arrière-plan de tous les autres onglets (widgets).

La plupart des actions se déroulent dans TNotebook. Il y a trois panneaux principaux (tous des TLableframes (ttk::Labelframes)) qui contiennent les widgets dont nous aurons besoin pour faire fonctionner le projet. De gauche à droite, nous avons les couleurs d'arrière-plan, les couleurs d'avant-plan, et un petit échantillon de divers widgets qui serviront d'aperçu, montrant à quoi ressembleront les couleurs.

Taking a closer look at the background colors TLableframe (the foreground works almost exactly the same, except for dealing with the foreground colors), we’ll concentrate on the background panel right now. We have three static text widgets (ttk::Labels), three Entry widgets (ttk:Entries), and three Buttons (Standard Tk::Buttons). Between the Entry widgets and the buttons, we can pick the colors we want to try. All three buttons have the same basic callback command function (lambda : on_bgColor(x) where x is the number of the button). This allows any of the three buttons to call the same function, with a different index, so the program knows which Button made the call. The buttons will call the ColorSelect dialog. If you know what color you want, you can put the color directly into the Entry box of the Labelframe or use the dialog. The dialog also lets you use the sliders or direct entry into the Entry box. Here is what you need to use the ColorSelect dialog. First, you need to import it from Tkinter. import tkinter.colorchooser as colorchooser Then, when you want the colorchooser dialog to be shown, the syntax is: result = tkColorChooser.askcolor(color, option=value, …)

En regardant de plus près les couleurs d'arrière-plan de TLabelframe (l'avant-plan fonctionne presque exactement de la même manière, à l'exception du traitement des couleurs d'avant-plan), nous allons nous concentrer sur le panneau d'arrière-plan pour le moment.

Nous avons trois widgets de texte statique (ttk::Labels), trois widgets d'entrée (ttk:Entries) et trois boutons (Standard Tk::Buttons). Entre les widgets Entry et les boutons, nous pouvons choisir les couleurs que nous voulons essayer. Les trois boutons ont la même fonction de commande de rappel de base (lambda : on_bgColor(x) où x est le numéro du bouton). Cela permet à n'importe lequel des trois boutons d'appeler la même fonction, avec un index différent, afin que le programme sache quel bouton a fait l'appel. Les boutons appellent la boîte de dialogue ColorSelect. Si vous connaissez la couleur que vous voulez, vous pouvez la saisir directement dans la zone d'entrée de Labelframe ou utiliser la boîte de dialogue. La boîte de dialogue vous permet également d'utiliser les curseurs ou de saisir directement dans la zone d'entrée.

Voici ce dont vous avez besoin pour utiliser la boîte de dialogue ColorSelect.

D'abord, vous devez l'importer de Tkinter.

import tkinter.colorchooser as colorchooser

Ensuite, quand vous voulez que le dialogue colorSelect soit montré, la syntaxe est :

result = tkColorChooser.askcolor(color, option=value, …)

The parameters are: Color - The initial color that the dialog will show. If you leave it blank, it will default to light gray. Title - The title for the dialog window Parent - The Toplevel form you wish the dialog to appear over. Usually, this would be your main form. The return value comes back as a tuple that comes in as (triple, color) – assuming the user clicks the Ok button. Triple is itself a tuple of (Red, Green, Blue) values (in the range of [0, 255]) and color is the regular Tkinter hex value object. If the user clicks the Cancel button, the return value will be (None,None). When the dialog is shown, the user can use the sliders to create a color they like, enter a hex value (starting with “#”) into the entry box, or enter one of the predefined Tkinter colors as a string (like “sky blue”). Any time you enter something into the entry box of the dialog, you MUST press the Enter key to “set” the information before you click the ok button (top right).

Les paramètres sont les suivants : Color - La couleur initiale que la boîte de dialogue affichera. Si vous laissez ce paramètre vide, la couleur par défaut sera le gris clair. Title - Le titre de la fenêtre de dialogue. Parent - Le formulaire de niveau supérieur sur lequel vous souhaitez que la boîte de dialogue apparaisse. En général, il s'agit de votre formulaire principal.

La valeur de retour est un tuple qui se présente sous la forme (triple, couleur) - en supposant que l'utilisateur clique sur le bouton OK. Ce triple est lui-même un tuple de valeurs (Rouge, Vert, Bleu) (dans la gamme de [0, 255]) et la couleur est l'objet Tkinter ordinaire en valeur hexadécimale. Si l'utilisateur clique sur le bouton Annuler, la valeur de retour sera (None,None).

Lorsque le dialogue est affiché, l'utilisateur peut utiliser les curseurs pour créer une couleur qu'il aime, entrer une valeur hexagonale (commençant par « # ») dans la boîte de saisie, ou entrer une des couleurs de Tkinter prédéfinies comme une chaîne (comme « bleu ciel »). Chaque fois que vous entrez quelque chose dans la zone de saisie de la boîte de dialogue, vous DEVEZ appuyer sur la touche Entrée pour « définir » l'information avant de cliquer sur le bouton OK (en haut à droite).

The TEntry widgets each have a textvar that allows the program to find the entered data simply and they are TEntry1Data, TEntry2Data and TEntry3Data. I’ve bound the three TEntry widgets to the same callback function whenever a key is pressed on the keyboard and the widget is in focus. In this function, we are only looking for the <Return> key, Then we simply read the text var to see what the user has entered. Now let’s look at some of the code that is attached to the buttons. Remember, we call the code as on_bgColor(n) where n is the value we gave the button. For the most part, the first portion of the code is generated by PAGE, showing each of the values passed into the function. I added the global statement and the if debug: portion of the code, so I can hide the value printout when I’m done with debugging. Next we look at the argument being passed in (which is the number of the button) and get the last color that was assigned to that background color group from the globals. This gives us the starting color for the Color Select dialog based on which of the three background colors we wish to work on.

Les widgets TEntry possèdent chacun une variable texte qui permet au programme de retrouver simplement les données saisies. Il s'agit de TEntry1Data, TEntry2Data et TEntry3Data. J'ai lié les trois widgets TEntry à la même fonction de rappel dès qu'on appuie sur une touche du clavier et que le widget est en focus. Dans cette fonction, nous ne recherchons que la touche <Return>, puis nous lisons simplement la variable texte pour voir ce que l'utilisateur a saisi.

Examinons maintenant une partie du code qui est attaché aux boutons. Rappelez-vous que nous appelons le code on_bgColor(n) où n est la valeur que nous avons donnée au bouton.

Pour l'essentiel, la première partie du code est générée par PAGE, montrant chacune des valeurs passées dans la fonction. J'ai ajouté l'instruction globale et la partie if debug: du code, afin de pouvoir masquer l'impression des valeurs lorsque j'en ai fini avec le débogage.

Ensuite, nous examinons l'argument transmis (qui est le numéro du bouton) et nous obtenons la dernière couleur qui a été attribuée à ce groupe de couleurs d'arrière-plan à partir des données globales. Cela nous donne la couleur de départ pour la boîte de dialogue de sélection des couleurs en fonction de la couleur d'arrière-plan sur laquelle nous souhaitons travailler.

We simply use an if statement to check the value passed in. which = args[0] if which == 1: colr = lastbg1 elif which == 2: colr = lastbg2 elif which == 3: colr = lastbg3 Simple enough, right? Now that we have the basic data, we can call the colorchooser dialog. result = colorchooser.askcolor( colr, title=f“Enter Color for Background #{which}”, parent=root) We set the starting color, the title of the dialog, and the name of the parent Toplevel so the dialog gets centered properly. The response from the user comes back as the variable result.

Nous utilisons simplement une instruction if pour vérifier la valeur transmise :

  which = args[0]
  if which == 1:
      colr = lastbg1
  elif which == 2:
      colr = lastbg2
  elif which == 3:
      colr = lastbg3

C'est assez simple, non ? Maintenant que nous avons les données de base, nous pouvons appeler la boîte de dialogue colorchooser :

result = colorchooser.askcolor(

 colr, title=f "Enter Color for Background #{which}", parent=root)

Nous définissons la couleur de départ, le titre de la boîte de dialogue, et le nom du parent Toplevel pour que la boîte de dialogue soit centrée correctement. La réponse de l'utilisateur revient sous la forme de la variable result.

Since the dialog returns two values (the first being a tuple containing R,G and B value, and the second returning the hex value of the color chosen), we need to check at least one of the two values. Tkinter doesn’t allow for the RGB values to be used directly, so we want to check the hex value which comes in as the second value. In addition, the values can be either valid color values or two None values. I opted to check the second value, which is what we will be using to set the color if there is a value there. The first thing we to do is make sure that the user didn’t click the Cancel button (bottom left). If the returned value is not None, we then set the hex value into the TEntry widget and set the background color of the button to visually show the color that was chosen. The same code is basically used for the other two possible button/TEntry combinations. Then, finally we call the root.update() function just to make sure everything looks right (bottom right).

Puisque le dialogue retourne deux valeurs (la première étant un tuple contenant les valeurs R, G et B, et la seconde retournant la valeur hexadécimale de la couleur choisie), nous devons vérifier au moins une des deux valeurs. Tkinter ne permet pas d'utiliser directement les valeurs RGB, donc nous voulons vérifier la valeur hexadécimale qui arrive comme deuxième valeur. De plus, les valeurs peuvent être, soit des valeurs de couleurs valides, soit deux valeurs None. J'ai choisi de vérifier la deuxième valeur, qui est celle que nous utiliserons pour définir la couleur, s'il y a une valeur. La première chose à faire est de s'assurer que l'utilisateur n'a pas cliqué sur le bouton Annuler (en bas à gauche).

Si la valeur renvoyée n'est pas None, nous plaçons la valeur hexadécimale dans le widget TEntry et définissons la couleur d'arrière-plan du bouton pour afficher visuellement la couleur choisie. Le même code est utilisé pour les deux autres combinaisons possibles bouton/TEntry. Enfin, nous appelons la fonction root.update() pour nous assurer que tout semble correct (en bas à droite).

The Foreground color (the text color) is basically the same process, so we’ll skip it here for this month. So here is what a simple color combination works out to be. Selected Background is Tab 1, Tab 2 is the Active background (where the mouse is hovering), and Tabs 3 through 5 are the Inactive Backgrounds. In order to get the colors to actually be applied to the widgets, we need to apply the colorsets. Looking back at the full image of the form, there is a button called “Apply Colors”. This has a callback that simply calls a function called set_colors(). Since I originally designed this to deal with ttk widgets, we need to start by calling the ttk.Style() to get a default style structure. def set_colors(): global lastbg1, lastbg2, lastbg3, lastfg1, lastfg2, lastfg3 # ================================================= style = ttk.Style() In order to manipulate any of the styles for any of the ttk widgets, we have to modify the style.map structure. Since we want to change the TNotebook tabs first, we start there (top right).

La couleur d'avant-plan (la couleur du texte) suit fondamentalement le même processus ; nous allons donc l'ignorer pour ce mois-ci. Voici donc ce que donne une simple combinaison de couleurs. L'arrière-plan sélectionné est l'onglet 1, l'onglet 2 est l'arrière-plan actif (là où la souris se trouve) et les onglets 3 à 5 sont les arrière-plans inactifs.

Pour que les couleurs soient réellement appliquées aux widgets, nous devons appliquer les jeux de couleurs.

En regardant l'image complète du formulaire, il y a un bouton appelé « Apply Colors ». Il possède un callback qui appelle simplement une fonction appelée set_colors(). Puisque j'ai conçu cette fonction à l'origine pour traiter les widgets ttk, nous devons commencer par appeler la fonction ttk.Style() pour obtenir une structure de style par défaut :

def set_colors() :

  global lastbg1, lastbg2, lastbg3, lastfg1, lastfg2, lastfg3
  # =================================================
  style = ttk.Style()

Afin de manipuler n'importe quel style pour n'importe quel widget ttk, nous devons modifier la structure style.map. Comme nous voulons d'abord modifier les onglets de TNotebook, nous commençons par là (en haut à droite).

Each ttk widget has a different set of states that can be set. These can include states like “Active”, “Disabled”, “Background” and more. You can see that we set the three background and three foreground color values above. What is not obvious from the documentation on ttk Style manipulation is the inactive state. “Selected” and “Active” are all obvious, but there is the “!active” state, which is the inactive state (when the widget is just sitting there without the mouse doing anything around it). As I said, every widget is different as to the states that it will support. For example, the TButton has an “Active”, a “Disabled” and a “Readonly” state, all of which have separate attributes that can be set (bottom left). Many of the ttk widgets also need to be configured, sort of like the “standard” Tk widgets do, to set many of the various attributes available. To do this, we need to create a “generic” style for that widget, then apply it using the style attribute. (Gets somewhat confusing, huh?.

Chaque widget ttk possède un ensemble différent d'états qui peuvent être définis. Il peut s'agir d'états tels que « Active », « Disabled », « Background » et plus encore. Vous pouvez voir que nous avons défini les trois valeurs de couleur d'arrière-plan et d'avant-plan ci-dessus. Ce qui n'est pas évident dans la documentation sur la manipulation de ttk Style, c'est l'état inactif. Les états « Selected » et « Active » sont évidents, mais il y a l'état « !active », qui est l'état inactif (lorsque le widget est juste posé là sans que la souris ne fasse quoi que ce soit autour de lui).

Comme je l'ai dit, chaque widget est différent quant aux états qu'il supporte. Par exemple, le TButton a un état « Active », un « Disabled » et un « Readonly », qui ont tous des attributs séparés qui peuvent être définis (en bas à gauche).

La plupart des widgets ttk doivent également être configurés, un peu comme les widgets Tk « standard », pour définir les différents attributs disponibles. Pour ce faire, nous devons créer un style « générique » pour ce widget, puis l'appliquer en utilisant l'attribut style. (C'est un peu confus, non ?).

We do this by using the style.configure function, starting with our named style along with the widget, then set the attributes as we want them, then finally applying the style via the style attribute (bottom right). You can do this with many of the “normal” attributes that you don’t get to change within PAGE, since any ttk widget can have any style available. Imagine having 100 ttk widgets each with its own style. It can be done! Enough theory for this month. Next month, we’ll look at saving the colorsets into something that we can use and apply, and a way to write this information out so we can use it within other programs in a very simple way. Until next time, as always; stay safe, healthy, positive and creative!

Nous le faisons en utilisant la fonction style.configure, en commençant par notre style nommé avec le widget, puis en définissant les attributs comme nous les voulons, et enfin en appliquant le style via l'attribut style (en bas à droite).

Vous pouvez faire cela avec de nombreux attributs « normaux » que vous ne pouvez pas modifier dans PAGE, puisque n'importe quel widget ttk peut avoir n'importe quel style disponible. Imaginez 100 widgets ttk, chacun avec son propre style. C'est possible !

Assez de théorie pour ce mois-ci. Le mois prochain, nous verrons comment sauvegarder les jeux de couleurs dans quelque chose que nous pouvons utiliser et appliquer, et comment écrire cette information pour pouvoir l'utiliser dans d'autres programmes d'une manière très simple.

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

issue183/python.txt · Dernière modification : 2022/08/02 15:10 de andre_domenech