Outils pour utilisateurs

Outils du site


issue179:python

As most of you know, I work fairly closely with Don Rozenberg on his free GUI designer for Python programs called PAGE. Just the other day, I received the following message from SourceForge: “Congratulations! PAGE has just been recognized with the following awards by SourceForge: Community Leader Community Choice Open Source Excellence SourceForge Favorite These honors are awarded only to select projects that have reached significant milestones in terms of downloads and user engagement from the SourceForge community. This is a big achievement, as your project has qualified for these awards out of over 500,000 open source projects on SourceForge. SourceForge sees nearly 30 million users per month looking for, and developing, open source software. These award badges will now appear on your project page, and the award assets can be found in your project admin section.”

Comme la plupart d'entre vous le savent, je travaille en étroite collaboration avec Don Rozenberg sur son concepteur d'interface graphique libre pour les programmes Python appelé PAGE. L'autre jour, j'ai reçu le message suivant de SourceForge :

« Félicitations ! PAGE vient d'être reconnu par SourceForge avec les récompenses suivantes :

Leader de la communauté Choix de la communauté Excellence de l'Open Source Favoris de SourceForge

Ces distinctions sont attribuées uniquement à des projets sélectionnés qui ont atteint des étapes importantes en termes de téléchargements et d'engagement des utilisateurs de la communauté SourceForge.

C'est une grande réussite, car votre projet s'est qualifié pour ces prix parmi plus de 500 000 projets Open Source sur SourceForge. SourceForge compte près de 30 millions d'utilisateurs par mois qui recherchent et développent des logiciels libres. Ces badges de récompense apparaîtront désormais sur la page de votre projet, et les actifs de récompense peuvent être trouvés dans la section d'administration de votre projet. »

To celebrate this accomplishment, I decided to share some of the tricks and tips I’ve learned about using Tkinter to make easy GUI front ends for Python programs using PAGE. The neat thing about these tips is that they don’t require any special coding. It’s all done by setting the appropriate attributes. The first tip concerns enhancing the Tk Checkbutton. We all know what a “regular” checkbutton looks like. While this is an easy widget to use to represent a many-of-many set of options, this is pretty much an old style visual widget. But what about this? This is the image of a customized Checkbutton in the off state, and here is the same Checkbutton in the on state. It’s really easy to create a Checkbutton that looks and works like this using Tkinter and especially in PAGE. First, you need to have the two graphic images you want to use to represent the selected and unselected states. I went to my standard goto website for graphics, openclipart.org. I did a simple search for “switch” and this was one of the options. https://openclipart.org/detail/203164/ui-toggle-button I chose the small .png version, downloaded it and then used Gimp to cut each one out and saved them as separate .png files. I copied them into an images folder inside my project.

Pour fêter cette récompense, j'ai décidé de partager certains des trucs et astuces que j'ai appris sur l'utilisation de Tkinter pour créer des interfaces graphiques pour les programmes Python en utilisant PAGE. Ce qui est bien avec ces astuces, c'est qu'elles ne nécessitent aucun codage spécial. Tout se fait en définissant les attributs appropriés.

La première astuce concerne l'amélioration du bouton de contrôle Tk, le Tk Checkbutton. Nous savons tous à quoi ressemble une case à cocher « normale ».

Bien qu'il s'agisse d'un widget facile à utiliser pour représenter un ensemble d'options multiples, il s'agit plutôt d'un widget visuel de style ancien. Mais qu'en est-il de ceci ?

Voici l'image d'un bouton à cocher personnalisé à l'état désactivé, et voici le même bouton à cocher à l'état activé.

Il est très facile de créer un bouton de contrôle qui ressemble et fonctionne comme celui-ci en utilisant Tkinter, surtout dans PAGE. D'abord, vous devez avoir les deux images graphiques que vous voulez utiliser pour représenter les états sélectionné et non sélectionné. Je suis allé sur mon site habituel pour les graphiques, openclipart.org. J'ai fait une recherche simple pour « switch » (interrupteur) et ceci était l'une des possibilités.

https://openclipart.org/detail/203164/ui-toggle-button

J'ai choisi la petite version .png, je l'ai téléchargée, puis j'ai utilisé Gimp pour découper chacune d'entre elles et les enregistrer en tant que fichiers .png séparés. Je les ai copiés dans un dossier d'images dans mon projet.

Next, I simply placed a standard Tk Checkbutton on the Toplevel form, next to a few other Checkbuttons and I set the attributes using the PAGE Attribute Editor (see table, previous page, bottom right). When the program is run, the Custom checkbutton will act as a toggle switch. There is one other trick that can be used with the Checkbutton, and no images are needed. It turns the Checkbutton into a “sticky” button. When it is unselected, it looks very much like a standard button. When it is selected (clicked), the button stays depressed until it is clicked again. Here is the “unselected” state. And this is the selected state. You can pick to have a color in the unselected state or not. I chose to use coral for the unselected and limegreen for the selected color. Just like the Checkbutton, you will need to set the indicator to No (see table below). The next trick is to modify the standard Tk Radiobutton to provide a custom indicator dot. As with the Checkbutton trick, you will need two graphics. One for the indicator when it is not selected and one for when it is selected.

Ensuite, j'ai simplement placé un bouton à cocher Tk standard sur le formulaire Toplevel, à côté de quelques autres boutons à cocher et j'ai défini les attributs à l'aide de l'éditeur d'attributs PAGE (voir tableau, page précédente, en bas à droite).

Lorsque le programme est exécuté, le bouton à cocher personnalisé agira comme un interrupteur à bascule.

Il existe une autre astuce qui peut être utilisée avec le bouton à cocher, et aucune image n'est nécessaire. Elle transforme le bouton à cocher en un bouton « à verrouillage ». Lorsqu'il n'est pas sélectionné, il ressemble beaucoup à un bouton standard. Lorsqu'il est sélectionné (cliqué), le bouton reste enfoncé jusqu'à ce qu'il soit cliqué à nouveau. Voici l'état « non sélectionné ».

Et voici l'état « sélectionné ».

Vous pouvez choisir d'avoir une couleur dans l'état non sélectionné ou non. J'ai choisi d'utiliser la couleur corail pour l'état non sélectionné et le vert tilleul pour l'état sélectionné. Tout comme pour le bouton de contrôle, vous devez définir Indicator à No (voir le tableau ci-dessous).

L'astuce suivante consiste à modifier le bouton radio standard de Tk pour fournir un point indicateur personnalisé. Comme pour l'astuce du bouton de contrôle, vous aurez besoin de deux graphiques. Un pour l'indicateur lorsqu'il n'est pas sélectionné et un pour lorsqu'il est sélectionné.

As I’ve stated many times in the past, I am not an artist in any way, shape or form. I threw together the following images to help show the process. First the unselected image. It’s simply a circle. And the selected image, which is the circle above with a black dot in the middle. Just like we did with the Checkbuttons, we set the attributes as follows (top right). The only thing that is a downside for this trick is that (as you can see in the image below) the Radiobutton goes to a sunken relief. As far as I can tell, there’s nothing that we can do about that (but you know I won’t give up trying). So here is what the full demo project looks like (next page, top right).

Comme je l'ai dit à plusieurs reprises dans le passé, je ne suis pas un artiste de quelque manière que ce soit. J'ai rassemblé les images suivantes pour aider à montrer le processus.

D'abord l'image non sélectionnée. C'est un simple cercle.

Et l'image sélectionnée, qui est le cercle ci-dessus avec un point noir au milieu.

Comme nous l'avons fait pour les boutons de contrôle, nous avons défini les attributs comme suit (en haut à droite).

La seule chose qui est un inconvénient pour cette astuce est que (comme vous pouvez le voir dans l'image ci-dessous) le bouton radio prend du relief en creux. Pour autant que je puisse dire, il n'y a rien que nous puissions faire à ce sujet (mais vous savez que je ne renoncerai pas à essayer).

Voici donc à quoi ressemble le projet de démonstration complet (page suivante, en haut à droite).

As to the code, it’s really very simple. def startup(): _w1.Checkbutton1.invoke() _w1.Radiobutton1.invoke() _w1.Radiobutton3.invoke() The startup function calls the .invoke method of the first Checkbutton and the first and third Radiobuttons. The invoke method makes the program think that there was a mouse-click on the widget, that then calls the associated command callback function. I wanted to show the first widget of each group to be selected on start up. def on_chkbtnClick(*args): status_list = ['Off', 'ON'] cb1 = _w1.che47.get() cb2 = _w1.che48.get() cb3 = _w1.che49.get() cb4 = _w1.che50.get() _w1.CheckDisplay.set( f'{status_list[cb1]} - {status_list[cb2]} - {status_list[cb3]} - {status_list[cb4]}' )

  
  Quant au code, il est vraiment très simple.

def startup() :

  _w1.Checkbutton1.invoke()
  _w1.Radiobutton1.invoke()
  _w1.Radiobutton3.invoke()

La fonction de démarrage appelle la méthode .invoke du premier bouton à cocher et des premier et troisième boutons radios. La méthode invoke fait croire au programme qu'il y a eu un clic de souris sur le widget, ce qui appelle alors la fonction de rappel de la commande associée. Je voulais que le premier widget de chaque groupe soit sélectionné au démarrage.

def on_chkbtnClick(*args) :

  status_list = ['Off', 'ON']
  cb1 = _w1.che47.get()
  cb2 = _w1.che48.get()
  cb3 = _w1.che49.get()
  cb4 = _w1.che50.get()
  _w1.CheckDisplay.set(
      f'{status_list[cb1]} - {status_list[cb2]} - {status_list[cb3]} {status_list[cb3]} - {status_list[cb4]}'
  )
  

The callback for the Checkbuttons is really simple. The first thing that gets done is to create a very simple list with the text values ‘Off’ and ‘On’ which will be shown as part of a string that will be sent to the display label. Next each of the variables for the Checkbuttons show 0 for unselected and 1 for selected. Those values work nicely as a “pointer” into the list for the display string. Finally we create the string and send it to the label to be displayed. The next two callbacks are for when the Radibutton groups are clicked. The first two (top two) Radiobuttons on the form are handled by the top function and the bottom two custom Radiobuttons are handled by the second function. def on_rbtnClick1(*args): which1 = _w1.selectedButton.get() _w1.RadioDisplay.set(f'Normal RB {which1} Selected') def on_rbtnClick2(*args): which2 = _w1.selectedButton2.get() _w1.RadioDisplay.set(f'Special Rb {which2} Selected')

  
  Le rappel des boutons de contrôle est vraiment simple. La première chose qui est faite est de créer une liste très simple avec les valeurs de texte « Off » et « On » qui seront affichées dans le cadre d'une chaîne qui sera envoyée à l'étiquette d'affichage. Ensuite, chacune des variables des boutons de contrôle affiche 0 pour non sélectionné et 1 pour sélectionné. Ces valeurs fonctionnent bien comme un « pointeur » dans la liste pour la chaîne d'affichage. Enfin, nous créons la chaîne et l'envoyons à l'étiquette pour qu'elle soit affichée.

Les deux rappels suivants s'appliquent lorsque les groupes de boutons radios sont cliqués. Les deux premiers boutons radios du formulaire sont gérés par la fonction du haut et les deux boutons radios personnalisés du bas sont gérés par la deuxième fonction.

def on_rbtnClick1(*args) :

  which1 = _w1.selectedButton.get()
  _w1.RadioDisplay.set(f'Normal RB {which1} Selected')

def on_rbtnClick2(*args) :

  which2 = _w1.selectedButton2.get()
  _w1.RadioDisplay.set(f'Special Rb {which2} Selected')
  

That’s all I have time for this month. Remember these tips are for “standard” Tk widgets. Yes, there are ttk widgets that can have styles and themes applied to them. The problem with styles and themes are: • Styles and themes are poorly documented • Styles and themes require special programming in Tcl/Tk • Much of the documentation on styles and themes is incomplete • AND (from what I’ve been told) many things are downright wrong! The PAGE source (version 7.3) and the Python code are all available on my repository. You can find it at https://github.com/gregwa1953/FCM-179 . Until next time, as always; stay safe, healthy, positive and creative!

C'est tout ce que j'ai le temps de faire ce mois-ci. Rappelez-vous que ces conseils concernent les widgets Tk « standard ». Oui, il existe les widgets ttk auxquels on peut appliquer des styles et des thèmes. Le problème avec les styles et les thèmes est que :

- Les styles et les thèmes sont mal documentés. - Les styles et les thèmes nécessitent une programmation spéciale en Tcl/Tk. - Une grande partie de la documentation sur les styles et les thèmes est incomplète. - ET (d'après ce qu'on m'a dit) beaucoup de choses sont carrément fausses !

La source PAGE (version 7.3) et le code Python sont tous disponibles sur mon dépôt. Vous pouvez le trouver à https://github.com/gregwa1953/FCM-179 .

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

issue179/python.txt · Dernière modification : 2022/03/30 17:43 de andre_domenech