CodeS-SourceS
Rechercher un code, un tuto, une réponse

Personalisation des composants Swing

Octobre 2017


Personalisation des composants Swing



Description


Ce tutoriel explique comment surcharger la méthode paintComponent des objets graphiques Swing afin de pouvoir modifier leur aspect. Les codes donnés en exemple sont disponible à cette adresse : http://codes-sources.commentcamarche.net/source/51830-personaliser-les-composants-swing


Le code de darksidious utilisé pour la partie 4 se trouve à cette adresse : http://codes-sources.commentcamarche.net/source/42967-button-graphique-effet-glass



Introduction


La personnalisation des composants se fait toujours de la même manière, en surchargeant les méthodes paintCompoent du composant à personnaliser. Nous allons voire comment insérer un dégradé de couleur, une image sur des boutons ou des JPanel. Ces deux composants nous permettrons d'aborder les principales difficultés rencontrées. Il sera donc facile de personnaliser d'autres composants une fois que nous saurons comment personnaliser ces composants.

La méthode paintComponent et les formes de base


La méthode paintComponent permet de dessiner un objet graphique. Cette méthode est définie pour tous les composants Swing et nous l'appelons sans le savoir quand nous faisons un repaint(). Elle prend un attribut Graphics. C'est l'élément sur lequel nous allons dessiner.

Surcharge de la méthode


Surcharger une méthode signifie redéfinir la méthode pour une classe héritière, voici la base de la surcharge de la méthode paintComponent pour un Jpanel :


public class PanelPerso extends JPanel {

    public PanelPerso(){
        super();
    }

    protected void paintComponent(Graphics g){
    }
}

Comment dessiner ?


Pour dessiner le composant il suffit donc de remplir la méthode paintComponent. Les paragraphes suivants nous donnent les bases pour dessiner.

Comment se repérer ?


L'origine du repère est situé en haut à gauche du composant, l'axe des abscisses est orienté de gauche à droite et l'axe des ordonnées de haut en bas.

Pour connaître les dimensions du composant, nous allons utiliser les méthodes getWidth() pour la largeur et getHeigth() pour la hauteur.

Premier dessin : une ligne diagonale sur le JPanel


protected void paintComponent(Graphics g){

    /* La diagonale va de l'origine au point bas gauche
     * donc du point (0, 0) au point (getWidth(), getHeigth())
     */
    g.drawLine(0, 0, getWidth(), getHeight());
}

Les dessins possibles


Ovale : g.drawOval(x, y, width, height);

Arc de cercle : g.drawArc(x, y, width, height, startAngle, arcAngle);

Rectangle : g.drawRect(x, y, width, height);

Rectangle arrondi : g.drawRoundRect(x, y, width, height, arcWidth, arcHeight);

Chaîne de caractères : g.drawString("chaine", x, y);

Les méthodes préfixées par draw ne dessinent que les contours, pour remplir le dessin, on utilise les mêmes méthodes préfixées par fill.

Les couleurs


Pour dessiner en couleurs, il suffit de faire un setColor sur l'élément graphique. Par exemple, pour dessiner les deux diagonales d'un JPanel de couleurs différentes le tout sur un rectangle blanc :

protected void paintComponent(Graphics g){
    g.setColor(Color.white);
    g.fillRect(0, 0, getWidth(), getHeight());
    g.setColor(Color.cyan);
    g.drawLine(0, 0, getWidth(), getHeight());
    g.setColor(Color.red);
    g.drawLine(getWidth(), 0, 0, getHeight());
}

Insérer une image


public void paintComponent(Graphics g) {
    try {
        BufferedImage image = ImageIO.read(new File(adresseImage));
        g.drawImage(image, 0, 0, null);
    }
    catch (IOException e) {
       e.printStackTrace();
    }
}

Écrire et centrer le texte


Lorsqu'on surcharge les paintComponent des composants tels que JLabel et JButton, il faut redéfinit l'écriture du texte et centrer le texte.

Les lignes suivantes permettent de récupérer les coordonnées qui vont centrer le texte « Texte »

FontMetrics fm = g.getFontMetrics();
int x = (this.getWidth() - fm.stringWidth("Texte")) / 2;
int y = (fm.getAscent() + (this.getHeight() - (fm.getAscent() + fm.getDescent())) / 2);

Code de la fonction paintComponent permettant de créer un bouton avec un texte et un rectangle centrés:

public void paintComponent(Graphics g){
    g.setColor(Color.orange);
    g.fillRect(getWidth()/2 - getWidth()/8, getHeight()/2 - getHeight()/8, getWidth()/4, getHeight()/4);
    
    g.setColor(Color.black);
    FontMetrics fm = g.getFontMetrics();
    int x = (this.getWidth() - fm.stringWidth(this.name)) / 2;
    int y = (fm.getAscent() + (this.getHeight() - (fm.getAscent() + fm.getDescent())) / 2);
    g.drawString(this.name, x, y);
}

Vous savez à présent personnaliser vos composants de manière assez basique, nous allons voire comment obtenir des composants de meilleure qualité avec des gradients.

Utilisation des gradients


Les gradients sont des dégradés de couleurs, ils peuvent contenir autant de couleurs que vous voulez, nous nous limiterons à deux, il sera cependant facile d'en faire de même avec trois couleurs ou plus.

Construction du gradient


Le gradient est constitué de deux couleurs que nous appellerons couleur1 et couleur2. Pour le définir, nous avons également besoin de savoir à quel endroit la couleur du gradient sera exactement la couleur définie. Nous allons donc utiliser le tableau dist.

Color[] colors = {couleur1, couleur2};
float[] dist = {0.0f, 1.0f};
/* Ce qui signifie qu'au point de départ du gradient (0.0f),
* le gradient à la couleur couleur 1 */

new LinearGradientPaint(
    new Point2D.Float(0, 0),
    new Point2D.Float(0, hauteur),
    dist,
    colors);

Surcharge de paintComponent


Le problème du gradient pour la surcharge de la méthode paintComponent est que ce n'est pas un objet graphics mais graphics 2D. Nous devons donc caster g en Graphics2D.

Graphics2D g2d;

if (g instanceof Graphics2D) {
    g2d = (Graphics2D) g;
}
else {
    System.out.println("Error");
    return;
}


Code complet de la méthode

protected void paintComponent(Graphics g){
    Paint paint;
    Graphics2D g2d;
    if (g instanceof Graphics2D) {
        g2d = (Graphics2D) g;
    }
    else {
        System.out.println("Error");
        return;
    }

    Color[] colors = {couleur1, couleur2};

    float[] dist = {0.0f, 1.0f};

    paint = new LinearGradientPaint(

    new Point2D.Float(0, 0),

    new Point2D.Float(0, getHeight()), dist, colors);

    g2d.setPaint(paint);

    g2d.fillRect(0, 0, getWidth(), getHeight());
}

Construction d'un bouton effet glass


Cette partie s'inspire d'un code posté par Darksidious à l'adresse suivante : http://codes-sources.commentcamarche.net/source/42967-button-graphique-effet-glass

Cette classe permet de créer un bouton assez sympa, testez le et vous verrez...

public class BoutonRond extends JButton {

    private static final long serialVersionUID = 1L;
    private final int BULLE_WIDTH;
    private Color BULLE_COLOR;
    private Color BULLE_COLOR_D;
    private Color BULLE_COLOR_B;
    private Color currentColor;
    private Color couleurTexte;
    private Font font;
    private String texte="null";
    private int x = 4;
    private int y = 4;

    public BoutonRond(Color couleur, int taille) {
        BULLE_COLOR=couleur;
        BULLE_COLOR_D=couleur.darker();
        BULLE_COLOR_B=couleur.brighter();
        currentColor=BULLE_COLOR_D;
        BULLE_WIDTH=taille;
        initialize();
    }

    public BoutonRond(Color couleur, int taille, String texte, Font f, Color couleurTexte) {
        BULLE_COLOR=couleur;
        BULLE_COLOR_D=couleur.darker();
        BULLE_COLOR_B=couleur.brighter();
        currentColor=BULLE_COLOR;
        BULLE_WIDTH=taille;
        this.font=f;
        this.texte=texte;
        this.couleurTexte=couleurTexte;
        initialize();
    }

    public void setColor(Color c){
        this.BULLE_COLOR_D=c;
    }

    private void initialize() {
        this.setFocusPainted(false);
        this.setSize(new Dimension(BULLE_WIDTH + 10, BULLE_WIDTH + 10));
        this.setBorderPainted(false);
        this.setContentAreaFilled(false);
        this.setOpaque(false);
        this.addMouseListener(new java.awt.event.MouseListener() {
            public void mouseEntered(java.awt.event.MouseEvent e) {
                if (isEnabled()) {
                    // on change la couleur
                    currentColor = BULLE_COLOR_B;
               }
            }

            public void mouseClicked(java.awt.event.MouseEvent e) {
            }

            public void mousePressed(java.awt.event.MouseEvent e) {
                x-=2;
                y-=2;
            }

            public void mouseReleased(java.awt.event.MouseEvent e) {
                x+=2;
                y+=2;
            }

            public void mouseExited(java.awt.event.MouseEvent e) {
                if (isEnabled()) {
                    // on rétablit la couleur d'origine
                    // System.out.println("couleur d'origine");
                   currentColor = BULLE_COLOR_D;
                }
            }
        });
    }

    public void paint(Graphics arg0) {
        super.paint(arg0);
        Graphics2D g2d = (Graphics2D) arg0;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(currentColor);
        g2d.setStroke(new BasicStroke(3));
        g2d.drawOval(x, y, BULLE_WIDTH, BULLE_WIDTH);
        GradientPaint gradient = new GradientPaint(BULLE_WIDTH / 2, y,
        currentColor, (BULLE_WIDTH) / 2, y + BULLE_WIDTH, Color.white);
        g2d.setPaint(gradient);
        g2d.fillOval(x, y, BULLE_WIDTH, BULLE_WIDTH);
        gradient = new GradientPaint(BULLE_WIDTH / 2, y, Color.white,
        BULLE_WIDTH / 2, y + BULLE_WIDTH / 2, new Color(currentColor
        getRed(), currentColor.getGreen(), currentColor
        getBlue(), 0));
        g2d.setPaint(gradient);
        g2d.fillOval(x + BULLE_WIDTH / 5, y, 5 * BULLE_WIDTH / 8,
        BULLE_WIDTH / 3);
        
        if(this.texte!="null"){
            g2d.setFont(this.font);
            float[] dist = {0.1f, 0.3f};
            Color c = new Color(22,22,22,0);
            Color[] colors = {c, this.couleurTexte};
            Paint gp = new LinearGradientPaint(new Point2D.Float(0, 0),
            new Point2D.Float(0, getHeight()), dist, colors);
            g2d.setPaint(gp);
            FontMetrics fm = g2d.getFontMetrics();
            int x0 = (this.getWidth() - fm.stringWidth(this.texte)) / 2;
            int y0 = (fm.getAscent() + (this.getHeight() -
            (fm.getAscent() + fm.getDescent())) / 2);
            g2d.drawString(this.texte, x0, y0);
        }
    }
}

A voir également

Publié par cs_Julien39.
Ce document intitulé «  Personalisation des composants Swing  » issu de CodeS-SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
CVS dans Eclipse
Java pour iPhone avec iSpectrum : tutoriel sur UIPageControl et UIScrollView