Java auf Button-Eingabe warten lassen?

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet

Zuerst:

1) Schmeiße diese Zeile raus und vergiss diese Methodik auch schnell wieder, denn sie stellt derb schlechten Stil dar.

contentPanel.setLayout(null);

Verwende einen regulären Layout Manager oder falls du damit nicht zurechtkommst, gibt es noch externe Bibliotheken (MiGLayout) oder den Swing Builder (wie WindowBuilder) für Drag&Drop.

Am besten wäre es zudem auch, die Größe des Fensters automatisch mit pack ermitteln zu lassen. Gewünschte Größen kann man mit setPreferredSize anbringen.

2) Wenn ich einmal davon ausgehe, dass du für deinen Dialog entweder einen JFrame oder JDialog verwendest, ist der Standard-Layout-Manager bereits das BorderLayout. Das heißt, diese Zeile:

getContentPane().setLayout(new BorderLayout());

kann auch raus.

3) Der Zugriff auf das ContentPane lässt sich leicht über this abkürzen. Du brauchst es nicht explizit holen, das macht die JFrame/JDialog-Klasse schon für dich.

4) Mache dein Fenster erst sichtbar, sobald es auch fertig ist (also alle gewünschten Komponenten angehängt und Größen, Position, etc. festgelegt wurden). Andernfalls zwingst du Swing dazu, das Fenster mehrmals (und unnötig) nacheinander neuzeichnen zu lassen.

5) Ich verstehe nicht, wieso du so viele Code-Blöcke öffnest. Soll das deine Art an Code-Strukturierung sein? Um Quellcode in übersichtliche Blöcke aufzuteilen, gibt es in Java Methoden.

Zu deinem Problem:

Erweitere eine JDialog-Klasse, die als Modal gekennzeichnet wird. Sie hält ein Feld, welches den Rückgabewert speichert und zudem wird in ihr eine Methode definiert, die zum einen das Fenster einblendet und zum anderen den erwarteten Wert zurückgibt. Die Action Listener der Buttons in diesem Fenster sorgen für eine Berechnung des Rückgabewerts und das folgende Ausblenden des Dialogs.

Dazu ein einfaches Beispiel:

Main.java

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

public class Main {
  public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
      JFrame frame = new JFrame("Modal dialog example");
      frame.setLayout(new FlowLayout());

      final JLabel label = new JLabel();

      JButton askButton = new JButton("Open modal");
      askButton.addActionListener(evt -> {
        var dialog = new MyDialog(frame);
        label.setText(dialog.showModal());
      });

      frame.add(askButton);
      frame.add(label);
      frame.pack();
      frame.setVisible(true);
    });
  }
}

MyDialog.java

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

public class MyDialog extends JDialog {
  private String result;

  public MyDialog(Window parent) {
    super(parent, ModalityType.APPLICATION_MODAL);
    setLayout(new FlowLayout());

    JButton okButton = new JButton("OK");
    okButton.addActionListener(evt -> {
      result = "Approved.";
      dispose();
    });
    add(okButton);

    JButton cancelButton = new JButton("Cancel");
    cancelButton.addActionListener(evt -> {
      result = "Cancelled.";
      dispose();
    });
    add(cancelButton);

    pack();
  }

  public String showModal() {
    setVisible(true);
    return result;
  }
}

An sich könnte man diese Klasse noch weiter abstrahieren, indem man den Rückgabetyp generisch definiert und die Berechnung ebenso in eine eigene Klasse auslagert (siehe Strategy Pattern).

Weitere Informationen zu Dialogen und Modals findest übrigens du in der Oracle Dokumentation:


Usernase 
Fragesteller
 01.09.2020, 12:08

Zu 1) - 3) ich erstelle die GUI über den Eclipse Editor und der hat das wohl an den Stellen so gemacht.

0