27.5.2 Spätes Binden
 
Downlaod:
JDemoQuadrat Kreis.java
Der Quelltext von JDemoQUadratKreis.java:
mport java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import tauglichkeitstester.figur.*;



public class JDemoQuadratKreis extends JFrame

                               implements ActionListener {

    // Konstanten

    private static final int BREITE = 200, HOEHE = 200;

    private static int xMitte, yMitte, b=0;;



    //Attribute

    private JPanel myPanel, westPanel;

    private JButton bQuadrat, bKreis;

    private JLabel textLabel, copyRight;

    private ButtonGroup bgFarbe;

    private JRadioButton rbRot, rbGruen, rbBlau, rbSchwarz;

    private ZeichenPanel zeichenFlaeche;

    private Figur dieFigur;

    private JTextField textFeld;

    private Color farbe;



    //Konstruktor

    public JDemoQuadratKreis(String titel){

      super(titel);



      // Zum ordentlichen Beenden des Programms

      setDefaultCloseOperation(EXIT_ON_CLOSE);

    

      // Anfangswerte festlegen

      xMitte = BREITE/2; 

      yMitte = HOEHE/2; 

      b = Math.min(BREITE, HOEHE)*9/10;



      myPanel = new JPanel(new BorderLayout(15, 5));

      getContentPane().add(myPanel);

    

      westPanel = new JPanel();

      westPanel.setLayout(new BoxLayout(westPanel, 

                              BoxLayout.Y_AXIS));

      myPanel.add(westPanel,BorderLayout.WEST);



      textLabel = new JLabel("TestProgramm ", 

                             SwingConstants.CENTER);

      textLabel.setFont(new Font("MS Sans Serif", Font.BOLD, 30));

      myPanel.add(textLabel, BorderLayout.NORTH);



      textFeld = new JTextField("Durchmesser bzw. Seite 

                               in Pixel (Zahl!)",20);

      westPanel.add(textFeld);



      bgFarbe = new ButtonGroup();

    

      rbSchwarz = new JRadioButton("schwarz",true);

      rbSchwarz.addActionListener(this);

    

      rbGruen = new JRadioButton("grün",false);

      rbGruen.addActionListener(this);

    

      rbRot = new JRadioButton("rot",false);

      rbRot.addActionListener(this);

    

      rbBlau = new JRadioButton("blau",false);

      rbBlau.addActionListener(this);

    

      bgFarbe.add(rbSchwarz);

      bgFarbe.add(rbGruen);

      bgFarbe.add(rbRot);

      bgFarbe.add(rbBlau);

    

      westPanel.add(rbSchwarz);

      westPanel.add(rbGruen);

      westPanel.add(rbRot);

      westPanel.add(rbBlau);

    

      bKreis = new JButton("zeichne Kreis");

      bKreis.addActionListener(this);

      westPanel.add(bKreis);



      bQuadrat = new JButton("zeichne Quadrat");

      bQuadrat.addActionListener(this);

      westPanel.add(bQuadrat);

    

      zeichenFlaeche = new ZeichenPanel(BREITE, HOEHE);

      zeichenFlaeche.setFigur(dieFigur);               

      myPanel.add(zeichenFlaeche, BorderLayout.CENTER);



      copyRight = new JLabel("Multiplikatorengruppe 

              Informatik SII, \u00a9 2002", SwingConstants.LEFT);

      copyRight.setFont(new Font("SansSerif", Font.PLAIN, 11));

      myPanel.add(copyRight,BorderLayout.SOUTH);



      // Erscheinungsbild festlegen

      pack();

      setResizable(false);

      // Auf dem Bildschirm zentrieren und sichtbar machen

      Dimension screenSize = 

              Toolkit.getDefaultToolkit().getScreenSize();

      setLocation((screenSize.width - this.getSize().width)/2,

                (screenSize.height - this.getSize().height)/2);

      setVisible(true);

    }



    public void actionPerformed(ActionEvent e) {

        // Welches Objekt hat das Ereignis ausgelöst?

        Object obj = e.getSource();

        // Kreis wurde gewählt

        if (obj == bKreis) {

            b = Integer.parseInt(textFeld.getText())/2;

            System.out.println("Figur hat Farbe: "+farbe);

            dieFigur = new Kreis(xMitte,yMitte,b,farbe);

            zeichenFlaeche.setFigur(dieFigur);

        }

        // Quadrat wurde ausgewählt

        if (obj == bQuadrat) {

            b = Integer.parseInt(textFeld.getText());

            System.out.println("Figur hat Farbe: "+farbe);

            dieFigur = new Quadrat(xMitte, yMitte,b,farbe);

            zeichenFlaeche.setFigur(dieFigur);

        }

        //schwarz wurde gewählt

        if (obj == rbSchwarz){

          farbe = Color.black;

          System.out.println("Schwarz");

        }

        //grün wurde gewählt

        if (obj == rbGruen){

          farbe = Color.green;

          System.out.println("Grün");

        }

        //rot wurde gewählt

        if (obj == rbRot){

          farbe = Color.red;

          System.out.println("Rot");

        }

        //blau wurde gewählt

        if (obj == rbBlau){

          farbe = Color.blue;

          System.out.println("Blau");

        }

        

        repaint();

    }



    //Main-Methode

    public static void main(String args[]){

        new JDemoQuadratKreis("Quadrat- und Kreis-Tester");

    }

}

  Der Quelltext zeigt über weite Strecken Bekanntes. Was ist neu? Zunächst erkennt man, dass bei den Attributen mit

        private Figur dieFigur;

ein Variable vom Typ Figur deklariert wird.  Instanziiert wird dieFigur erst in der Methode actionPerformed:

        if (obj == bKreis) {
            b = Integer.parseInt(textFeld.getText())/2;
            System.out.println("Figur hat Farbe: "+farbe);
            dieFigur = new Kreis(xMitte,yMitte,b,farbe);
            zeichenFlaeche.setFigur(dieFigur);
        }

bzw.

        if (obj == bQuadrat) {
            b = Integer.parseInt(textFeld.getText());
            System.out.println("Figur hat Farbe: "+farbe);
            dieFigur = new Quadrat(xMitte, yMitte,b,farbe);
            zeichenFlaeche.setFigur(dieFigur);
        }

Die Entscheidung, ob dieFigur als Quadrat oder als Kreis instanziiert wird, wird erst zur Laufzeit entschieden. Wir sprechen deshalb von einer späten Bindung als eine weitere Form von Polymorphie. Die Zeichenfläche ist in einer eigenen Klasse, nämlich ZeichenPanel implementiert. Interessant ist nun, was die Methode setFigur(Figur, dieFigur), die hier für die Instanz zeichenFlaeche aufgerufen wird (grün unterlegt) tut.

Wir schauen uns dazu den Quelltext von ZeichenPanel.java an.

 

Download:
ZeichenPanel. java
import java.awt.*;

import javax.swing.*;

import tauglichkeitstester.figur.*;



class ZeichenPanel extends JPanel{

  private int width, height;

  private Figur dieFigur;

   

  public ZeichenPanel(int width, int height){

    super();

    this.width = width;

    this.height = height;

    setPreferredSize(new Dimension (width, height));

    setBorder(BorderFactory.createLineBorder(Color.darkGray,2));

    setBackground(Color.white);

  }

    

  public void setFigur(Figur dieFigur) {

    this.dieFigur = dieFigur;           

  }                                     





  public void paintComponent(Graphics g){

    super.paintComponent(g);

    // Nur wenn ein Test instanziiert ist, soll gezeichnet werden.

    if (dieFigur != null)

      dieFigur.zeigeDich(g);

    else {

      g.setColor(getBackground());

      g.drawRect(0, 0, getSize().width, getSize().height);

    }

  }

}

  Wieder ist ein Objekt, nämlich dieFigur als Figur deklariert und wird beim Aufruf der setFigur(Figur dieFigur) gebunden, d.h.  es handelt sich um ein Quadrat oder ein Kreis (gelb unterlegt). 
 
  Interessant ist die Methode paintComponent(Graphiucs g). Sie wurde von JPanel geerbt und wird hier überschrieben. Dass sie auf jeden Fall ihre geerbte Funktionalität behält, garantiert

super.paintComponent(g);

Im weitern Code bekommt diese Methode eine weitere Funktionalität. Falls dieFigur eine Referenz hat, wird dieFigur gezeichnet, also die Methode zeigeDich(Graphics g) für dieFigur aufgerufen (grün unterlegt) . Jetzt wird noch mal deutlich, warum das Zeichnen in Figur organisiert wurde. Je nach Bindung von dieFigur ruft zeigeDich(Graphics g) nachdem sie die Zeichenfarbe gesetzt hat die Methode zeichne(Graphics g) von der Tochterklasse Kreis oder Quadrat auf.

Es bleibt noch zu klären was paintComponent(Graphics g) eigentlich macht und wer sie aufruft. Die Java-Dokumentation gibt darüber Auskunft. Sobald bei einer grafischen Applikation etwas verändert wurde, ruft die VM paintComponent(Graphics g) auf, die ihrerseits die Methode paint() aufruft.

   
zu 27.6 Übungen
zur Startseite www.pohlig.de  (C) MPohlig 2004