INTRODUCTION |
Les programmes que vous utilisez d’habitude sont dotés d’une interface utilisateur (GUI = Graphical User Interface). Parmi les éléments graphiques souvent présents, on compte les barres de menu, les champs de saisie ou les boutons. De tels composants graphiques sont appelés widgets et sont considérés comme des objets, tout comme les objets tortues que nous avions manipulés dans le chapitre Objets tortues. Si vous voulez développer un programme avec une interface utilisateur moderne, il est essentiel de connaître et bien comprendre les notions de base de la programmation orientée objets (POO = OOP en anglais, pour object-oriented programming) [plus...Les concepts de POO sont présentés de manière approfondie dans le chapitre Développement de jeux]. Les widgets sont répartis en différentes classes comme le montre la liste ci-dessous.
De même que l’on avait engendré une tortue en appelant le constructeur de la classe turtle, on doit créer un composant de l’interface utilisateur en appelant le constructeur de la classe idoine. Les constructeurs acceptent souvent des paramètres permettant d’initialiser certaines propriétés du widget. Par exemple, on peut créer un champ de saisie d’une longueur de 10 caractères avec tf = JTextField(10). Lors de l’appel du constructeur, il est également nécessaire de définir une variable qui servira ultérieurement à accéder à l’objet créé et retourné par l’appel au constructeur. Le code, tf.getText() retourne par exemple le texte présent dans le champ de texte référencé par la variable tf. Pour rendre un widget visible dans le GPanel, on utilise la fonction addComponent() à laquelle on passe la variable référençant le widget à placer. Les widgets sont automatiquement placés dans l’ordre des appels à addComponent() dans la partie supérieure de la fenêtre GPanel
[plus...Pour obtenir une disposition plus soignée et plus flexible, il faut faire appel
|
ESTIMATION DE PI PAR SIMULATION MONTE CARLO |
L’interface utilisateur comporte deux étiquettes, deux champs de saisie textuels et un bouton. Une fois créés, on ajoute ces widgets au GPanel à l’aide de addComponent(). Il est clair qu’un clic sur le bouton OK devrait être considéré comme un événement. La fonction de rappel qui sert de gestionnaire pour cet événement de clic est enregistrée par le paramètre actionListener dans le constructeur de JButton. Vous vous rappelez sûrement qu’il ne faut pas placer du code qui s’exécute sur une longue durée à l’intérieur des fonctions de rappel. De ce fait, on ne fait rien d’autre, dans la fonction de rappel, que d’appeler wakeUp() pour réveiller le programme qui avait été endormi dans la boucle while par l’appel à putSleep() dans le but de lancer la simulation. from gpanel import * from random import random from javax.swing import * def actionCallback(e): wakeUp() def createGUI(): addComponent(lbl1) addComponent(tf1) addComponent(btn1) addComponent(lbl2) addComponent(tf2) validate() def init(): tf2.setText("") clear() move(0.5, 0.5) rectangle(1, 1) move(0, 0) arc(1, 0, 90) def doIt(n): hits = 0 for i in range(n): zx = random() zy = random() if zx * zx + zy * zy < 1: hits = hits + 1 setColor("red") else: setColor("green") point(zx, zy) return hits lbl1 = JLabel("Number of drops: ") lbl2 = JLabel(" PI = ") tf1 = JTextField(6) tf2 = JTextField(10) btn1 = JButton("OK", actionListener = actionCallback) makeGPanel("Monte Carlo Simulation", -0.1, 1.1, -0.1, 1.1) createGUI() tf1.setText("10000") init() while True: putSleep() init() n = int(tf1.getText()) k = doIt(n) pi = 4 * k / n tf2.setText(str(pi)) |
MEMENTO |
Les widgets sont des objets de la bibliothèque de classes Swing faisant partie de l’écosystème Java. Ils sont créés par l’appel du constructeur qui porte le même nom que la classe. Lors de l’appel du constructeur, on veille à créer une variable qui permet de référencer l’objet nouvellement créé pour une utilisation future. Pour afficher le widget dans GPanel, il faut appeler la fonction addComponent() en lui fournissant cette variable en tant que paramètre. Une fois tous les widgets ajoutés au GPanel, il faut appeler la fonction validate()pour lancer une régénération complète de la fenêtre. Ceci permet de tenir compte des nouveaux widgets insérés en garantissant un résultat tout-à-fait prévisible. On peut enregistrer des gestionnaires d’événements avec le paramètre nommé actionListener. Il ne faut jamais exécuter du code long à terminer à l’intérieur d’une fonction de rappel. |
LES MENUS (Rien à voir avec la cantine !) |
De nombreuses fenêtres sont pourvues d’une barre de menu comportant plusieurs éléments de menu (menu items). Lors d’un clic sur un élément de menu, il n’est pas rare qu’un autre sous-menu s’ouvre à son tour, pouvant lui-même comporter plusieurs nouvelles entrées de menu. Les menus et entrées de menu sont également considérés comme des objets qu’il faut créer. La sélection d’une entrée de menu va également générer un événement qui sera traité par un gestionnaire d’événements approprié enregistré au préalable.
from gpanel import * from javax.swing import * def actionCallback(e): if e.getSource() == goItem: wakeUp() if e.getSource() == exitItem: dispose() if e.getSource() == aboutItem: msgDlg("Pyramides Version 1.0") def doIt(): clear() for i in range(1, 30): setColor(getRandomX11Color()) fillRectangle(i/2, i - 0.35, 30 - i/2, i + 0.35) fileMenu = JMenu("File") goItem = JMenuItem("Go", actionPerformed = actionCallback) exitItem = JMenuItem("Exit", actionPerformed = actionCallback) fileMenu.add(goItem) fileMenu.add(exitItem) aboutItem = JMenuItem("About", actionPerformed = actionCallback) menuBar = JMenuBar() menuBar.add(fileMenu) menuBar.add(aboutItem) makeGPanel(menuBar, 0, 30, 0, 30) while not isDisposed(): putSleep() if not isDisposed(): doIt() |
MEMENTO |
Rappelez-vous toujours qu’une fonction de rappel telle qu’un gestionnaire d’événements ne devrait jamais exécuter du code qui prend long à se terminer. On effectue de ce fait le dessin dans le programme principal. Pour s’assurer que le programme se termine avec une certitude absolue lorsque l’utilisateur clique sur le bouton fermer, on utilise isDisposed() pour tester si la fenêtre a été fermée [plus...Lorsque la fenêtre est fermée ou que la fonction dispose() est appelée, la fonction putSleep() se termine et retourne à l’appelant]. |
EXERCICES |
|