Frage zur objektorentierten Swing Programmierung

Java_Fan_

Mitglied
Guten Abend,

und zwar stelle ich mir folgende Frage. Bei diesem objektorientierten Ansatz zur Erstellung eines JFrames wurde folgender Code verwendet:

Java:
/* Listing3601.java */

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

public class Listing3601 extends JFrame {
   public Listing3601() {
      super("Ein einfacher JFrame");
      addWindowListener(new WindowClosingAdapter(true));
   }

   public static void main(String[] args) {
      Listing3601 wnd = new Listing3601();
      wnd.setLocation(100, 100);
      wnd.setSize(300, 200);
      wnd.setVisible(true);
   }
}

Nun Frage ich mich die Klasse Listing3601 erbt ja alle Eigenschaften der importierten Klasse JFrame, d.h alle Funktionen die public sind sowie Methoden(gorb gesagt). So nun zum Konstruktor von der Klasse Listing3601. Diese verwendet ja die Funktion super(). Diese ruft ja den Konstruktor von JFrame auf. Nur Frage ich mich jetzt im Hauptprogramm wie es möglich ist, dass ein Fenster erzeugt wird, wenn es doch gar kein JFrame-Objekt im Sinne von JFrame fenster = new JFrame(); geschaffen wurde? Ich weiß das es mit dem Konstruktoraufruf durch super zusammenhängt, kann mir jemand aber mal erklären wie genau?

Mit freundlichen Grüßen
 
Zuletzt bearbeitet von einem Moderator:
Die Listing Klasse erbt von JFrame und ist damit auch ein JFrame. Der new Operator auf die Listing Klasse erzeugt somit ein JFrame.

Evtl. Wird es deutlich, wenn du die eine Zeile umändert in JFrame wnd = new Listing3601();

Konrad
 
Vielen Dank, jetzt ist mir das klar geworden.

Ich hätte aber noch eine Frage und diese bezieht sich diesmal auf die Implementierung des ActionListener.
Wenn ich ein Interface implementiere, welches ja nur abstrakte Methoden erhält, dann implementiere ich ja diese abtrakten Methoden. Also als Beispiel:

Java:
interface Punktschnittstelle
{
    /* Methoden, die von einem Punkt implementiert werden sollen */
    public int getX();
    public void setX(int i);
}

/* Unsere Klasse Punkt, die das Interface PunktSchnittstelle einbindet */
public class GraphObj
{
    private int x;
     /* Implementierung der Methode getX aus dem Interface PunktSchnittstelle */
    public int getX()
    {
        return x;
    }
    /* Implementierung der Methode setX aus dem Interface PunktSchnittstelle */
    public void setX(int i)
    {
        x = i;
    }

Mit der Implementierung "verpflichtet" man sich ja sozuagen, dass eine Klasse, die ein Interface implementiert, dass diese die Methoden des Interfaces beinhaltet. In diesem Beispiel kann man also auch das implementeren des Interfaces Punktschnittstelle weglassen und es würde funktionieren.

Im jetzigen Beispiel

Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

// Damit Objekte der Klasse BeispielListener
// zum ActionListener werden kann, muss das Interface
// ActionListener implementiert werden
public class BeispielListener extends JFrame implements ActionListener
{
    JButton button1;
    JButton button2;
    JButton button3;
    JLabel label;
    JPanel panel;

    public BeispielListener(){
        this.setTitle("ActionListener Beispiel");
        this.setSize(400, 200);
        panel = new JPanel();

        // Leeres JLabel-Objekt wird erzeugt
        label = new JLabel();

        //Drei Buttons werden erstellt
        button1 = new JButton("Button 1");
        button2 = new JButton ("Button 2");
        button3 = new JButton ("Button 3");

        //Buttons werden dem Listener zugeordnet
        button1.addActionListener(this);
        button2.addActionListener(this);
        button3.addActionListener(this);

        //Buttons werden dem JPanel hinzugefügt
        panel.add(button1);
        panel.add(button2);
        panel.add(button3);

        //JLabel wird dem Panel hinzugefügt
        panel.add(label);
        this.add(panel);
    }

    public static void main(String[] args)
    {
        // Ein neues Objekt der Klasse BeispielListener wird erzeugt
        // und sichtbar gemacht
        BeispielListener bl = new BeispielListener();
        bl.setVisible(true);
    }

    public void actionPerformed (ActionEvent ae){
        // Die Quelle wird mit getSource() abgefragt und mit den
        // Buttons abgeglichen. Wenn die Quelle des ActionEvents einer
        // der Buttons ist, wird der Text des JLabels entsprechend geändert
        if(ae.getSource() == this.button1){
            label.setText(("Button 1 wurde betätigt"));
        }
        else if(ae.getSource() == this.button2){
            label.setText("Button 2 wurde betätigt");
        }
        else if (ae.getSource() == this.button3){
            label.setText(("Button 3 wurde betätigt"));
        }
    }
}

verstehe ich nicht so ganz, warum ich den ActionListener implementieren muss, wenn dieser doch wie eh nur abstrakte Methoden enthält. Warum darf ich die Implementierung des ActionListener nicht einfach weglassen?
 
Klassen welche ein Interface implementieren verpflichten sich bestimmte Methoden zu implementieren (ob diese sinnvoll oder nicht sinnvoll implementiert sind ist etwas anderes 😉).

Deine Klasse "BeispielListener" implementiert das Interface "ActionListener" und muss daher dessen Methode implementieren.
Deine Klasse "GraphObj" implementiert keine Interfaces daher könnte man die Methode getX und setX auch weglassen.
 
Das Wichtige ist, dass ich dann eine Instanz der Klasse unter dem Interface ansprechen kann.

Also bei Deinem Beispiel mit der Punktschnittstelle:

Wenn ich eine Funktion habe, die als Parameter eine Punktschnittstelle erwartet, dann kann ich ein GraphObj derzeit nicht übergeben. Sobald GraphObj aber Punktschnittstelle implementiert kann ich eine Instanz von GraphObj übergeben.

So auch in dem konkreten Beispiel: addActionListener will einen ActionListener als Parameter. Wenn Deine Class ActionListener nicht implementiert, dann kannst Du die auch nicht übergeben, aber genau das willst Du ja wenn Du this übergibst.

Konrad
 
"Das Wichtigste ist, dass ich dann eine Instanz der Klasse unter dem Interface ansprechen kann."
Könntest du das nochmal bitte erläutern? Ich dachte der ActionListener wäre nur ein Interface. Ich kann doch auch so mit this die Klasse BeispielListener ansprechen? Und das die Klasse BeispielListener die Methoden des ActionListener verwenden muss, ist ja verständlich, aber warum muss ich ihn implementieren. Ich könnte ja auch einfach so seine Funktion add verwenden, da diese ja im Interface nur abstrakt und nicht konkret formuliert ist?
 
Also wenn Klasse MyClass von SuperClass abgeleitet wird und MyInterface implementiert, dann sind folgende Zuweisungen möglich:
Code:
MyClass c = new MyClass();
SuperClass s = c;
MyInterface i = c;

Und Dein Code hatte u.a. folgende Zeilen:
Code:
        button1.addActionListener(this);
        button2.addActionListener(this);
        button3.addActionListener(this);

Hast Du Dir die Dokumentation der Funktion addActionListener schon einmal angesehen? Was wird da als Parameter erwartet?
Also https://docs.oracle.com/javase/7/docs/api/javax/swing/JButton.html ansehen - addActionListener ist von AbstractButton geerbt. Und somit landet man bei https://docs.oracle.com/javase/7/do...ActionListener(java.awt.event.ActionListener)

Argument ist ein ActionListener. Und aus dem ersten Beispiel hast Du hoffentlich gelernt, dass Instanzen einer Klasse nicht nur in ihre Super-Klassen sondern auch in die implementierten Interfaces gecastet werden kann.

Konrad
 
Also nur um noch einmal sicher zu gehen, dass ich das richtig verstanden habe. Der ActionListener ist ein Interface der Klasse AbstractButton, die ich geerbt habe(durch das JFrame?) und deshalb muss ich den ActionListener als Interface implementieren?
 
ActionListener ist einfach ein Interface. Das hat erst einmal mit keiner Klasse etwas zu tun. Nur eben gibt es dann Funktionen, die eine Instanz erwarten, die dieses Interface implementieren.

In diesem Fall ist das einfach eine Klasse, die auf eine Aktion hört. Dem Button wird sozusagen gesagt, in welcher Instanz die Funktion actionPerformed aufgerufen werden soll. Und in Deinem Code wolltest Du eben, dass dies Bestandteil Deiner Klasse BeispielListener sein soll. Das könnte aber auch irgend eine andere, beliebige Klasse sein. Ein Pattern, dass man öfters sieht ist die Erstellung einer neuen annonymen Klasse nur für diese Listener:
Code:
// ActionListener wird als anonyme Klasse eingebunden
        someItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                // Code der ausgeführt werden soll ...
            }
        });

Konrad
 

Neue Themen


Zurück
Oben