issue175:python
Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
issue175:python [2021/11/28 13:12] – créée auntiee | issue175:python [2021/12/03 14:47] (Version actuelle) – andre_domenech | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | A few weeks ago, one of my Python newsfeeds alerted me about a neat new project – one that creates a still video image that is downloaded from NASA (National Aeronautics and Space Administration) every 45 seconds or so and displays it in the application’s GUI window. | + | **A few weeks ago, one of my Python newsfeeds alerted me about a neat new project – one that creates a still video image that is downloaded from NASA (National Aeronautics and Space Administration) every 45 seconds or so and displays it in the application’s GUI window. |
I thought that was a neat idea, so I jumped to the website and started reading. It seems that the author decided to use PySimpleGUI to make the GUI form, which is a program that I’m not really familiar with. I took a look at his screenshot of the GUI and I thought that I could create a comparable version using PAGE. I took up the challenge and thought that it would be a good project to present here. So I present my version of Spacestills.py. | I thought that was a neat idea, so I jumped to the website and started reading. It seems that the author decided to use PySimpleGUI to make the GUI form, which is a program that I’m not really familiar with. I took a look at his screenshot of the GUI and I thought that I could create a comparable version using PAGE. I took up the challenge and thought that it would be a good project to present here. So I present my version of Spacestills.py. | ||
- | The author’s blog is at https:// | + | The author’s blog is at https:// |
- | We’ll be using two external Python libraries. You might already have them. They are requests and PIL (pillow). If you don’t have them, you can use pip to install them. They have to be on your system before you try to run the project. | + | Il y a quelques semaines, l'un de mes fils d' |
+ | |||
+ | J'ai pensé que c' | ||
+ | |||
+ | Le blog de l' | ||
+ | |||
+ | |||
+ | **We’ll be using two external Python libraries. You might already have them. They are requests and PIL (pillow). If you don’t have them, you can use pip to install them. They have to be on your system before you try to run the project. | ||
Here is what my version of his project looks like during a running session. | Here is what my version of his project looks like during a running session. | ||
Ligne 11: | Ligne 18: | ||
I decided to make a little bit more space between the rows of user accessible widgets, since my mousing hand has a tendency to shake a bit. We’ll start to create the GUI in PAGE. | I decided to make a little bit more space between the rows of user accessible widgets, since my mousing hand has a tendency to shake a bit. We’ll start to create the GUI in PAGE. | ||
- | Just in case you don’t have PAGE, you can get it at https:// | + | Just in case you don’t have PAGE, you can get it at https:// |
- | Let’s look at some of the requirements that we need to keep in mind during the design process. The images that come in from the Internet will be 704x480 pixels. The shortest time between the images is 45 seconds. This information came from the author's blog page as well as his code (his blog page states the image size is 704x408, but the actual image and his code is 704x480). The only code of his that I used are a few of his constants. The rest of the code for this project is code that I have used in previous projects. His project allows the end user to select the time between | + | Nous utiliserons deux bibliothèques Python externes. Vous les avez peut-être déjà. Il s'agit de requests |
- | So start up PAGE, and resize the default Toplevel designer window to about 777 pixels wide and 657 high. Don’t be too concerned about the actual dimensions of the main form, just get it close. Now move the form to somewhere in the middle of your screen. Set the title attribute in the Attribute Editor to “NasaStills-tk”. While we are in the Attribute Editor, set the background color to “skyblue4”. This is a nice dark bluish gray color. | + | Voici à quoi ressemble ma version de son projet pendant une session qui tourne. |
+ | |||
+ | J'ai décidé de faire un peu plus d' | ||
+ | |||
+ | Au cas où vous n' | ||
+ | |||
+ | |||
+ | **Let’s look at some of the requirements that we need to keep in mind during the design process. The images that come in from the Internet will be 704x480 pixels. The shortest time between the images is 45 seconds. This information came from the author' | ||
+ | |||
+ | Examinons quelques-unes des exigences que nous devons garder à l' | ||
+ | |||
+ | |||
+ | **So start up PAGE, and resize the default Toplevel designer window to about 777 pixels wide and 657 high. Don’t be too concerned about the actual dimensions of the main form, just get it close. Now move the form to somewhere in the middle of your screen. Set the title attribute in the Attribute Editor to “NasaStills-tk”. While we are in the Attribute Editor, set the background color to “skyblue4”. This is a nice dark bluish gray color. | ||
Next, we’ll put a frame widget into the Toplevel form. This will hold the Label widget that we will use to display the still image from the Nasa site. Place it near the top-left of the main form. Don’t worry too much about the placement at this point. Using the Attribute Editor again, make sure that the frame is selected, and set the width to 714 and the height to 492. Next, add a Label widget and set the X and Y position in the Attribute editor to 2 and 2. This will provide a nice little border around the Label widget when it is set to its full size. Set the width of the Label to 704, the height to 488, and the background color to “skyblue3”. This gives us a nice color for the visual inner display area. Set the Alias of the Label widget to “labelImage”, | Next, we’ll put a frame widget into the Toplevel form. This will hold the Label widget that we will use to display the still image from the Nasa site. Place it near the top-left of the main form. Don’t worry too much about the placement at this point. Using the Attribute Editor again, make sure that the frame is selected, and set the width to 714 and the height to 492. Next, add a Label widget and set the X and Y position in the Attribute editor to 2 and 2. This will provide a nice little border around the Label widget when it is set to its full size. Set the width of the Label to 704, the height to 488, and the background color to “skyblue3”. This gives us a nice color for the visual inner display area. Set the Alias of the Label widget to “labelImage”, | ||
- | Now we will finish the placement of the Frame and Label combo. PAGE has a feature that allows you to select multiple widgets and manipulate them as a group, like centering horizontally or vertically, equally spacing them within their parent, and so on. At this point, we want to just center the frame within the main form horizontally. In the Widget Tree, use the middle mouse button to click on the Frame: Frame1 entry. | + | Now we will finish the placement of the Frame and Label combo. PAGE has a feature that allows you to select multiple widgets and manipulate them as a group, like centering horizontally or vertically, equally spacing them within their parent, and so on. At this point, we want to just center the frame within the main form horizontally. In the Widget Tree, use the middle mouse button to click on the Frame: Frame1 entry.** |
- | Notice that it turns green. The black resize handles of the Frame in the main form also turn green to let you know you are in the multi-select mode. We need to select only the Frame, since it is the parent of the image label. Now right-click on the Frame/Image combo in the main form. You will see a context menu appear. | + | Lancez donc PAGE, et redimensionnez la fenêtre par défaut du concepteur Toplevel à environ 777 pixels de large et 657 de haut. Ne vous préoccupez pas trop des dimensions réelles du formulaire principal, il suffit qu' |
+ | |||
+ | Ensuite, nous allons placer un widget de cadre dans le formulaire Toplevel. Il contiendra le widget Label que nous utiliserons pour afficher l' | ||
+ | |||
+ | Nous allons maintenant terminer le placement de la combinaison Cadre et Étiquette. PAGE dispose d'une fonction qui vous permet de sélectionner plusieurs widgets et de les manipuler en tant que groupe, par exemple en les centrant horizontalement ou verticalement, | ||
+ | |||
+ | |||
+ | **Notice that it turns green. The black resize handles of the Frame in the main form also turn green to let you know you are in the multi-select mode. We need to select only the Frame, since it is the parent of the image label. Now right-click on the Frame/Image combo in the main form. You will see a context menu appear. | ||
Select Center Horizontal from the menu. The Frame will now be centered in the form horizontally. Click Unselect MS in the Widget Tree window. I set the top of my Frame to 10 pixels down from the top of the form (Y position). It’s time to save your project. Name it “NasaStills.tcl”. | Select Center Horizontal from the menu. The Frame will now be centered in the form horizontally. Click Unselect MS in the Widget Tree window. I set the top of my Frame to 10 pixels down from the top of the form (Y position). It’s time to save your project. Name it “NasaStills.tcl”. | ||
Ligne 27: | Ligne 53: | ||
Now we can start to place the rest of the widgets on our form. We’ll place the first of two Checkbuttons next. Be sure to make it a Tk Checkbutton, | Now we can start to place the rest of the widgets on our form. We’ll place the first of two Checkbuttons next. Be sure to make it a Tk Checkbutton, | ||
- | I’ll give you the attributes you will want to set in the grid below. | + | I’ll give you the attributes you will want to set in the grid below.** |
- | Some information about these attributes. By setting the Active Background (active bg) and select color attributes, we control the colors when the mouse is over the widget (active bg) as well as the color when the status is Checked (select color). Setting the foreground color to antiquewhite2, | + | Remarquez qu'il devient vert. Les poignées de redimensionnement noires du cadre dans le formulaire principal deviennent également vertes pour vous indiquer que vous êtes en mode de sélection multiple. Nous devons sélectionner uniquement le cadre, car il est le parent de l' |
+ | |||
+ | Sélectionnez Center Horizontal dans le menu. Le cadre sera maintenant centré horizontalement dans le formulaire. Cliquez sur Unselect MS dans la fenêtre Widget Tree. J'ai réglé le haut de mon cadre à 10 pixels en dessous du haut du formulaire (position Y). Il est temps d' | ||
+ | |||
+ | Nous pouvons maintenant commencer à placer le reste des widgets sur notre formulaire. Nous allons placer le premier des deux boutons de contrôle. Assurez-vous d'en faire un bouton de contrôle Tk, et non un bouton de contrôle ttk Themed. | ||
+ | |||
+ | Dans la grille ci-dessous, je vais vous donner les attributs que vous voudrez définir. | ||
+ | |||
+ | |||
+ | **Some information about these attributes. By setting the Active Background (active bg) and select color attributes, we control the colors when the mouse is over the widget (active bg) as well as the color when the status is Checked (select color). Setting the foreground color to antiquewhite2, | ||
Save again and we’ll add three more buttons. Make sure they line up nicely in the row with the Checkbutton. The first one will be the Save button, next is the Reload button, and the last is the Exit button. You might want to sneak a peek at the image above for a reference. Here are the attributes for the Save button. | Save again and we’ll add three more buttons. Make sure they line up nicely in the row with the Checkbutton. The first one will be the Save button, next is the Reload button, and the last is the Exit button. You might want to sneak a peek at the image above for a reference. Here are the attributes for the Save button. | ||
Ligne 36: | Ligne 71: | ||
Finally the Exit button. | Finally the Exit button. | ||
- | Remember to make everything line up in the row nicely, and provide a little bit of space between the bottom of the frame and the top of the buttons. | + | Remember to make everything line up in the row nicely, and provide a little bit of space between the bottom of the frame and the top of the buttons.** |
+ | |||
+ | Quelques informations sur ces attributs. En définissant les attributs Active Background (active bg) et select color, nous contrôlons les couleurs lorsque la souris passe sur le widget (active bg) ainsi que la couleur lorsque l' | ||
+ | |||
+ | Enregistrez à nouveau et nous allons ajouter trois autres boutons. Veillez à ce qu'ils soient bien alignés avec le bouton de contrôle. Le premier sera le bouton Enregistrer, | ||
+ | |||
+ | Ensuite, le bouton Recharger | ||
+ | |||
+ | Enfin, le bouton Quitter. | ||
+ | |||
+ | N' | ||
+ | |||
- | Save your project again and we’ll finish up with the last three widgets. First we’ll do another Tk Checkbutton. | + | **Save your project again and we’ll finish up with the last three widgets. First we’ll do another Tk Checkbutton. |
Next will be the Spinbox. You’ll want to make it a bit smaller in width from the default that PAGE gives you. I made mine only 58 pixels wide. How wide you make it is up to you. Here are the attributes. | Next will be the Spinbox. You’ll want to make it a bit smaller in width from the default that PAGE gives you. I made mine only 58 pixels wide. How wide you make it is up to you. Here are the attributes. | ||
Ligne 46: | Ligne 93: | ||
Save your project and generate your Python modules. Next we’ll work on the code in the _support module. | Save your project and generate your Python modules. Next we’ll work on the code in the _support module. | ||
- | We’ll start with the imports section. | + | We’ll start with the imports section.** |
- | import sys | + | Sauvegardez à nouveau votre projet et nous allons terminer avec les trois derniers widgets. Tout d' |
+ | |||
+ | Ensuite, c'est la Spinbox. Vous voudrez lui donner une largeur un peu plus petite que celle qui est proposée par défaut par PAGE. La mienne ne fait que 58 pixels de large. C'est vous qui décidez de sa largeur. Voici les attributs. | ||
+ | |||
+ | Le dernier mais non le moindre, c'est le bouton Set. L' | ||
+ | |||
+ | Sauvegardez votre projet et générez vos modules Python. Ensuite, nous allons travailler sur le code du module _support. | ||
+ | |||
+ | Nous allons commencer par la section des importations. | ||
+ | |||
+ | |||
+ | **import sys | ||
from os.path import exists | from os.path import exists | ||
Ligne 67: | Ligne 125: | ||
We’ll also need to import a couple of extra Tkinter modules. | We’ll also need to import a couple of extra Tkinter modules. | ||
+ | |||
+ | from tkinter import Spinbox, messagebox | ||
+ | |||
+ | from tkinter import font | ||
+ | |||
+ | from tkinter import filedialog | ||
+ | |||
+ | from tkinter import constants** | ||
+ | |||
+ | import sys | ||
+ | |||
+ | from os.path import exists | ||
+ | |||
+ | from datetime import datetime, timedelta | ||
+ | |||
+ | from pathlib import Path | ||
+ | |||
+ | import requests | ||
+ | |||
+ | from requests.exceptions import Timeout | ||
+ | |||
+ | from PIL import Image, ImageTk | ||
+ | |||
+ | import shutil | ||
+ | |||
+ | Je montre la ligne import sys en maigre (pas en gras), puisque PAGE l'a déjà fait pour nous. | ||
+ | |||
+ | Nous aurons également besoin d' | ||
from tkinter import Spinbox, messagebox | from tkinter import Spinbox, messagebox | ||
Ligne 77: | Ligne 163: | ||
- | If you scroll down the file a little bit, there is a function called set_Tk_var(). We’ll need to make one small change to that function, so I’ll show that one change in bold below. Basically, it sets the default for the spinbox to 45 at startup. | + | **If you scroll down the file a little bit, there is a function called set_Tk_var(). We’ll need to make one small change to that function, so I’ll show that one change in bold below. Basically, it sets the default for the spinbox to 45 at startup. |
def set_Tk_var(): | def set_Tk_var(): | ||
Ligne 95: | Ligne 181: | ||
che48 = tk.IntVar() | che48 = tk.IntVar() | ||
- | The next function in the file should be the init function. PAGE creates this function for us, and again, we need to make a one line addition to it. I’ll put it in bold. | + | The next function in the file should be the init function. PAGE creates this function for us, and again, we need to make a one line addition to it. I’ll put it in bold.** |
+ | Si vous faites défiler le fichier un peu plus bas, il y a une fonction appelée set_Tk_var(). Nous allons devoir apporter une petite modification à cette fonction, et je vais donc la montrer en gras ci-dessous. En gros, elle fixe la valeur de spinbox à 45 par défaut au démarrage. | ||
- | def init(top, gui, *args, **kwargs): | + | def set_Tk_var() : |
+ | |||
+ | global spinbox | ||
+ | |||
+ | spinbox = tk.StringVar() | ||
+ | |||
+ | spinbox.set(' | ||
+ | |||
+ | global che47 | ||
+ | |||
+ | che47 = tk.IntVar() | ||
+ | |||
+ | global che48 | ||
+ | |||
+ | che48 = tk.IntVar() | ||
+ | |||
+ | La fonction suivante dans le fichier doit être la fonction init. PAGE crée cette fonction pour nous et, encore une fois, nous devons faire un ajout d'une ligne dans cette fonction. Je vais la mettre en gras. | ||
+ | |||
+ | |||
+ | **def init(top, gui, *args, **kwargs): | ||
global w, top_level, root | global w, top_level, root | ||
Ligne 112: | Ligne 218: | ||
The startup function (right) is run just before the user sees the project main form. Here we set any global variables we need as well as define some constants. | The startup function (right) is run just before the user sees the project main form. Here we set any global variables we need as well as define some constants. | ||
- | A couple of things you might want to be aware of. We have set the checkboxes to unchecked by using the che48.set(0) and che47.set(0). We also set the spinbox to be disabled at startup. When the user checks the “Auto-reload” checkbox, we’ll set it back to a normal state. We also create (if it doesn’t exist) a very simple text file, which will hold the number of the last saved image file. | + | A couple of things you might want to be aware of. We have set the checkboxes to unchecked by using the che48.set(0) and che47.set(0). We also set the spinbox to be disabled at startup. When the user checks the “Auto-reload” checkbox, we’ll set it back to a normal state. We also create (if it doesn’t exist) a very simple text file, which will hold the number of the last saved image file.** |
+ | |||
+ | def init(top, gui, *args, **kwargs) : | ||
+ | |||
+ | global w, top_level, root | ||
+ | |||
+ | w = gui | ||
+ | |||
+ | top_level = top | ||
+ | |||
+ | root = top | ||
+ | |||
+ | startup() | ||
+ | |||
+ | La fonction startup (à droite) est exécutée juste avant que l' | ||
+ | |||
+ | Il y a deux choses que vous devez savoir. Nous avons défini les cases à cocher comme non cochées en utilisant les variables che48.set(0) et che47.set(0). Nous avons également configuré la spinbox pour qu' | ||
- | def on_chkAspect(): | + | **def on_chkAspect(): |
# print(' | # print(' | ||
Ligne 125: | Ligne 248: | ||
def on_chkTime(): | def on_chkTime(): | ||
+ | |||
+ | # print(' | ||
+ | |||
+ | # sys.stdout.flush() | ||
+ | |||
+ | if che48.get() == 1: | ||
+ | |||
+ | w.Spinbox1.configure(state=tk.NORMAL) | ||
+ | |||
+ | else: | ||
+ | |||
+ | w.Spinbox1.configure(state=tk.DISABLED) | ||
+ | |||
+ | refresh_time = spinbox.get() | ||
+ | |||
+ | root.update()** | ||
+ | | ||
+ | def on_chkAspect() : | ||
+ | |||
+ | # print(' | ||
+ | |||
+ | # sys.stdout.flush() | ||
+ | |||
+ | pass | ||
+ | |||
+ | Nous n' | ||
+ | |||
+ | def on_chkTime() : | ||
# print(' | # print(' | ||
Ligne 141: | Ligne 292: | ||
root.update() | root.update() | ||
+ | | ||
- | Here is the chkTime function I told you about. We check if the checkbox variable is equal to 1. If so, we set the spinbox state to normal. Otherwise set it to disabled. | + | **Here is the chkTime function I told you about. We check if the checkbox variable is equal to 1. If so, we set the spinbox state to normal. Otherwise set it to disabled. |
def on_btnExit(): | def on_btnExit(): | ||
Ligne 154: | Ligne 306: | ||
The on_btnExit is the callback for the Exit button. It simply calls the PAGE created function destroy_window to close the program properly. | The on_btnExit is the callback for the Exit button. It simply calls the PAGE created function destroy_window to close the program properly. | ||
- | The on_btnReload function is the callback function that will reload the image. It calls the get_image_from_web function. If you click the Aspect checkbutton, | + | The on_btnReload function is the callback function that will reload the image. It calls the get_image_from_web function. If you click the Aspect checkbutton, |
- | def on_btnReload(): | + | Voici la fonction chkTime dont je vous ai parlé. Nous vérifions si la variable checkbox est égale à 1. Si oui, nous mettons l' |
+ | |||
+ | def on_btnExit() : | ||
+ | |||
+ | # print(' | ||
+ | |||
+ | # sys.stdout.flush() | ||
+ | |||
+ | destroy_window() | ||
+ | |||
+ | Le on_btnExit est le callback pour le bouton Exit. Il appelle simplement la fonction destroy_window créée par PAGE pour fermer le programme correctement. | ||
+ | |||
+ | La fonction on_btnReload est la fonction de rappel qui va recharger l' | ||
+ | |||
+ | |||
+ | **def on_btnReload(): | ||
# print(' | # print(' | ||
Ligne 168: | Ligne 335: | ||
The on_btnSave callback function (top right) will attempt to save the current image to a file. It first opens the filecounter.txt file (which is created at startup if it doesn’t exist), reads the number of the last file (0 if none have been saved), increments by one, and then appends that value to “NasaStills” in the filename “NasaStills? | The on_btnSave callback function (top right) will attempt to save the current image to a file. It first opens the filecounter.txt file (which is created at startup if it doesn’t exist), reads the number of the last file (0 if none have been saved), increments by one, and then appends that value to “NasaStills” in the filename “NasaStills? | ||
- | The on_btnSet callback function is not needed if you decided not to include the Set button. If you did, and followed the instructions, | + | The on_btnSet callback function is not needed if you decided not to include the Set button. If you did, and followed the instructions, |
+ | |||
+ | def on_btnReload() : | ||
+ | |||
+ | # print(' | ||
+ | |||
+ | # sys.stdout.flush() | ||
+ | |||
+ | global feed_url | ||
+ | |||
+ | get_image_from_web(feed_url) | ||
+ | |||
+ | La fonction de rappel on_btnSave (en haut à droite) va tenter d' | ||
+ | |||
+ | La fonction de rappel on_btnSet n'est pas nécessaire si vous avez décidé de ne pas inclure le bouton Set. Si vous l'avez fait, et que vous avez suivi les instructions, | ||
- | def on_btnSet(): | + | **def on_btnSet(): |
# print(' | # print(' | ||
Ligne 181: | Ligne 363: | ||
def on_spinChange(): | def on_spinChange(): | ||
+ | |||
+ | # print(' | ||
+ | |||
+ | # sys.stdout.flush() | ||
+ | |||
+ | global refresh_time | ||
+ | |||
+ | refresh_time = spinbox.get()** | ||
+ | | ||
+ | def on_btnSet() : | ||
+ | |||
+ | # print(' | ||
+ | |||
+ | # sys.stdout.flush() | ||
+ | |||
+ | showinfo(" | ||
+ | |||
+ | La fonction de rappel on_spinChange se déclenche chaque fois que la spinbox est incrémentée ou décrémentée. Elle définit simplement la variable globale refresh_time. C'est un artefact d'une version antérieure que j'ai faite, puisque la fonction de minuterie on_tick obtient actuellement la valeur directement de la spinbox pour définir la prochaine valeur de la minuterie. Je l'ai fourni ici juste comme un exemple de comment obtenir la valeur de la spinbox. | ||
+ | |||
+ | def on_spinChange() : | ||
# print(' | # print(' | ||
Ligne 189: | Ligne 391: | ||
refresh_time = spinbox.get() | refresh_time = spinbox.get() | ||
+ | | ||
+ | |||
+ | **The get_image_from_web function (next page, top right) is where the first part of the “magic” happens. We use the requests.get method from the requests library to grab an image from a website. The image is received and saved as a .png image. Then, we verify the width and height of the image. If it is the correct size (704x480), and the aspect ratio checkbutton is not checked, then it is simply saved as a local image. If the aspect ratio checkbutton IS checked, then the PIL library resizes to the 16x9 format before it gets saved. Finally, we set the image attribute of the Label to the image we just downloaded. We also save it to a convenient local file, in case the user wants to save it. | ||
+ | |||
+ | The on_tick function (page after next, top right) is where the rest of the “magic” happens, in my mind at least. Here we use the root.after function of Tkinter to create a timer event. The first thing we do is to get the current value of the spinbox (between 45 and 300) and store it in a temporary variable rt (standing for refresh time). It then calls the get_image_from_web function to get the image and refresh the Label. Finally the callback is enabled with the time in milliseconds (rt * 1000) and reset the callback for the next call.** | ||
+ | |||
+ | La fonction get_image_from_web (page suivante, en haut à droite) est l' | ||
- | The get_image_from_web function | + | La fonction on_tick |
- | The on_tick function (page after next, top right) is where the rest of the “magic” happens, in my mind at least. Here we use the root.after function of Tkinter to create a timer event. The first thing we do is to get the current value of the spinbox (between 45 and 300) and store it in a temporary variable rt (standing for refresh time). It then calls the get_image_from_web function to get the image and refresh the Label. Finally the callback is enabled with the time in milliseconds (rt * 1000) and reset the callback for the next call. | ||
- | The showinfo function takes two parameters, title and message, then calls the Tkinter message box to show the message box to the user. We also provide the parent (which in this case will always be root, but that will keep the messagebox over the actual application and set the icon to the INFO icon. | + | **The showinfo function takes two parameters, title and message, then calls the Tkinter message box to show the message box to the user. We also provide the parent (which in this case will always be root, but that will keep the messagebox over the actual application and set the icon to the INFO icon. |
def showinfo(titl, | def showinfo(titl, | ||
Ligne 206: | Ligne 414: | ||
messagebox.showerror(titl, | messagebox.showerror(titl, | ||
- | Finally, we have the centre_screen function, which takes the width and height of our main form (which is provided in the GUI python file that PAGE creates). It then uses the screen width and height to calculate the centre of the screen and form. | + | Finally, we have the centre_screen function, which takes the width and height of our main form (which is provided in the GUI python file that PAGE creates). It then uses the screen width and height to calculate the centre of the screen and form.** |
+ | La fonction showinfo prend deux paramètres, | ||
- | def centre_screen(wid, | + | def showinfo(titl, |
+ | |||
+ | messagebox.showinfo(titl, | ||
+ | |||
+ | La fonction showerror est presque exactement la même que la fonction showinfo, mais affiche une boîte de message d' | ||
+ | |||
+ | def showerror(titl, | ||
+ | |||
+ | messagebox.showerror(titl, | ||
+ | |||
+ | Enfin, nous avons la fonction centre_écran, | ||
+ | |||
+ | |||
+ | **def centre_screen(wid, | ||
ws = root.winfo_screenwidth() | ws = root.winfo_screenwidth() | ||
Ligne 220: | Ligne 442: | ||
root.geometry(' | root.geometry(' | ||
- | |||
- | |||
That’s it. Our project is completed. I feel happy about the functionality that Tkinter provides against the PySimpleGUI toolkit. When I did the first version of the program, it took me only about 30 minutes to design the PAGE GUI form and write or borrow the code snippets from some of my previous programs. The length of the actual support module with comments (LOTS of comments), and double spacing between functions, is only about 230 lines of code, which isn’t too bad. | That’s it. Our project is completed. I feel happy about the functionality that Tkinter provides against the PySimpleGUI toolkit. When I did the first version of the program, it took me only about 30 minutes to design the PAGE GUI form and write or borrow the code snippets from some of my previous programs. The length of the actual support module with comments (LOTS of comments), and double spacing between functions, is only about 230 lines of code, which isn’t too bad. | ||
Ligne 227: | Ligne 447: | ||
You can find the code already created for you and ready to run at my github repository at https:// | You can find the code already created for you and ready to run at my github 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!** |
+ | |||
+ | def centre_screen(wid, | ||
+ | |||
+ | ws = root.winfo_screenwidth() | ||
+ | |||
+ | hs = root.winfo_screenheight() | ||
+ | |||
+ | x = (ws / 2) - (wid / 2) | ||
+ | |||
+ | y = (hs / 2) - (hei / 2) | ||
+ | |||
+ | root.geometry(' | ||
+ | |||
+ | Voilà, c'est fait. Notre projet est terminé. Je suis content que Tkinter soit si fonctionel par rapport à la boîte à outils PySimpleGUI. Quand j'ai fait la première version du programme, il ne m'a fallu qu' | ||
+ | |||
+ | Vous pouvez trouver le code déjà créé pour vous et prêt à être exécuté sur mon dépôt github à l' | ||
+ | |||
+ | Jusqu' |
issue175/python.1638101550.txt.gz · Dernière modification : 2021/11/28 13:12 de auntiee