web-dev-qa-db-fra.com

Préoccupations concernant la fonction de JPanel: paintcomponent ()

bonjour je suis nouveau dans la programmation Java, et j'ai besoin que quelqu'un m'explique ces lignes de code:

 public class drawpanel extends JPanel
 {
     public void paintComponent(Graphics g)
     { 
         super.paintComponent(g);
         ...
     }
 }

Je ne comprends pas la ligne public void paintComponent(Graphics g): pourquoi dois-je déclarer cette fonction comme ça si elle est prédéfinie dans JPanel?

Et cette ligne super.paintComponent(g): Je ne la comprends pas du tout. Merci de votre aide.

19
jose gabriel

La structure de base:

Le mot clé extends signifie que DrawPanel hérite de JPanel. En d'autres termes, DrawPanel "est un" JPanel. En tant que tel, il peut remplacer ses méthodes (celles qui ne sont pas marquées final). Vous voudrez peut-être le faire pour plusieurs raisons. Par exemple, vous souhaiterez peut-être accéder à la classe Graphics du panneau, que vous pouvez utiliser pour dessiner un cercle sur le panneau, ou un graphique à barres ou une chaîne de texte.

Si vous ne remplacez aucune méthode, alors lorsque vous étendez JPanel, vous obtenez quelque chose comme ceci:

public class DrawPanel extends JPanel {
    //TODO not much
}

Cependant, ce n'est pas très utile ... à moins que vous n'aimiez tout simplement pas le nom JPanel et que vous vouliez l'appeler AwesomePanel à la place ( note: don ' t faire cela ). Si c'est tout ce que vous avez, vous feriez mieux de simplement créer un instance de JPanel, comme ceci: JPanel drawPanel = new JPanel();


paintComponent:

Le but de l'extension d'un JPanel est de remplacer la méthode paintComponent. JPanel est invisible jusqu'à ce que vous remplaciez paintComponent ( note: être invisible est ce qui en fait un conteneur utile pour les boutons et autres composants ). Vous avez raison de dire que la méthode paintComponent est prédéfinie (dans la classe JComponent si vous vous posez la question), mais tout ce que cette méthode fait est de créer un JPanel vide. Si vous souhaitez dessiner quelque chose sur le panneau, vous devez le remplacer, comme ceci:

public class DrawPanel extends JPanel {
    @Override public void paintComponent(Graphics g) { // <-- HERE!
        //TODO draw stuff
    }
}

note: la partie @Override n'est pas strictement nécessaire mais il est recommandé de l'inclure car elle réduit le nombre d'erreurs d'exécution et améliore la lisibilité du code

Vous avez maintenant accès à l'objet Graphicsg pour le panneau. Graphics est une classe d'aide qui vous permet de dessiner des choses sur le panneau, comme ceci:

public class DrawPanel extends JPanel {
    @Override public void paintComponent(Graphics g) {
        g.drawOval(50, 50, 50, 50); // <-- draws an oval on the panel
    }
}

super.paintComponent:

métaphore utile (que je viens de composer): Le JPanel est le canevas, le Graphics l'objet est votre pinceau, et super.paintComponent(g) est votre gomme. (De plus, JFrame est votre chevalet.)

Ainsi, super.paintComponent(g) appelle la méthode paintComponent de la superclasse de JPanel (la classe JComponent) pour effacer tout ce qui est actuellement dessiné sur le panneau. Ceci est utile pour l'animation.

Par exemple, envisagez de dessiner une horloge analogique sur le panneau. Vous devez le rafraîchir toutes les secondes, de sorte que chaque seconde, vous devez effacer l'horloge précédente et redessiner l'horloge, en ajustant l'aiguille des secondes. Si vous n'invoquez pas super.paintComponent(g) avant de redessiner l'horloge, elle continuera à dessiner de nouvelles horloges par dessus les anciennes horloges et en 60 secondes ce que vous aurez sera juste un cercle rempli, plus ou moins .

Une dernière chose à retenir: appelez toujours super.paintComponent(g) d'abord dans la méthode paintComponent, comme ceci:

public class DrawPanel extends JPanel {
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // <-- HERE!
        g.drawOval(50, 50, 50, 50);
    }
}

C'est tout. N'hésitez pas à me contacter.


Exemple:

J'ai créé un exemple simple qui utilise ces concepts pour afficher une chaîne de texte sur un panneau (qui est placé à l'intérieur d'un cadre). Enregistrez dans votre IDE as TestPanel.Java.

import Java.awt.*;
import Java.util.*;
import javax.swing.*;

/**
 * A frame containing a panel that is sometimes red and sometimes 
 * blue. Also, it displays the Word to go with it. 
 * 
 * Inspired by www.sometimesredsometimesblue.com.
 *
 */
public class TestPanel extends JPanel {

    private Random random = new Random();
    private boolean isRed;
    private String s = "";

    public TestPanel() {
        //randomly determine whether the background should be red
        isRed = random.nextBoolean();

        //set the background to blue
        setBackground(Color.BLUE);
        s = "BLUE";

        //if 'isRed' is true, set the background to red
        if (isRed) {
            setBackground(Color.RED);
            s = "RED";
        }
    }

    @Override 
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        //write either "RED" or "BLUE" using graphics
        g.setColor(Color.WHITE);
        g.setFont(new Font("serif", Font.BOLD, 60));
        g.drawString(s, getWidth() / 2 - g.getFontMetrics().stringWidth(s) / 2,
                getHeight() / 2 + g.getFontMetrics().getHeight() / 2);
    }

    //main method: create an instance of TestPanel and output it on a JFrame
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setSize(500, 500);
        f.setTitle("Sometimes Red, Sometimes Blue");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new TestPanel());
        f.setVisible(true);
    }
}
51
TheBlackKeys

paintComponent() est une méthode définie à l'origine dans la classe abstraite JComponent. Les composants qui étendent JComponent directement indirectement (s'ils sont exposés) ont la possibilité de remplacer paintComponent (). l'appel à super.paintComponent(g) appelle l'implémentation de la super classe de paintComponent() (dans votre cas, c'est JPanel). Vous voudriez remplacer paintComponent() si vous voulez faire d'autres choses avec Graphics g en plus de ce que fait déjà JPanel.

2
Bala R

Vous n'avez besoin de définir paintComponent() dans votre classe que si vous voulez changer la façon dont votre composant est dessiné. Dans votre implémentation personnalisée, vous devez appeler super.paintComponent(g);, c'est-à-dire une version de classe de base de paintComponent(), car elle fait un travail nécessaire pour préparer le composant pour le dessin.

1
pajton