Fil d'Ariane
Mis à jour le jeudi 9 mars 2017
  • 40 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Ce cours existe en eBook.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Notre première fenêtre

Connectez-vous ou inscrivez-vous pour bénéficier de toutes les fonctionnalités de ce cours !

Dans cette partie, nous aborderons les interfaces graphiques (on parle aussi d'IHMpourInterfacesHommeMachine ou deGUIpourGraphicalUserInterfaces) et, par extension, la programmation événementielle. Par là, vous devez comprendre que votre programme ne réagira plus à des saisies au clavier mais à des événements provenant d'un composant graphique : un bouton, une liste, un menu…

Le langage Java propose différentes bibliothèques pour programmer des IHM, mais dans cet ouvrage, nous utiliserons essentiellement les packagesjavax.swingetjava.awtprésents d'office dans Java. Ce chapitre vous permettra d'apprendre à utiliser l'objetJFrame, présent dans le packagejavax.swing. Vous serez alors à même de créer une fenêtre, de définir sa taille, etc.

Le fonctionnement de base des IHM vous sera également présenté et vous apprendrez qu'en réalité, une fenêtre n'est qu'une multitude de composants posés les uns sur les autres et que chacun possède un rôle qui lui est propre.
Mais trêve de bavardages inutiles, commençons tout de suite !

L'objet JFrame

Avant de nous lancer à corps perdu dans cette partie, vous devez savoir de quoi nous allons nous servir. Dans ce cours, nous traiterons dejavax.swinget dejava.awt. Nous n'utiliserons pas de composantsawt, nous travaillerons uniquement avec des composantsswing; en revanche, des objets issus du packageawtseront utilisés afin d'interagir et de communiquer avec les composantsswing. Par exemple, un composant peut être représenté par un bouton, une zone de texte, une case à cocher, etc.

Afin de mieux comprendre comment tout cela fonctionne, vous devez savoir que lorsque le langage Java a vu le jour, dans sa version 1.0, seulawtétait utilisable ;swingn'existait pas, il est apparu dans la version 1.2 de Java (appelée aussi Java 2). Les composantsawtsont considérés comme lourds (on dit aussiHeavyWeight) car ils sont fortement liés au système d'exploitation, c'est ce dernier qui les gère. Les composantsswing, eux, sont comme dessinés dans un conteneur, ils sont dit légers (on dit aussiLightWeight) ; ils n'ont pas le même rendu à l'affichage, car ce n'est plus le système d'exploitation qui les gère. Il existe également d'autres différences, comme le nombre de composants utilisables, la gestion des bordures...

Pour toutes ces raisons, il est très fortement recommandé de ne pas mélanger les composantsswingetawtdans une même fenêtre ; cela pourrait occasionner des conflits ! Si vous associez les deux, vous aurez de très grandes difficultés à développer une IHM stable et valide. En effet,swingetawtont les mêmes fondements mais diffèrent dans leur utilisation.

Cette parenthèse fermée, nous pouvons entrer dans le vif du sujet. Je ne vous demande pas de créer un projet contenant une classemain, celui-ci doit être prêt depuis des lustres ! Pour utiliser une fenêtre de typeJFrame, vous devez l'instancier, comme ceci :

import javax.swing.JFrame;
 
public class Test {
  public static void main(String[] args){       
    JFrame fenetre = new JFrame();
  }       
}

Lorsque vous exécutez ce code, vous n'obtenez rien, car par défaut, votreJFramen'est pas visible. Vous devez donc lui dire « sois visible » de cette manière :

import javax.swing.JFrame;
 
public class Test {
  public static void main(String[] args){
    JFrame fenetre = new JFrame();
    fenetre.setVisible(true);
  }       
}

Ainsi, lorsque vous exécutez ce code, vous obtenez la figure suivante.

Première fenêtre
Première fenêtre

À toutes celles et ceux qui se disent que cette fenêtre est toute petite, je réponds : « Bienvenue dans le monde de la programmation événementielle ! » Il faut que vous vous y fassiez, vos composants ne sont pas intelligents : il va falloir leur dire tout ce qu'ils doivent faire.

Pour obtenir une fenêtre plus conséquente, il faudrait donc :

  • qu'elle soit plus grande ;

  • qu'elle comporte un titre (ce ne serait pas du luxe !) ;

  • qu'elle figure au centre de l'écran, ce serait parfait ;

  • que notre programme s'arrête réellement lorsqu'on clique sur la croix rouge, car, pour ceux qui ne l'auraient pas remarqué, le processus Eclipse tourne encore même après la fermeture de la fenêtre.

Pour chacun des éléments que je viens d'énumérer, il y a aura une méthode à appeler afin que notreJFramesache à quoi s'en tenir. Voici d'ailleurs un code répondant à toutes nos exigences :

import javax.swing.JFrame;
 
public class Test {
  public static void main(String[] args){

    JFrame fenetre = new JFrame();
                
    //Définit un titre pour notre fenêtre
    fenetre.setTitle("Ma première fenêtre Java");
    //Définit sa taille : 400 pixels de large et 100 pixels de haut
    fenetre.setSize(400, 100);
    //Nous demandons maintenant à notre objet de se positionner au centre
    fenetre.setLocationRelativeTo(null);
    //Termine le processus lorsqu'on clique sur la croix rouge
    fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Et enfin, la rendre visible        
    fenetre.setVisible(true);
  }       
}

Voyez le rendu de ce code en figure suivante.

Une fenêtre plus adaptée
Une fenêtre plus adaptée

Afin de ne pas avoir à redéfinir les attributs à chaque fois, je pense qu'il serait utile que nous possédions notre propre objet. Comme ça, nous aurons notre propre classe !

Pour commencer, effaçons tout le code que nous avons écrit dans notre méthodemain. Créons ensuite une classe que nous allons appelerFenetreet faisons-la hériter deJFrame. Nous allons maintenant créer notre constructeur, dans lequel nous placerons nos instructions.
Cela nous donne :

import javax.swing.JFrame;
 
public class Fenetre extends JFrame {
  public Fenetre(){
    this.setTitle("Ma première fenêtre Java");
    this.setSize(400, 500);
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);             
    this.setVisible(true);
  }
}

Ensuite, vous avez le choix : soit vous conservez votre classe contenant la méthodemainet vous créez une instance deFenetre, soit vous effacez cette classe et vous placez votre méthodemaindans votre classeFenetre. Mais dans tous les cas, vous devez créer une instance de votreFenetre. Personnellement, je préfère placer ma méthodemaindans une classe à part… Mais je ne vous oblige pas à faire comme moi ! Quel que soit l'emplacement de votremain, la ligne de code suivante doit y figurer :

Fenetre fen = new Fenetre();

Exécutez votre nouveau code, et… vous obtenez exactement la même chose que précédemment. Vous conviendrez que c'est tout de même plus pratique de ne plus écrire les mêmes instructions à chaque fois. Ainsi, vous possédez une classe qui va se charger de l'affichage de votre futur programme. Et voici une petite liste de méthodes que vous serez susceptibles d'utiliser.

Positionner la fenêtre à l'écran

Nous avons déjà centré notre fenêtre, mais vous voudriez peut-être la positionner ailleurs. Pour cela, vous pouvez utiliser la méthodesetLocation(int x, int y). Grâce à cette méthode, vous pouvez spécifier où doit se situer votre fenêtre sur l'écran. Les coordonnées, exprimées en pixels, sont basées sur un repère dont l'origine est représentée par le coin supérieur gauche (figure suivante).

Coordonnées sur votre écran
Coordonnées sur votre écran

La première valeur de la méthode vous positionne sur l'axe x, 0 correspondant à l'origine ; les valeurs positives déplacent la fenêtre vers la droite tandis que les négatives la font sortir de l'écran par la gauche. La même règle s'applique aux valeurs de l'axe y, si ce n'est que les valeurs positives font descendre la fenêtre depuis l'origine tandis que les négatives la font sortir par le haut de l'écran.

Empêcher le redimensionnement de la fenêtre

Pour cela, il suffit d'invoquer la méthodesetResizable(boolean b):falseempêche le redimensionnement tandis quetruel'autorise.

Garder la fenêtre au premier plan

Il s'agit là encore d'une méthode qui prend un booléen en paramètre. Passertruelaissera la fenêtre au premier plan quoi qu'il advienne,falseannulera cela. Cette méthode estsetAlwaysOnTop(boolean b).

Retirer les contours et les boutons de contrôle

Pour ce faire, il faut utiliser la méthodesetUndecorated(boolean b).

Je ne vais pas faire le tour de toutes les méthodes maintenant, car de toute façon, nous allons nous servir de bon nombre d'entre elles très prochainement.Cependant, je suppose que vous aimeriez bien remplir un peu votre fenêtre. Je m'en doutais, mais avant il vous faut encore apprendre une bricole. En effet, votre fenêtre, telle qu'elle apparaît, vous cache quelques petites choses !

Vous pensez, et c'est légitime, que votre fenêtre est toute simple, dépourvue de tout composant (hormis les contours). Eh bien vous vous trompez ! UneJFrameest découpée en plusieurs parties superposées, comme le montre la figure suivante.

Structure d'une JFrame
Structure d'une JFrame

Nous avons, dans l'ordre :

  • la fenêtre ;

  • leRootPane(en vert), le conteneur principal qui contient les autres composants ;

  • leLayeredPane(en violet), qui forme juste un panneau composé du conteneur global et de la barre de menu (MenuBar) ;

  • laMenuBar(en orange), la barre de menu, quand il y en a une ;

  • le content pane (en rose) : c'est dans celui-ci que nous placerons nos composants ;

  • leGlassPane(en transparence), couche utilisée pour intercepter les actions de l'utilisateur avant qu'elles ne parviennent aux composants.

Pas de panique, nous allons nous servir uniquement du content pane. Pour le récupérer, il nous suffit d'utiliser la méthodegetContentPane()de la classeJFrame. Cependant, nous allons utiliser un composant autre que le content pane : unJPaneldans lequel nous insérerons nos composants.

L'objet JPanel

Comme je vous l'ai dit, nous allons utiliser unJPanel, composant de type conteneur dont la vocation est d'accueillir d'autres objets de même type ou des objets de type composant (boutons, cases à cocher…).

Voici la marche à suivre :

  1. Importer la classejavax.swing.JPaneldans notre classe héritée deJFrame.

  2. Instancier unJPanelpuis lui spécifier une couleur de fond pour mieux le distinguer.

  3. Avertir notreJFrameque ce sera notreJPanelqui constituera son content pane.

Rien de bien sorcier, en somme. Qu'attendons-nous ?

import java.awt.Color; 
import javax.swing.JFrame;
import javax.swing.JPanel;
 
public class Fenetre extends JFrame {
  public Fenetre(){             
    this.setTitle("Ma première fenêtre Java");
    this.setSize(400, 100);
    this.setLocationRelativeTo(null);               
 
    //Instanciation d'un objet JPanel
    JPanel pan = new JPanel();
    //Définition de sa couleur de fond
    pan.setBackground(Color.ORANGE);        
    //On prévient notre JFrame que notre JPanel sera son content pane
    this.setContentPane(pan);               
    this.setVisible(true);
  }       
}

Vous pouvez voir le résultat à la figure suivante.

Premier JPanel
Premier JPanel

C'est un bon début, mais je vois que vous êtes frustrés car il n'y a pas beaucoup de changement par rapport à la dernière fois. Eh bien, c'est maintenant que les choses deviennent intéressantes ! Avant de vous faire utiliser des composants (des boutons, par exemple), nous allons nous amuser avec notreJPanel. Plus particulièrement avec un objet dont le rôle est de dessiner et de peindre notre composant. Ça vous tente ? Alors, allons-y !

Les objets Graphics et Graphics2D

L'objetGraphics

Nous allons commencer par l'objetGraphics.Cet objet a une particularité de taille : vous ne pouvez l'utiliser que si et seulement si le système vous l'a donné via la méthodegetGraphics()d'un composantswing! Pour bien comprendre le fonctionnement de nos futurs conteneurs (ou composants), nous allons créer une classe héritée deJPanel : appelons-laPanneau. Nous allons faire un petit tour d'horizon du fonctionnement de cette classe, dont voici le code :

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel { 
  public void paintComponent(Graphics g){
    //Vous verrez cette phrase chaque fois que la méthode sera invoquée
    System.out.println("Je suis exécutée !"); 
    g.fillOval(20, 20, 75, 75);
  }               
}

Qu'est-ce que c'est que cette méthode ?

Cette méthode est celle que l'objet appelle pour se dessiner sur votre fenêtre ; si vous réduisez cette dernière et que vous l'affichez de nouveau, c'est encore cette méthode qui est appelée pour afficher votre composant. Idem si vous redimensionnez votre fenêtre… De plus, nous n'avons même pas besoin de redéfinir un constructeur car cette méthode est appelée automatiquement !

C'est très pratique pour personnaliser des composants, car vous n'aurez jamais à l'appeler vous-mêmes : c'est automatique ! Tout ce que vous pouvez faire, c'est forcer l'objet à se repeindre ; ce n'est toutefois pas cette méthode que vous invoquerez, mais nous y reviendrons.

Vous aurez constaté que cette méthode possède un argument et qu'il s'agit du fameux objetGraphicstant convoité. Nous reviendrons sur l'instructiong.fillOval(20, 20, 75, 75), mais vous verrez à quoi elle sert lorsque vous exécuterez votre programme.

Voici maintenant notre classeFenetre :

import javax.swing.JFrame;
 
public class Fenetre extends JFrame {
  public Fenetre(){                
    this.setTitle("Ma première fenêtre Java");
    this.setSize(100, 150);
    this.setLocationRelativeTo(null);               
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setContentPane(new Panneau());

    this.setVisible(true);
  }     
}

Exécutez votremain, vous devriez obtenir la même chose qu'à la figure suivante.

Test de l'objet Graphics
Test de l'objet Graphics

Une fois votre fenêtre affichée, étirez-la, réduisez-la… À présent, vous pouvez voir ce qu'il se passe lorsque vous interagissez avec votre fenêtre : celle-ci met à jour ses composants à chaque changement d'état ou de statut. L'intérêt de disposer d'une classe héritée d'un conteneur ou d'un composant, c'est que nous pouvons redéfinir la façon dont est peint ce composant sur la fenêtre.

Après cette mise en bouche, explorons un peu plus les capacités de notre objetGraphics. Comme vous avez pu le voir, ce dernier permet, entre autres, de tracer des ronds ; mais il possède tout un tas de méthodes plus pratiques et amusantes les unes que les autres… Nous ne les étudierons pas toutes, mais vous aurez déjà de quoi faire.

Pour commencer, reprenons la méthode utilisée précédemment :g.fillOval(20, 20, 75, 75). Si nous devions traduire cette instruction en français, cela donnerait : « Trace un rond plein en commençant à dessiner sur l'axe x à 20 pixels et sur l'axe y à 20 pixels, et fais en sorte qu'il occupe 75 pixels de large et 75 pixels de haut. »

Oui, mais si je veux que mon rond soit centré et qu'il le reste ?

C'est dans ce genre de cas qu'il est intéressant d'utiliser une classe héritée. Puisque nous sommes dans notre objetJPanel, nous avons accès à ses données lorsque nous le dessinons.

En effet, il existe des méthodes dans les objets composants qui retournent leur largeur (getWidth()) et leur hauteur (getHeight()). En revanche, réussir à centrer un rond dans unJPanelen toutes circonstances demande un peu de calcul mathématique de base, une pincée de connaissances et un soupçon de logique !

Reprenons notre fenêtre telle qu'elle se trouve en ce moment. Vous pouvez constater que les coordonnées de départ correspondent au coin supérieur gauche du carré qui entoure ce cercle, comme le montre la figure suivante.

Point de départ du cercle dessiné
Point de départ du cercle dessiné

Cela signifie que si nous voulons que notre cercle soit tout le temps centré, il faut que notre carré soit centré, donc que le centre de celui-ci corresponde au centre de notre fenêtre ! La figure suivante est un schéma représentant ce que nous devons obtenir.

Coordonnées recherchées
Coordonnées recherchées

Ainsi, le principe est d'utiliser la largeur et la hauteur de notre composant ainsi que la largeur et la hauteur du carré qui englobe notre rond ; c'est facile, jusqu'à présent…

Maintenant, pour trouver où se situe le point depuis lequel doit commencer le dessin, il faut soustraire la moitié de la largeur du composant à la moitié de celle du rond afin d'obtenir la valeur sur l'axe x, et faire de même (en soustrayant les hauteurs, cette fois) pour l'axe y. Afin que notre rond soit le plus optimisé possible, nous allons donner comme taille à notre carré la moitié de la taille de notre fenêtre ; ce qui revient, au final, à diviser la largeur et la hauteur de cette dernière par quatre. Voici le code correspondant :

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel { 
  public void paintComponent(Graphics g){                
    int x1 = this.getWidth()/4;
    int y1 = this.getHeight()/4;                      
    g.fillOval(x1, y1, this.getWidth()/2, this.getHeight()/2);
  }       
}

Si vous testez à nouveau notre code, vous vous apercevez que notre rond est maintenant centré. Cependant, l'objetGraphicspermet d'effectuer plein d'autres choses, comme peindre des ronds vides, par exemple. Sans rire ! Maintenant que vous avez vu comment fonctionne cet objet, nous allons pouvoir utiliser ses méthodes.

La méthodedrawOval()

Il s'agit de la méthode qui permet de dessiner un rond vide. Elle fonctionne exactement de la même manière que la méthodefillOval(). Voici un code mettant en œuvre cette méthode :

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel {
  public void paintComponent(Graphics g){                
    int x1 = this.getWidth()/4;
    int y1 = this.getHeight()/4;
    g.drawOval(x1, y1, this.getWidth()/2, this.getHeight()/2);
  }               
}

Le résultat se trouve en figure suivante.

Rendu de la méthode drawOval()
Rendu de la méthode drawOval()
La méthodedrawRect()

Cette méthode permet de dessiner des rectangles vides. Bien sûr, son homologuefillRect()existe. Ces deux méthodes fonctionnent de la même manière que les précédentes, voyez plutôt ce code :

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel {
  public void paintComponent(Graphics g){
    //x1, y1, width, height
    g.drawRect(10, 10, 50, 60);
    g.fillRect(65, 65, 30, 40);
  }               
}

Le résultat se trouve à la figure suivante.

Rendu des méthodes drawRect() et fillRect()
Rendu des méthodes drawRect() et fillRect()
La méthodedrawRoundRect()

Il s'agit du même élément que précédemment, hormis le fait que le rectangle sera arrondi. L'arrondi est défini par la valeur des deux derniers paramètres.

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel { 
  public void paintComponent(Graphics g){
    //x1, y1, width, height, arcWidth, arcHeight
    g.drawRoundRect(10, 10, 30, 50, 10, 10);
    g.fillRoundRect(55, 65, 55, 30, 5, 5);
  }               
}

Voyez le résultat en figure suivante.

Rendu de la méthode drawRoundRect()
Rendu de la méthode drawRoundRect()
La méthodedrawLine()

Cette méthode permet de tracer des lignes droites. Il suffit de lui spécifier les coordonnées de départ et d'arrivée de la ligne. Dans ce code, je trace les diagonales du conteneur :

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel { 
  public void paintComponent(Graphics g){
    //x1, y1, x2, y2
    g.drawLine(0, 0, this.getWidth(), this.getHeight());
    g.drawLine(0, this.getHeight(), this.getWidth(), 0);
  }               
}

Le résultat se trouve à la figure suivante.

Rendu de la méthode drawLine()
Rendu de la méthode drawLine()
La méthodedrawPolygon()

Grâce à cette méthode, vous pouvez dessiner des polygones de votre composition. Eh oui, c'est à vous de définir les coordonnées de tous les points qui les forment ! Voici à quoi elle ressemble

drawPolygon(int[] x, int[] y, int nbrePoints);

Le dernier paramètre est le nombre de points formant le polygone. Ainsi, vous n'aurez pas besoin d'indiquer deux fois le point d'origine pour boucler votre figure : Java la fermera automatiquement en reliant le dernier point de votre tableau au premier. Cette méthode possède également son homologue pour dessiner des polygones remplis :fillPolygon().

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel {
  public void paintComponent(Graphics g){
    int x[] = {20, 30, 50, 60, 60, 50, 30, 20};
    int y[] = {30, 20, 20, 30, 50, 60, 60, 50};
    g.drawPolygon(x, y, 8);

    int x2[] = {50, 60, 80, 90, 90, 80, 60, 50};
    int y2[] = {60, 50, 50, 60, 80, 90, 90, 80};
    g.fillPolygon(x2, y2, 8);
  }               
}

Voyez le résultat à la figure suivante.

Rendu des méthodes drawPolygon() et fillPolygon()
Rendu des méthodes drawPolygon() et fillPolygon()

Il existe également une méthode qui prend exactement les mêmes arguments mais qui, elle, trace plusieurs lignes :drawPolyline().

Cette méthode va dessiner les lignes correspondant aux coordonnées définies dans les tableaux, sachant que lorsque son indice s'incrémente, la méthode prend automatiquement les valeurs de l'indice précédent comme point d'origine. Cette méthode ne fait pas le lien entre la première et la dernière valeur de vos tableaux. Vous pouvez essayer le code précédent en remplaçantdrawPolygon()par cette méthode.

La méthodedrawString()

Voici la méthode permettant d'écrire du texte. Elle est très simple à utiliser : il suffit de lui passer en paramètre la phrase à écrire et de lui spécifier à quelles coordonnées commencer.

import java.awt.Graphics;
import javax.swing.JPanel;
 
public class Panneau extends JPanel {
  public void paintComponent(Graphics g){
    g.drawString("Tiens ! Le Site du Zéro !", 10, 20);
  }               
}

Le résultat se trouve à la figure suivante.

Rendu de la méthode drawString()
Rendu de la méthode drawString()

Vous pouvez aussi modifier la couleur (la modification s'appliquera également pour les autres méthodes) et la police d'écriture. Pour redéfinir la police d'écriture, vous devez créer un objetFont. Le code suivant illustre la façon de procéder.

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
 
import javax.swing.JPanel;
 
public class Panneau extends JPanel {
  public void paintComponent(Graphics g){                
    Font font = new Font("Courier", Font.BOLD, 20);
    g.setFont(font);
    g.setColor(Color.red);          
    g.drawString("Tiens ! Le Site du Zéro !", 10, 20);                
  }               
}

Le résultat correspond à la figure suivante.

Changement de couleur et de police d'écriture
Changement de couleur et de police d'écriture
La méthodedrawImage()

Voici à quoi elle ressemble :

drawImage(Image img, int x, int y, Observer obs);

Vous devez charger votre image grâce à trois objets :

  • un objetImage ;

  • un objetImageIO ;

  • un objetFile.

Vous allez voir que l'utilisation de ces objets est très simple. Il suffit de déclarer un objet de typeImageet de l'initialiser en utilisant une méthode statique de l'objetImageIOqui, elle, prend un objetFileen paramètre. Ça peut sembler compliqué, mais vous allez voir que ce n'est pas le cas… Notre image sera stockée à la racine de notre projet, mais ce n'est pas une obligation. Dans ce cas, faites attention au chemin d'accès de votre image.

En ce qui concerne le dernier paramètre de la méthodedrawImage, il s'agit de l'objet qui est censé observer l'image. Ici, nous allons utiliser notre objetPanneau, doncthis.

import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
 
public class Panneau extends JPanel {
  public void paintComponent(Graphics g){
    try {
      Image img = ImageIO.read(new File("images.jpg"));
      g.drawImage(img, 0, 0, this);
      //Pour une image de fond
      //g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
    } catch (IOException e) {
      e.printStackTrace();
    }                
  }               
}

Les résultats se trouvent aux deux figures suivantes (pour bien vous montrer la différence, j'ai créé une fenêtre plus grande que l'image).

Conservation de la taille d'origine de l'image
Conservation de la taille d'origine de l'image
Adaptation de la taille de l'image
Adaptation de la taille de l'image

L'objetGraphics2D

Ceci est une amélioration de l'objetGraphics, et vous allez vite comprendre pourquoi.

Pour utiliser cet objet, il nous suffit en effet de caster l'objetGraphicsenGraphics2D(Graphics2D g2d = (Graphics2D) g), et de ne surtout pas oublier d'importer notre classe qui se trouve dans le packagejava.awt. L'une des possibilités qu'offre cet objet n'est autre que celle de peindre des objets avec des dégradés de couleurs. Cette opération n'est pas du tout difficile à réaliser : il suffit d'utiliser un objetGradientPaintet une méthode de l'objetGraphics2D.

Nous n'allons pas reprendre tous les cas que nous avons vus jusqu'à présent, mais juste deux ou trois afin que vous voyiez bien la différence. Commençons par notre objetGradientPaint ; voici comment l'initialiser (vous devez mettre à jour vos imports en ajoutantimport java.awt.GradientPaint) :

GradientPaint gp = new GradientPaint(0, 0, Color.RED, 30, 30, Color.cyan, true);

Alors, que signifie tout cela ? Voici le détail du constructeur utilisé dans ce code :

  • premier paramètre : la coordonnée x où doit commencer la première couleur ;

  • deuxième paramètre : la coordonnée y où doit commencer la première couleur ;

  • troisième paramètre : la première couleur ;

  • quatrième paramètre : la coordonnée x où doit commencer la seconde couleur ;

  • cinquième paramètre : la coordonnée y où doit commencer la seconde couleur ;

  • sixième paramètre : la seconde couleur ;

  • septième paramètre : le booléen indiquant si le dégradé doit se répéter.

Ensuite, pour utiliser ce dégradé dans une forme, il faut mettre à jour notre objetGraphics2D, comme ceci :

import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
 
import javax.imageio.ImageIO;
import javax.swing.JPanel;
 
public class Panneau extends JPanel {
  public void paintComponent(Graphics g){
    Graphics2D g2d = (Graphics2D)g;         
    GradientPaint gp = new GradientPaint(0, 0, Color.RED, 30, 30, Color.cyan, true);                
    g2d.setPaint(gp);
    g2d.fillRect(0, 0, this.getWidth(), this.getHeight());                
  }               
}

Les deux figures suivantes représentent les résultats obtenus, l'un avec le booléen àtrue, et l'autre àfalse.

Dégradé répété
Dégradé répété
Dégradé stoppé
Dégradé stoppé

Votre dégradé est oblique (rien ne m'échappe, à moi :-p). Ce sont les coordonnées choisies qui influent sur la direction du dégradé. Dans notre exemple, nous partons du point de coordonnées (0, 0) vers le point de coordonnées (30, 30). Pour obtenir un dégradé vertical, il suffit d'indiquer la valeur de la seconde coordonnée x à 0, ce qui correspond à la figure suivante.

Dégradé horizontal
Dégradé horizontal

Voici un petit cadeau :

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D; 
import javax.imageio.ImageIO;
import javax.swing.JPanel;
 
public class Panneau extends JPanel { 
  public void paintComponent(Graphics g){
    Graphics2D g2d = (Graphics2D)g;
    GradientPaint gp, gp2, gp3, gp4, gp5, gp6; 
    gp = new GradientPaint(0, 0, Color.RED, 20, 0, Color.magenta, true);
    gp2 = new GradientPaint(20, 0, Color.magenta, 40, 0, Color.blue, true);
    gp3 = new GradientPaint(40, 0, Color.blue, 60, 0, Color.green, true);
    gp4 = new GradientPaint(60, 0, Color.green, 80, 0, Color.yellow, true);
    gp5 = new GradientPaint(80, 0, Color.yellow, 100, 0, Color.orange, true);
    gp6 = new GradientPaint(100, 0, Color.orange, 120, 0, Color.red, true);

    g2d.setPaint(gp);
    g2d.fillRect(0, 0, 20, this.getHeight());               
    g2d.setPaint(gp2);
    g2d.fillRect(20, 0, 20, this.getHeight());
    g2d.setPaint(gp3);
    g2d.fillRect(40, 0, 20, this.getHeight());
    g2d.setPaint(gp4);
    g2d.fillRect(60, 0, 20, this.getHeight());
    g2d.setPaint(gp5);
    g2d.fillRect(80, 0, 20, this.getHeight());
    g2d.setPaint(gp6);
    g2d.fillRect(100, 0, 40, this.getHeight());
  }               
}

Maintenant que vous savez utiliser les dégradés avec des rectangles, vous savez les utiliser avec toutes les formes. Je vous laisse essayer cela tranquillement chez vous.

  • Pour créer des fenêtres, Java fournit les composantsswing(dansjavax.swing) etawt(dansjava.awt).

  • Il ne faut pas mélanger les composantsswingetawt.

  • UneJFrameest constituée de plusieurs composants.

  • Par défaut, une fenêtre a une taille minimale et n'est pas visible.

  • Un composant doit être bien paramétré pour qu'il fonctionne à votre convenance.

  • L'objetJPanelse trouve dans le packagejavax.swing.

  • UnJPanelpeut contenir des composants ou d'autres conteneurs.

  • Lorsque vous ajoutez unJPanelprincipal à votre fenêtre, n'oubliez pas d'indiquer à votre fenêtre qu'il constituera son content pane.

  • Pour redéfinir la façon dont l'objet est dessiné sur votre fenêtre, vous devez utiliser la méthodepaintComponent()en créant une classe héritée.

  • Cette méthode prend en paramètre un objetGraphics.

  • Cet objet doit vous être fourni par le système.

  • C'est lui que vous allez utiliser pour dessiner dans votre conteneur.

  • Pour des dessins plus évolués, vous devez utiliser l'objetGraphics2Dqui s'obtient en effectuant un cast sur l'objetGraphics.

Exemple de certificat de réussite
Exemple de certificat de réussite