GUI mit Lambda-Ausdrücken
Sehr praktisch sind Lambda-Ausdrücke u.a. bei der GUI-Programmierung. Eine Beispielprogression, wie man von einem JFrame
, das ActionListener
implementiert, über (anonyme) innere Klassen zu Lambda-Ausdrücken kommt, findest Du hier.
Wir gehen von einem JFrame aus, das zwei Buttons enthält, und das Interface ActionListener
implementiert.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MeineGuiMitActionListener extends JFrame implements ActionListener{ JButton klickMichButton; JButton exitButton; public MeineGuiMitActionListener() { klickMichButton = new JButton("Klick mich"); klickMichButton.addActionListener(this); add(klickMichButton); exitButton = new JButton("Beenden"); exitButton.addActionListener(this); add(exitButton); setLayout(new FlowLayout()); pack(); setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); } public void actionPerformed(ActionEvent e) { if(e.getSource() == klickMichButton) klickAktionAusfuehren(); if(e.getSource() == exitButton) beenden(); } private void klickAktionAusfuehren() { JOptionPane.showMessageDialog(this, "Yippie, der Button wurde geklickt"); } private void beenden() { System.exit(0); } }
Um den Code zu vereinfachen, gehen wir zuerst den Umweg über weitere Klassen. Wir definieren dazu innere Klassen, die nur dazu da sind, um die Ereignisbehandlung für genau ein Ereignis zu behandeln.
// import-Anweisungen ausgelassen public class MeineGuiInnereKlassen extends JFrame{ // implementiert nicht mehr ActionListener JButton klickMichButton; JButton exitButton; class KlickMichButtonHandler implements ActionListener { public void actionPerformed(ActionEvent e) { klickAktionAusfuehren(); } } class ExitButtonHandler implements ActionListener { public void actionPerformed(ActionEvent e) { beenden(); } } public MeineGuiInnereKlassen() { klickMichButton = new JButton("Klick mich"); klickMichButton.addActionListener(new KlickMichButtonHandler()); add(klickMichButton); exitButton = new JButton("Beenden"); exitButton.addActionListener(new ExitButtonHandler()); add(exitButton); // restliche Initialisierung ausgelassen } private void klickAktionAusfuehren() { JOptionPane.showMessageDialog(this, "Yippie, der Button wurde geklickt"); } private void beenden() { System.exit(0); } }
Da man die Objekte zur Ereignisbehandlung genau einmal erzeugt, macht es Sinn anonyme innere Klassen zu benutzen:
public class MeineGuiAnonym extends JFrame{ JButton klickMichButton; JButton exitButton; public MeineGuiAnonym() { klickMichButton = new JButton("Klick mich"); klickMichButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { klickAktionAusfuehren(); } } ); add(klickMichButton); exitButton = new JButton("Beenden"); exitButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { beenden(); } } ); add(exitButton); // weitere Initialisierungen } private void klickAktionAusfuehren() { JOptionPane.showMessageDialog(this, "Yippie, der Button wurde geklickt"); } private void beenden() { System.exit(0); } }
Das Interface ActionListener ist ein "functional Interface", d.h. es besitzt nur eine einzige Methode, definiert also quasi eine Funktion. In solch einem Fall kann man statt der anonymen inneren Klasse einen Lambda-Ausdruck verwenden. Diesen kann man in unserem Fall zusätzlich verkürzen:
public class MeineGuiLambda extends JFrame{ JButton klickMichButton; JButton exitButton; public MeineGuiLambda() { klickMichButton = new JButton("Klick mich"); klickMichButton.addActionListener((ActionEvent e) -> { klickAktionAusfuehren(); }); add(klickMichButton); // maximal reduziert: exitButton = new JButton("Beenden"); exitButton.addActionListener(e -> beenden()); add(exitButton); // weitere Initialisierungen } private void klickAktionAusfuehren() { JOptionPane.showMessageDialog(this, "Yippie, der Button wurde geklickt"); } private void beenden() { System.exit(0); } }