2017-05-15 12 views
0

Je m'entraîne à dessiner une forme sur un JPanel en cliquant sur un bouton J, mais je ne peux pas. Cela fait cinq heures que je navigue sur le Web, mais je ne trouve pas le moyen de le faire. C'est ce que je veux faire: si je clique sur le bouton "Rectangle" un rectangle apparaît sous les boutons et si je clique sur le bouton "Cercle" un cercle apparaît.Comment dessiner une forme sur JPanel en utilisant ActionListener?

import javax.swing.*; 
    import java.awt.*; 
    import java.awt.event.*; 

    class Shape extends JFrame { 
     JButton rec, circle; 
     static String botSelected; 
     Shape(){ 
      frameSet(); 
     } 

     void frameSet(){ 
      JFrame frame = new JFrame(); 
      frame.setVisible(true); 
      frame.setSize(600,300); 
      rec = new JButton ("Rectangle"); 
      circle = new JButton("Circle"); 
      JPanel panel = new JPanel(); 
      frame.add(panel); 
      panel.add(rec); 
      panel.add(circle); 
      Click clk = new Click(); 
      rec.addActionListener(clk); 
      circle.addActionListener(clk); 
     } 

     public void paint (Graphics g){ 
      super.paint(g); 
      if (botSelected.equals("Rectangle")) 
       g.fillRect(50,50,50,50); 
      else if (botSelected.equals("Circle")) 
       g.fillOval(50,50,50,50); 
     } 

     public static void main (String [] arg){ 
      Shape s = new Shape(); 
     } 
    } 

    class Click implements ActionListener{ 
     public void actionPerformed (ActionEvent e){ 
      Shape.botSelected = e.getActionCommand(); 
     } 
    } 
+0

Vous devez appeler repeindre pour que les modifications apparaissent. Ce code est jonché de tant de mauvaises pratiques. Pourquoi étendez-vous JFrame? Vous ne devriez pas nommer votre classe 'Shape' parce que c'est une classe dans awt, ie' java.awt.Shape' – matt

+0

La première chose que je ferais est de lire [Painting in Swing] (http: // www. oracle.com/technetwork/java/painting-140037.html) et [Effectuer une peinture personnalisée] (https://docs.oracle.com/javase/tutorial/uiswing/painting/) pour mieux comprendre le fonctionnement du processus de peinture. Comme recommandation générale, j'éviterais 'static', ce n'est pas une solution pour la communication d'objet croisé – MadProgrammer

Répondre

1

La première chose que je voudrais faire est d'avoir une lecture par Painting in Swing et Performing custom painting pour mieux comprendre comment le processus de peinture fonctionne.

Ensuite, vous devez comprendre que JFrame est un mauvais choix pour la peinture. Pourquoi? Parce que c'est multicouche.

RootPane

A JFrame contient une JRootPane qui contient un JLayeredPane l'contentPane, glassPane et JMenuBar et dans votre exemple, il contient également un JPanel.

Avec l'exception (par défaut) du glassPane, tous ces composants sont opaques. Bien qu'il soit possible de faire dessiner quelque chose dans la méthode paint, si l'un des autres composants se peint, il sera nettoyé - car les composants Swing peuvent être peints indépendamment les uns des autres, avec demandez au parent de se peindre en premier.

Une meilleure solution est de commencer par l'extension de JPanel et remplacer sa méthode paintComponent.

Pour simplifier, je vous encourage aussi à mettre en œuvre la ActionListener contre cette classe ainsi, elle permettra la méthode actionPerformed pour accéder aux propriétés du composant et, dans votre cas, appelez repaint pour déclencher un cycle de peinture lorsque vous voulez mettre à jour l'interface utilisateur.

+0

Merci. Je ne savais pas à propos de ce verrePane. Je devrais en lire plus à ce sujet. –

1

Voici un exemple dérivé de votre code. Comme le dit @MadProgrammer, ne pas étendre JFrame.

Dans l'exemple suivant, voici les principaux changements:

  • donnent une valeur non nulle à botSelected, ou les premiers appels à paintComponent vous donnera une classe NullPointerException

  • maintenant étend JPanel et remplace paintComponent pour la peinture personnalisée

  • le ActionListener est une classe anonyme, être parce que vous n'avez pas besoin d'une classe séparée, et il a un accès direct aux champs de Shape

  • botSelected n'est statique plus (voir point)

.

import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

class Shape extends JPanel { 
    JButton rec, circle; 
    String botSelected = "";// don't let it be null, it would make paintComponent crash on startup 

    Shape() { 
     frameSet(); 
    } 

    void frameSet() { 
     JFrame frame = new JFrame(); 
     frame.setVisible(true); 
     frame.setSize(600, 300); 
     rec = new JButton("Rectangle"); 
     circle = new JButton("Circle"); 

     frame.add(this); 
     this.add(rec); 
     this.add(circle); 
     // anonymous class, has access to fields from the outer class Shape 
     ActionListener clk = new ActionListener() { 
      public void actionPerformed(final ActionEvent e) { 
       botSelected = e.getActionCommand(); 
       repaint(); 
      } 

     }; 
     rec.addActionListener(clk); 
     circle.addActionListener(clk); 
    } 

    //custom painting of the JPanel 
    @Override 
    public void paintComponent(final Graphics g) { 

     super.paintComponent(g); 
     if (botSelected.equals("Rectangle")) { 
      g.fillRect(50, 50, 50, 50); 
     } else if (botSelected.equals("Circle")) { 
      g.fillOval(50, 50, 50, 50); 
     } 
    } 

    public static void main(final String[] arg) { 
     Shape s = new Shape(); 
    } 

} 
+0

Merci beaucoup. J'ai beaucoup appris. –

+0

Je ne comprends toujours pas pourquoi l'extension de JFrame n'a pas fonctionné mais Jpanel fonctionne. et comment le "ceci" fonctionne pour ajouter les boutons. Et pourquoi la dernière chaîne dans la méthode principale? Où puis-je en lire plus à ce sujet? TNX –

+0

Un 'JFrame' a son propre contenu' JPanel', essayer de remplacer le 'paint' du' JFrame' ne fera rien d'utile. Puisque votre classe elle-même est 'JPanel',' this' signifie 'Shape'' JPanel'eself, vous pouvez donc ajouter des choses simplement avec 'this.add ...'. – Berger