ActionListener - Swinguebungen

Googlehupf

Erfahrenes Mitglied
Hallo!

Ich/Wir haben erst vor 2 Wochen angefangen mit Java und gleich ein bisschen Swing kennengelernt.

Nun habe ich 2 Aufgaben, die ich erledigen muss:

Übung 1: Fenster mit Button. Wenn Button gedrückt wird dann soll es von Rot auf Grün bzw. von Grün auf Rot wechseln.

Übung 2: 2 Buttons. Einer Grün(text) und der andere Rot(text). Soll immer der button(text: grün bzw. rot) der den aktuellen Hintergrund(rot bzw. grün) entspricht gesperrt sein. Also, wenn der Hintergrund grün ist, soll jener Button gesperrt sein wo "grün" drauf steht und das gleiche mit rot.

Ich kann die Aufgaben nicht besser beschreiben, aber wenn ihr euch den Code anschaut dann wirds sicher klar^^.

Die 1. Aufgabe funktioniert ja einwandfrei, aber bei der 2. hab ich nicht wirklich eine Ahnung wie ich das machen soll. Könnt ihr mir paar Tipps geben bitte?

Java:
package uebg01;
 
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
 
public class MainFrame extends JFrame {
    private JPanel contentPane;
    private JButton button1;
    private JButton button2;
    private JPanel panel1;
    
    public MainFrame() {
        try {
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            FrameInit();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
 
    /**
     * Component initialization.
     * 
     * @throws java.lang.Exception
     */
    private void FrameInit() throws Exception {
        contentPane = (JPanel) getContentPane();
        contentPane.setLayout(new BorderLayout());
        setSize(new Dimension(400, 300));
        setTitle("Frame Title");
 
        panel1 = new JPanel();
        panel1.setLayout(new FlowLayout());
        panel1.setBackground(Color.green);
        button1 = new JButton();
        button2 = new JButton();
        button1.setText("red");
        button2.setText("green");
        button1.setFont(new Font("Calibri", Font.BOLD, 15));
        button2.setFont(new Font("Calibri", Font.BOLD, 15));
        button1.addActionListener(new Button1_ActionListener());
        button2.addActionListener(new Button2_ActionListener());
        panel1.add(button1);
        panel1.add(button2);
        contentPane.add(panel1, BorderLayout.CENTER);
        button2.setEnabled(false);
    }
 
    private class Button1_ActionListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            if (panel1.getBackground() == Color.green) {
                panel1.setBackground(Color.red);
                button1.setText("green");
                button2.setEnabled(true);
                button1.setEnabled(false);
            } else {
                button1.setEnabled(false);
                panel1.setBackground(Color.green);
                button1.setText("red");
                button2.setEnabled(false);
            }
        }
    }
    
    private class Button2_ActionListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            if (panel1.getBackground() == Color.green) {
                panel1.setBackground(Color.red);
                button2.setText("green");
                button2.setEnabled(true);
                button1.setEnabled(false);
            } else {
                button1.setEnabled(false);
                panel1.setBackground(Color.green);
                button2.setText("red");
                button2.setEnabled(false);
            }
        }
    }
}

Andere Frage:

Es geht um ActionListener. ActionListener funktioniert ja nur bei JButton, also wenn eine Schaltfläche gedruckt wird bekommt das ActionListener mit, richtig?

Aber wie funktioniert das jetzt intern im PC, bei der Programmausführung?
In C ist das irgendwie alles viel einfach zu verstehn, das Programm wird von oben bis unten im main() einfach durchgearbeitet, klar ist es in Java ähnlich, aber in C einfach zu verstehn finde ich.

Hier mal ein Bsp-Code dazu:
Java:
    private class button1_ActionListener implements ActionListener {
        private int i;
        public void actionPerformed(ActionEvent ae) {
            i++;
            label1.setText("Button gedrückt:"+i+" mal gedrückt");

        }
    }


Jedes mal wenn die Schaltfläche gedrückt wird wird hinaufgezählt. Muss man den, wenn man den ActionListener verwenden will immer so schreiben? mit dem actionPerformed etc.? Also diese 2 Blöcke da?

Da steht ja button1_ActionListener wird implementiert in ActionListener, oder von ActioListener? Wie sagt man das genau? Was heißt "implementieren" in diesem Fall? Ähnlich wie extends(ableiten)?

Kann ich das so beschreiben: Wenn man eine Schaltfläche drückt, dann wird die Klasse button1_ActionListener aufgerufen, oder das ActionPerformed und dies kann man als "Endlosschleife" sehn?

Danke im voraus!

mfg
 
Hi

zur Aufgabe zuerst:
Am ANfang setzt du ja ienen der zwei Buttons sofort auf Disabled, soll ja auch so sein.
Aber: Da er so ja nicht mehr gedrückt werden kann
brauchst du das if-else im actionListener ja nicht.
Wenn der Button gedrückt wird/werden kann
ist sicher immer ein bestimmter Zustand, Rot oder Grün.

Beim einen Button schreibst du dann eben rein:
Farbe auf grün, sich selbst dis- und den anderen Button enablen.
Der Andere Button:
Farbe auf rot, sich selbst dis- und den anderen Button enablen.
Je drei Befehle, ohne irgendwas Komplizierteres.


Zur Theorie, C-Teil:
Bist du in C über die Konsole rausgekommen?
Beim GUI-erstellen findet man auch in C/C++ das Listener-Prinzip wieder.
Da geht nichts mehr von oben nach unten durch,
sondern es werden auch für bestimtme Ereignisse (wie Klicks) Aktionen festgelegt.
Ob das jetzt Actionlistener oder WM_MOUSEDOWN oder irgendwie Anders genannt wird,
ist vom Prinzip her egal.
Auf diese Eventart machts für eine GUI einfach mehr Sinn.
Die sture Oben-nach-unten-Ausführung geht schwer, wenn man nicht voraussagen kann,
was der Benutzer mit Maus/Tastatur als nächstes macht.


Zu deiner "Verpackung" für die Listener:
Die eigene Klasse rundherum ist nicht nötig, actionPerformed allein reicht.
Also als normale Methode auf selber Ebene wie FrameInit etc.
Beim addActionListener, wo ja die Klasse angegeben werden muss,
machst du dann kein new..., sondern verwendest die vorhandene Klasse,
in der FrameInit gerade ausgeführt wird. Also "this".


Zum implements:
Ja, das ist sowas wie extends. Stichwort Interface.
Bei extends änderst du ja eine vorhandene Klasse ab, die auch allein funktionieren kann.
Bei einem Interface steht zuerst nur drin, dass es zB. eine Methode actionPerformed
mit xxyy Parametern geben muss, ohne dass die Methoden einen wirklichen Inhalt
haben. Das ist dann deine Aufgabe. Das Interface allein hat nichts zum Ausführen
und kann so allein nicht verwendet werden.

Warum ActionListener da eingebunden wird:
ActionListener schreibt eben eine Methode actionPerformed vor, was bei der Action gemacht wird.
Der Compiler prüft dann auch, ob du wirklich ein actionPerformed programmiert hast.
addActionListener nimmt dann als Parameter alles, was ActionListener implementiert
und kann sich so sicher sein, dass es ein aufrufbares actionPerformed gibt.

ActionListener ist übrigens nicht auf JButton beschränkt.


Am Rande noch:
Auch die ganzen Listenersachen haben ihren Ursprung im Von-oben-nach-unten-durch.
Allerdings wird das vom Betriebssystem verwaltet,
hat für Programmierer und Computer einige Vorteile.
Das OS kontrolliert regelmäßig Maus/Tastatur usw.
und gibt das an die einzelnen GUI-besitzenden Programme weiter.
Die haben dann eben für bestimmte Nachrichten vom OS bestimmte Codeteile,
die als Reaktion ausgeführt werden.
Im Fall Java gehts zuerst noch über die JVM, die das in Aufrufe der Listener umsetzt.
 
Ok, danke!

Dieses extends, implements(interface etc.) verstehe ich noch nicht so ganz. Könntest du mir bitte kleine Code-Beispiele dazu machen und dann vergleichen?

Warum darf ich beim ActionListener nicht einfach extends nehmen?

Java:
public class MainFrame extends JFrame
--> MainFrame kann alle Klassen/Methoden benutzen die JFrame auch vererbt bekommen hat und selber hat richtig? Aber wo setzen wir da MainFrame? Ich sehe hier nur dann eine Methode und dann ein weiterer Methoden aufruf, wo dann alles gemacht wird.

Wie läuft den dieser Vorgang genau ab?

Code-Ausschnitt von der Aufgabe:
Java:
    private void FrameInit() throws Exception {
        contentPane = (JPanel) getContentPane();//Panel erzeugen?
        contentPane.setLayout(new BorderLayout());//was heißt das?
        setSize(new Dimension(400, 300)); // Fenstergröße bestimmen - ist klar
        setTitle("Frame Title"); // Titel bestimmen, auch ok
        panel1 = new JPanel();// hier erzeugt man eine Instanz(oder Objekt?) von der Klasse Jpanel? Also keine Kopie?
        panel1.setLayout(new FlowLayout());//was ist das? mach das den Button zum kleinen Button?
        panel1.setBackground(Color.green);// farbe ändern
        button1 = new JButton(); // selbe wie bei new JPanel
        button1.setText("red");
        button1.addActionListener(new Button1_ActionListener());// selbe wie bei new JPanel?
        panel1.add(button1);//button auf panel1 platzieren
        contentPane.add(panel1, BorderLayout.CENTER);//panel auf panel platzieren? Was soll das bitte? Warum eig. 2mal JPanel verwenden?
    }

Was ist den mit Panel eigentlich gemeint hier? Also ein Panel, wort wörtlich übersetzt ist ja eine Tafel, oder Platte.
 
Zuletzt bearbeitet:
Also...
Kleinere sprachspezifische Sachen wie public vor jeder Methode, override usw.
sind hier mal weggelassen, zur Übersichtlichkeit.

Eine Klasse
Code:
class A {
    void ausgabe() {
        println("Hier ist A");
    }
}
wäre so fertig.
Folgendes kann man jetzt machen:
Code:
A bla = new A();
bla.ausgabe();
und das funktioniert auch.

Vererbend kann man zB. sowas machen:
Code:
class B extends A {
    void andereAusgabe() {
        println("Lalala");
    }
}
Bei Instanzen von B kann man andereAusgabe und ausgabe aufrufen.
ausgabe von A bleibt also erhalten.

Code:
class C extends A {
}
geht auch, da kommt eben nichts Neues dazu.
ausgabe gibts aber trotzdem.

Code:
class D extends A {
    void ausgabe() {
        println("hehe, nicht die alte Ausgabe");
    }
}
geht auch.
ausgabe ist hier durch was Neues überschrieben worden
und macht bei D dadurch nicht das Selbe wie bei A.
Trotzdem gibt es immerhin ein ausgabe, das aufgerufen werden kann und etwas macht.

Also egal, was man macht, alles was von A erbt (und A selber) hat garantiert ein ausgabe.
Das geht nicht weg.

Wenns jetzt irgendwo etwas gibt, dem man ein A übergeben soll
Code:
void irgendwas(A parameter) {
    parameter.ausgabe();
}
kann man drin ausgabe aufrufen, weil das garantiert immer vorhanden ist.
Egal ob man jetzt wirklich ein A, oder B, C oder D übergibt
(man kann ja außer A alles übergeben, das von A erbt).
Alles Mögliche hat ausgabe.


Ein Interface ist eine Klasse ohne tatsächlichen ausführbaren Code, wie
Code:
interface hatAusgabe {
    void ausgabe();
}
Folgendes geht nicht:
Code:
hatAusgabe bla = new hatAusgabe();
bla.ausgabe();
ausgabe hat ja nichts, was es beim Aufruf tun könnte.
(Und weil es im Sinn von einem Interface liegt, so unvollständig zu sein,
kann man mit new auch keine Instanzen erzeugen.)

Wozu ist das gut:
Code:
class A implements hatAusgabe {
    void ausgabe() {
        println("Hier ist A");
    }
}
Code:
void irgendwas(hatAusgabe parameter) {
    parameter.ausgabe();
}
Wirds klarer?
Alles, was ein hatAusgabe ist, hat garantiert ein Ausgabe.
Übergeben kann man alles, was hatAusgabe implementiert.
Und A, was ja hatAusgabe implementiert, wird damit gezwungen,
auch ein ausgabe mit Code bereitzustellen (sonst Compilerfehler, ausgabe fehlt noch).
Code:
class A implements hatAusgabe {
    void irgendwasAnderes() {
        ...
    }
}
ist nicht möglich, es muss mindestens ein ausgabe vorhanden sein,
damit es dem Interface entspricht.
(irgendwasAnderes geht natürlich schon, aber nicht allein).



Um zum ActionListener zurückzukommen:

addActionListener will irgendwas, bei dem actionPerformed aufgerufen werden kann.
Es gibt ein Interface ActionListener, das eine Methode actionPerformed vorschreibt.
Also nimmt addActionListener eben einen ActionListener.

Das, was du übergibst, braucht mindestens ein actionPerformed,
und als Qualitätssiegel implementiert es ActionListener.
Falls es doch kein actionPerformed gibt jammert der Compiler,
dass das dem ActionListener nicht reicht.

edit1:
Warum man ActionListener nicht auch als Klasse machen könnte:
a) actionPerformed kann man beim vererben ja trotzdem überschreiben
und damit seinen Wünschen nach anpassen, aber es würde einen Standardcode
in der Grundklasse brauchen (unvollständige codelose Sachen gehen nur im Interface).
Was nimmt man als Standardaktion für Mausklicks?
b) Aus verschiedenen Gründen kann eine Klasse in Java nur von einer Vaterklasse,
aber zusätzlich beliebig vielen Interfaces erben.
Wäre ActionListener eine Klasse müsste dein MainFrame auf JFrame verzichten
(oder du machst wie am Anfang eine Klasse pro actionPerformed).
Nicht schön.


Warum extends bei Klassen, implements bei Interface?
Einfach so. Kein tieferer Sinn. Haben sich die Erfinder von Java so gedacht.
Vielleicht, damit man beim Code-anschauen sofort sieht,
was Klassen und was Interfaces sind.

Aber wo setzen wir da MainFrame? Ich sehe hier nur dann eine Methode und dann ein weiterer Methoden aufruf, wo dann alles gemacht wird.
Was meinst du damit?


Ein Panel ist eine Art (unsichtbares) Rechteck im Fenster,
in das man andere Sachen wie Buttons reinstecken kann.
Wenn man sein Fenster in mehrere Panels unterteilt
kann man mehr Ordung/Einfachkeit reinbringen;
ganze Panels mit Inhalt woanders hinverschieben, unsichtbar machen usw.usw.
Panels kann man auch ineinander verschachteln.
Falls du dich mit HTML auskennst: <div> entspricht dem Panel

Zum Code
Was mit den JPaneln ist, ist vllt. durch den Text weiter oben schon klar?

getContentPane:
Der JFrame (das ganze Fenster) hat unter Anderem
ein Hauptpanel über seine gesamte Fläche.
Da kann man dann die ganzen Buttons etc. reintun,
oder eben selbst durch weitere Panels unterteilen.
Das (schon vorhandene) Hauptpanel bekommt man mit getContentPane.

BorderLayout etc.:
Die "normale" Vorgehensweise beim GUI-Erstellen wäre:
Man muss für jeden Button etc. Positionskoordinaten und Abmessungen in Pixeln angeben
(und auch noch berücksichtigen, was passiert, wenn der Benutzer die Fenstergröße ändert).
Swing hat unterstützend solche Layouts: Wenn man einem Panel sagt, es hat Layout xy,
kann man alle Buttons usw. einfach ohne Koordinaten/Größe reinstecken.
Diese Angaben werden dann nach bestimmten Regeln selbst berechnet;
das sind dann die einzelnen Layouts.
Jedes hat eine bestimmte Art, wie es die Sachen anordnet.
Hier für ein paar Layouts beschreibungen mit Bildern, da sollte alles klar werden:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html


Instanz/Objekt/Klasse :rolleyes:

Eine Klasse wie JPanel ist eine Vorlage/Beschreibung.
Baupläne für ein Auto.

Eine Variable "JPanel meinPanel;" ist die Garage.

Eine Instanz "new JPanel" ist ein wirkliches Auto nach den Plänen von JPanel.
So direkt hinschreiben geht aber nicht, das Auto braucht auch einen Stellplatz:
Mit "meinPanel = new JPanel" hat man das neue Auto in seiner Garage.

Und im Fall von Klassen ist Objekt einfach das Selbe wie Instanz.
Es gibt ja auch Sachen, die keine Klassen sind.
Zum Beispiel int.
int ist die Vorlage, "int a" und "int b" sind Instanzen.
Objekte kann man nur dann sagen, wenn int eine Klasse wäre.

So.
 
Danke dir! Ich denke ich habs nun Großteils verstanden :).

Hier der Code zur Aufgabe 2:
Java:
package uebg02;


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

public class MainFrame extends JFrame {
	private JPanel  contentPane;
	private JButton button1;
	private JPanel  panel1;
	private JButton button2;
	
	public MainFrame() {
		try {
			setDefaultCloseOperation(EXIT_ON_CLOSE);
			FrameInit();
		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}

	/**
	 * Component initialization.
	 * 
	 * @throws java.lang.Exception
	 */
	private void FrameInit() throws Exception {
		contentPane = (JPanel) getContentPane();
		contentPane.setLayout(new BorderLayout());
		setSize(new Dimension(400, 300));
		setTitle("Frame Title");

		panel1 = new JPanel();
		panel1.setLayout(new FlowLayout());
		panel1.setBackground(Color.green);
		
		button1 = new JButton();
		button2 = new JButton();
		button1.setText("red");
		button2.setText("green");
		button2.setEnabled(false);
		button1.addActionListener(new Button1_ActionListener());
		button2.addActionListener(new Button2_ActionListener());
		
		
		panel1.add(button1);
		panel1.add(button2);
		
		contentPane.add(panel1, BorderLayout.CENTER);
	}

	private class Button1_ActionListener implements ActionListener {
		public void actionPerformed(ActionEvent ae) {
			panel1.setBackground(Color.red);
			button2.setEnabled(true);
			button1.setEnabled(false);
		}
	}
	
	private class Button2_ActionListener implements ActionListener {
		public void actionPerformed(ActionEvent ae) {
			panel1.setBackground(Color.green);
			button1.setEnabled(true);
			button2.setEnabled(false);
		}
	}
}

Also ist das eh so gemeint, die Aufgabenstellung? Oder könnte es eventuell so sein das Aufgabe 2 an Aufgabe 1 folgt.

Jetzt zu dem JFrame, das was ich meinte war:

Hier ein Code-Bsp wo JFrame wirklich verwendet wurde:
Java:
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.FlowLayout;

public class View
{
   public static void main (String[] args)
   {
      // Hauptfenster erzeugen
      JFrame frame = new JFrame ("Hauptfenster");
      // Schaltflaeche erzeugen
      JButton button1 = new JButton ("Schaltflaeche1");

      frame.setLayout (new FlowLayout());

      // Schaltflaeche dem Hauptfenster hinzufuegen.
      frame.add (button1);
 
      frame.setSize (400, 100);
      frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
      frame.setVisible (true);
   }
}

}

Wie man hier sehn kann erzeugt das JFrame ein Hauptfenster also mit Minimieren, Maximieren und X-Button. Zuvor dachte ich immer das macht das JPanel, aber das macht nur die Aufteilung von Button etc., also ein Panel ist das was innheralb des "Fenster-Rahmens" ist, richtig?

Naja aufjedenfall kann ich nicht erkennen wo in meinen Programm das "Hauptfenster" mit "new" oder so erzeugt wird. Dies hat sicher was mit "MainFrame extends JFrame" zu tun, aber wie hängt das jetzt da zusammen? Was wird hier gemacht?

Deine Beispiele oben mit extends verstehe ich, aber da in meine Programm habe ich keine Ahung, wo das Fenster da erzeugt wird.
 
Zuletzt bearbeitet:
Zum Code:
Eigentlich ganz schön, aber eine Sache hab ich noch :)
Die Listener sind noch immer in eigenen Klassen. Wozu?
a) Die Methoden aus ihren Klassen rausnehmen und dafür in den MainFrame direkt rein.
Statt
Java:
private class Button1_ActionListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            panel1.setBackground(Color.red);
            button2.setEnabled(true);
            button1.setEnabled(false);
        }
    }
    
    private class Button2_ActionListener implements ActionListener {
        public void actionPerformed(ActionEvent ae) {
            panel1.setBackground(Color.green);
            button1.setEnabled(true);
            button2.setEnabled(false);
        }
    }
das:
Java:
        public void actionPerformed(ActionEvent ae) {
            panel1.setBackground(Color.red);
            button2.setEnabled(true);
            button1.setEnabled(false);
        }
    
        public void actionPerformed(ActionEvent ae) {
            panel1.setBackground(Color.green);
            button1.setEnabled(true);
            button2.setEnabled(false);
        }
b) Weil es jetzt ja zwei actionPerformed gibt, die eins werden müssen:
Java:
public void actionPerformed(ActionEvent ae) {
    if(ae.getSource() == button1) {
        panel1.setBackground(Color.red);
        button1.setEnabled(false);
        button2.setEnabled(true);
    }
    else if(ae.getSource() == button2) {
        panel1.setBackground(Color.green);
        button1.setEnabled(true);
        button2.setEnabled(false);
    }
}
Das ActionEvent hat verschiedene nützliche Informationen,
unter anderem den betroffenen Button als "Source".

c) Die Klasse MainFrame muss jetzt bestätigen, dass sie ein actionPerformed hat:
Java:
public class MainFrame extends JFrame implements ActionListener
d) Beim addActionListener keine neuen Objekte von den Klassen erstellen,
die es ja jetzt nicht mehr gibt, sondern einfach auf das vorhandene MainFrame verweisen:
Java:
button1.addActionListener(this);
button2.addActionListener(this);


Zu der JFrame-Sache:
So wie im Code 2 kann man JFrame auch verwenden, aber der Nachteil:
Nur sehr eingeschränkt.
In dem man sich eine eigene Klasse macht, die von JFrame erbt (eben MainFrame)
kommt man zB. zu bestimmten Methoden in JFrame dazu,
die von außen nicht aufrufbar wären (public/protected/private-Sache).
Oder solche Sachen wie "implements ActionListener" brauchen auch eine volle Klasse.
Nur auf ein einzelnes "new JFrame()" kann man das nicht anwenden,
und das Original-JFrame abändern wäre (wenn überhaupt möglich) auch nicht ideal.

Und beim MainFrame-Programm gibts sicher auch irgendwo eine Stelle mit "new MainFrame".
Wahrscheinlich in einer zweiten Codedatei.
 
Ah ok, deine Methode ist mir eigentlich klar und eigentlich viel einfacher :D. Aber das mit den komischen extends mit fertigen Klassen, in unserem Fall JFrame, bekomme ich nicht in den Kopf.

Ok, gut wir wissen das MainFrame alle Methoden/Klassen von JFrame geerbt hat.

Hier der Code, wo man ein Hauptfenster erzeugt:
Java:
package uebg02;

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

public class Application {

  /**
   * Construct and show the application.
   */
  public Application() {
    MainFrame frame = new MainFrame();
    // Validate frames that have preset sizes
    frame.validate();

    // Center the window
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    Dimension frameSize = frame.getSize();
    if (frameSize.height > screenSize.height) {
      frameSize.height = screenSize.height;
    }
    if (frameSize.width > screenSize.width) {
      frameSize.width = screenSize.width;
    }
    frame.setLocation( (screenSize.width - frameSize.width) / 2,
                      (screenSize.height - frameSize.height) / 2);
    frame.setVisible(true);
  }

  /**
   * Application entry point.
   *
   * @param args String[]
   */
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        new Application();
      }
    });
  }
}

Diesen Code hier hat der Lehrer noch nicht erklärt, d.h. ich verstehe so gut wie gar nix davon.

Wenn Zeile 12 ausgeführt wird, dann wird ja ein Objekt erzeugt oder? Also ein Hauptfenster in dem Fall. In dieser Zeile springt es dann zu dem Konstruktor der sich in MainFrame.java in Zeile 14 befindet und dann halt das FrameInit aufmacht?

Geht er auch irgendwann mal zur Zeile 8, oder wird das eh schon überprüft/festgelegt/durchgeführt, wenn er ins MainFrame.java kommt?

In der Methode MainFraime ist ja eine neue Methode namens FrameInit, zumindest der Aufruf, übernimmt FrameInit jetzt die gleichen Klassen/Methoden von MainFrame?

contentPane.setLayout(new BorderLayout()); vs frame.setLayout(new BorderLayout):

Und genau hier ist das Problem. Ich tu mir schwer das Problem zu erklären^^.
in dem view.java, wird das frame.setLay.... verwendet und halt in meine Programm das andere.

Hat jetzt dieses contentPane(ich mein hier den benutzten/erstellten namen/variable) die gleichen Eigenschaften, oder Methoden von JFrame, weil man veerbt hat?

Beim anderen ist es mir völlig klar. Weil frame direkt von JFrame ist.
 
Zuletzt bearbeitet:
Hi, wieder da:
Wenn Zeile 12 ausgeführt wird, dann wird ja ein Objekt erzeugt oder? Also ein Hauptfenster in dem Fall. In dieser Zeile springt es dann zu dem Konstruktor der sich in MainFrame.java in Zeile 14 befindet und dann halt das FrameInit aufmacht?
Genau.
Geht er auch irgendwann mal zur Zeile 8, oder wird das eh schon überprüft/festgelegt/durchgeführt, wenn er ins MainFrame.java kommt?
Überprüft etc. wird es beim Kompilieren.
Wirklich gestartet werden ja die fertigen class-Dateien, da ist alles schon geprüft reingestopft.
In der Methode MainFraime ist ja eine neue Methode namens FrameInit, zumindest der Aufruf, übernimmt FrameInit jetzt die gleichen Klassen/Methoden von MainFrame?
Du verwechselst hier was ganz arg.
FrameInit ist eine Methode, ja. Methode, Funktion...wie auch immer.
MainFrame ist eine Klasse.
Eine Klasse, die Methoden und Variablen beinhaltet.
Das ganze Vererbungszeug findet auf Klassenebene statt, nicht für jede einzelne Methode.

JFrame hat zB. eine Methode setSize.
Da MainFrame von JFrame erbt gibt es auch in MainFrame ein setSize.
Und da du kein eigenen setSize mit anderem Code in MainFrame hast
wird eben das Originale genommen
(und irgendwo von dir auch aufgerufen, wenn ich mich richtig erinnere).

Java:
class JFrame {
    void setSize() {
        ...
    }
   ...
}

contentPane.setLayout(new BorderLayout()); vs frame.setLayout(new BorderLayout):

Und genau hier ist das Problem. Ich tu mir schwer das Problem zu erklären^^.
in dem view.java, wird das frame.setLay.... verwendet und halt in meine Programm das andere.

Hat jetzt dieses contentPane(ich mein hier den benutzten/erstellten namen/variable) die gleichen Eigenschaften, oder Methoden von JFrame, weil man veerbt hat?

Beim anderen ist es mir völlig klar. Weil frame direkt von JFrame ist.

Aaalso...
Wiederholung von oben:
Mit Panels kann das Fenster in Bereiche eingeteilt werden.
Ein Panel kann in sich wieder durch Panels unterteilt werden.

Und der Frame ist letztendlich nichts Anderes als ein besonderes Panel.
Man kann Buttons etc reintun oder durch Panels unterteilen.
Was den JFrame vom JPanel unterscheidet: Ein Panel allein ist nicht "überlebensfähig".

JFrame ist ein Panel, das unter Anderem (über Umwege) mit dem Betriebssystem
klärt, dass das eigene Javaprogramm doch gern ein Fenster möchte,
dazu eine Titelleiste und ein X zum Schließen drin usw.

Wenn man diese "Nebensachen" wegnimmt bleibt vom Sinn her ein normales JPanel übrig.
Und damit man nicht alles Panel-artige doppelt programmiert
(warum ist da eigentlich keine Vererbung im Einsatz ;-] (edit: Es erbt tatsächlich von (einem) Frame))
hat JFrame in sich drin ein JPanel als Variable.

Wenn man jetzt was vom Panel im Frame will bekommt man es mit als contentPane.
Alternativ sind einige Sachen (wie setLayout, das eigentlich das Panel im Frame betrifft)
auch als Methoden im Frame vorhanden.

So irgendwas ca.
Java:
class JFrame {
    protected JPanel contentPane;

    public JPanel getContentPane() {
        return contentPane;
    }

    public setLayout(Layout lay) {
        contentPane.setLayout(lay);
    }
   ...
}
 
Ich geb dir auch mal ein Reallife Beispiel, welches eigentlich immer sehr beliebt ist.

wir haben die Klassen

(JFrame) (MainFrame) (Application)
Fahrzeug <- Auto <- Porsche

Zur Vererbung :
Ein Porsche ist ein Auto und ein Auto ein Fahrzeug. Das bedeutet :

Ein Porsche kann all das was ein Auto kann, besitzt aber wiederum eigene Attribute und auch eigene Methoden.

Ein Auto kann aber auch alles was ein Fahrzeug kann und besitzt aber auch eigene Attribute und eigene Methoden.

Ein Fahrzeug kann sich bewegen und beschleunigen.
Ein Auto kann dies ja selbstverständlich auch, da dieses ja ein Fahrzeug ist(es erbst alle Eigentschaften des Fahrzeugs). Da die Grundlage für das bewegen eines Fahrzeugs und eines Autos ja die selben sind, und diese nicht erweitert werden müssen, muss man diese Methode nicht explizit in die Klasse Auto übertragen.
Wenn ich jetzt ein Objekt der Klasse Porsche erstelle, muss dieses sich doch auch bewegen können, sprich es erbt alle Eigenschaften, welches das Auto auch erbt usw...
 
Danke!

Eins kommt mir aber noch nicht ganz plausibel vor. Wenn in einer Klasse z.b. 2 ActionListener-Klassen(oder 2 normale Klassen, erstmal egal) sind und wenn man im 1. Actionlistener variable verändert, dass diese dann im anderen ActionListener auch verändert ist.

Wie kann man das bitte machen? Wenn man schaut wird dann 0 ausgegeben. Und listener.variable geht auch nicht.

Java:
public class Klasse {
private int variable = 0;

private class listener implements ActionListener {
public ActionListener
{
variable++;
}

private class listener2 implements ActionListener {
System.out.println(variable);
}
//ActionEvent ist auch noch da, einfach vorstellen, hab jetzt nur das Prinzip der Frage aufgeschrieben
}
 
Zurück