SpringLayout mit zusätzlichen Buttons außerhalb des SpringLayout

volcanos

Bekanntes Mitglied
Wie kann man am Besten die 3 Buttons (saveButton - refreshButton - exitButton)
unterhalb des SpringLayout sichtbar machen (neben einander in einer Reihe) ?

Meine Lösung funktioniert anscheinend nicht so, wie ich sie mir vorgestellt habe !

Java:
package com.mycompany.springlayoutdemo;

import java.awt.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import javax.swing.*;


public class SpringLayoutDemo
{
    private static Container createForm(Component[] leftComponents,
                                        Component[] rightComponents,
                                        int initialX, int initialY,
                                        int xPad, int yPad)
    {
        SpringLayout layout = new SpringLayout();
        int numRows = Math.max(leftComponents.length, rightComponents.length);
        
        // Die konstanten Sprünge, die verwendet werden, um den Abstand zu erzwingen:
        Spring xSpring = Spring.constant(initialX);
        Spring ySpring = Spring.constant(initialY);
        Spring xPadSpring = Spring.constant(xPad);
        Spring yPadSpring = Spring.constant(yPad);
        Spring negXPadSpring = Spring.constant(-xPad);

        // Container und Components erzeugen:
        JPanel parent = new JPanel(layout);
        for (int i = 0; i < numRows; i++)
        {
            parent.add(leftComponents[i]);
            parent.add(rightComponents[i]);
        }

        Spring maxEastSpring = layout.getConstraint("East", leftComponents[0]);
        for (int row = 1; row < numRows; row++)
        {
            maxEastSpring = Spring.max(maxEastSpring, layout.getConstraint("East", leftComponents[row]));
        }

        // Layout für jedes Paar:
        SpringLayout.Constraints lastConsL = null;
        SpringLayout.Constraints lastConsR = null;
        Spring parentWidth = layout.getConstraint("East", parent);
        Spring rWidth = null;
        Spring maxHeightSpring = null;
        Spring rX = Spring.sum(maxEastSpring, xPadSpring);
        Spring negRX = Spring.minus(rX);

        for (int row = 0; row < numRows; row++)
        {
            SpringLayout.Constraints consL = layout.getConstraints(leftComponents[row]);
            SpringLayout.Constraints consR = layout.getConstraints(rightComponents[row]);

            consL.setX(xSpring);
            consR.setX(rX);
            rWidth = consR.getWidth();                                       
            consR.setWidth(Spring.sum(Spring.sum(parentWidth, negRX), negXPadSpring));
            
            if (row == 0)
            {
                consL.setY(ySpring);
                consR.setY(ySpring);
                maxHeightSpring = Spring.sum(ySpring, Spring.max(consL.getHeight(), consR.getHeight()));
            }
            // row > 0:
            else
            {
                Spring y = Spring.sum(Spring.max(lastConsL.getConstraint("South"), lastConsR.getConstraint("South")), yPadSpring);
                consL.setY(y);
                consR.setY(y);
                maxHeightSpring = Spring.sum(yPadSpring, Spring.sum(maxHeightSpring, Spring.max(consL.getHeight(), consR.getHeight())));
            }
            lastConsL = consL;
            lastConsR = consR;
        } 

        // Verbinden des Osten und Sueden des Containers, sodass dieser bevorzugt wird:
        SpringLayout.Constraints consParent = layout.getConstraints(parent);
        consParent.setConstraint("East", Spring.sum(rX, Spring.sum(rWidth, xPadSpring)));
        consParent.setConstraint("South", Spring.sum(maxHeightSpring, yPadSpring));
        
        return parent;
    }
    
    
    // Main:
     public static void main(String[] args)
    {
        int numPairs = 5;
        JLabel[] labels = new JLabel[numPairs];
        JTextField[] textFields = new JTextField[numPairs];
        
        // Label erstellen (1. Spalte):
        labels[0] = new JLabel("                    Name");
        // labels[0].setFont(labels[0].getFont().deriveFont(Font.PLAIN, 16f));
        labels[1] = new JLabel("PLZ und Ort");
        labels[2] = new JLabel("Geburts-Datum");
        labels[3] = new JLabel("Email-Adtresse");
        labels[4] = new JLabel("Telefon-Nummer");
      
        // Text-Feld erstellen (2. Spalte):
        for (int i = 0; i < numPairs; i++)
        { textFields[i] = new JTextField(10); }

        // Jedes Label mit seinem Textfeld verknüpfen:
        for (int i = 0; i < numPairs; i++)
        { labels[i].setLabelFor(textFields[i]); }               

        // Aufrufen der createForm-Methode:
        Container container = createForm(labels, textFields, 5, 5, 5, 5);       
        
        JButton saveButton = new JButton("Save");               
        saveButton.addActionListener(AE ->
        {
            Path directory = Path.of("E:/NetBeansProjects/SpringLayoutDemo/Daten.txt");
            try
            {
                Files.writeString(directory, "\n", StandardOpenOption.APPEND);
                
                for(int x = 0; x < numPairs; x++)
                { Files.writeString(directory, textFields[x].getText() + "\n", StandardOpenOption.APPEND); }               
                
                Files.writeString(directory, "\n", StandardOpenOption.APPEND);                 
            } catch (IOException e) { System.out.println("File not found or no permissions !!!"); }
        });       
        
        JButton refreshButton = new JButton("Refresh");
        refreshButton.addActionListener(AE ->
        {
            for(int x = 0; x < numPairs; x++)
            { textFields[x].setText(""); }   
        });
        
        JButton exitButton = new JButton();
        exitButton.addActionListener(AE ->
        {
           System.exit(0);
        });
        
        // Das Frame erzeugen, sichtbar machen und in die Mitte des Desktops setzen:
        JFrame frame = new JFrame("Daten-Eingabe");       
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         
        frame.setContentPane(container);   
        frame.add(saveButton);
        frame.add(refreshButton);
        // frame.add(exitButton);
        frame.setSize(400, 300);       
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }
}
 

MarvinsDepression

Bekanntes Mitglied
Zudem solltest du in deiner main() - Methode die Zeilen 142 bis 151 nicht so stehen lassen, da AWT und Swing Komponenten grundsätzlich niche ausserhalb des "event dispatch thread" manipuliert werden sollten.
Packe die Zeilen in
Java:
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
       ...
       ...
      }
    });
 

volcanos

Bekanntes Mitglied
Ja , hast recht , das ist echt genial ... die Main-Methode funktioniert auch mit SwingUtilities.invokeLater(new Runnable() 👍
...
Nur muss ich dir ehrlich sagen ... was ein "event dispatch thread" ist -> KEINE AHNUNG -> noch nie gehört 🥽

Java:
    // Main:
    public static void main(String... args)
    {
        int numPairs = 5;
        JLabel[] labels = new JLabel[numPairs];
        JTextField[] textFields = new JTextField[numPairs];
        
        // Label erstellen (1. Spalte):
        labels[0] = new JLabel("                    Name");
        // labels[0].setFont(labels[0].getFont().deriveFont(Font.PLAIN, 16f));
        labels[1] = new JLabel("PLZ und Ort");
        labels[2] = new JLabel("Geburts-Datum");
        labels[3] = new JLabel("Email-Adtresse");
        labels[4] = new JLabel("Telefon-Nummer");
      
        // Text-Feld erstellen (2. Spalte):
        for (int i = 0; i < numPairs; i++)
        { textFields[i] = new JTextField(10); }

        // Jedes Label mit seinem Textfeld verknüpfen:
        for (int i = 0; i < numPairs; i++)
        { labels[i].setLabelFor(textFields[i]); }               

        // Aufrufen der createForm-Methode:
        Container container = createForm(labels, textFields, 5, 5, 5, 5);       
        
        JButton saveButton = new JButton("Save");               
        saveButton.addActionListener(AE ->
        {
            Path directory = Path.of("E:/NetBeansProjects/SpringLayoutDemo/Daten.txt");
            try
            {
                Files.writeString(directory, "\n", StandardOpenOption.APPEND);
                
                for(int x = 0; x < numPairs; x++)
                { Files.writeString(directory, textFields[x].getText() + "\n", StandardOpenOption.APPEND); }               
                
                Files.writeString(directory, "\n", StandardOpenOption.APPEND);                 
            }
            catch (IOException e)
            { System.out.println("File not found or no permission to this file !!!"); }
        });       
        
        JButton refreshButton = new JButton("Refresh");
        refreshButton.addActionListener(AE ->
        {
            for(int x = 0; x < numPairs; x++)
            { textFields[x].setText(""); }   
        });
        
        JButton exitButton = new JButton();
        exitButton.addActionListener(AE ->
        { System.exit(0); });       
        
        // Das Frame erzeugen, sichtbar machen und in die Mitte des Desktops setzen:
         SwingUtilities.invokeLater(new Runnable()
         {
            public void run()
            {
                JFrame frame = new JFrame("Daten-Eingabe");       
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         
                frame.setContentPane(container);   
                frame.add(saveButton);
                frame.add(refreshButton);
                // frame.add(exitButton);
                frame.setSize(400, 300);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);       
            }
         });       
    }
 

volcanos

Bekanntes Mitglied
Was hältst du übrigens von dieser Zeile ?
Wie könnte man die Zeile in den Text bzw. Kontext bringen ?

Code:
public static void main(String... args)
  { SwingUtilities.invokeLater(SpringLayoutDemo::new); }

In Java können wir den doppelten Doppelpunktoperator :):) verwenden, um eine Methode aufzurufen,
indem wir mit Hilfe ihres Klassennamens auf sie verweisen.

Wir können dies auch tun, indem wir die Lambda-Ausdrücke verwenden. Der einzige Unterschied,
den wir hier finden, besteht darin, dass wir die Methode direkt über den Namen referenzieren können,
während wir den Operator :: verwenden.

Das ist die Theorie ... funktioniert leider nicht immer !
 

mihe7

Top Contributor
Nur muss ich dir ehrlich sagen ... was ein "event dispatch thread" ist -> KEINE AHNUNG -> noch nie gehört 🥽
Das ist essentiell zu wissen, wenn man mit UIs arbeitet.

UIs sind ereignisorientiert. Wenn Du die Maus bewegst, ist das ein Ereignis, genauso wenn Du Dein Fenster minimierst oder schließt. Ebenso ein Ereignis ist das Neuzeichnen des Fensterinhalts.

Beispiel: der Fenstermanager stellt fest, dass ein Fenster, das vor Deiner Anwendung lag, verschoben wurde. Also muss der Inhalt Deines Fensters neu gezeichnet werden, dementsprechend wird ein Ereignis ausgelöst.

In Java gibt es nun zwei wesentliche Bauteile:
  1. Alle ankommenden Ereignisse (auch solche, die intern vom Programm aus gesendet werden) landen in einer Warteschlage, der sog. Event Queue.
  2. Es gibt einen Thread, der die Ereignisse aus der Queue nimmt und verarbeitet, insbesondere an die betreffenden Swing-Komponenten "verteilt", d. h. entsprechende Methoden aufruft -> der sog. Event Dispatch Thread (EDT)
Es ist wichtig zu verstehen, dass praktisch alles, was mit UI zu tun hat, im EDT läuft: paintComponent(), actionPerformed() etc. -> alles wird im EDT ausgeführt.

Warum ist das wichtig?

Ganz einfach: so lange die Methoden ausgeführt werden, kann das nächste Ereignis aus der Queue nicht verarbeitet werden; der EDT ist in der Zeit blockiert. Lädst Du z. B. in einer actionPerformed()-Methode eine große Datei, blockiert der EDT, bis dieser Vorgang abgeschlossen ist. Das UI friert in der Zeit ein, für den Anwender sieht es so aus, als wäre das Programm abgestürzt.

Deswegen lagert man lang laufende Dinge in einen separaten Thread aus. Damit hast Du ein neues Problem: Du kannst von einem anderen Thread aus nicht einfach das UI ändern (die Methoden sind in der Regel nicht thread-safe). Man muss also dafür sorgen, dass die UI-Änderungen im EDT ablaufen.

Wie funktioniert das? Man legt ein Runnable in die Event Queue - in der Regel per invokeLater(). Eine andere Möglichkeit (die intern natürlich nichts anderes macht), ist es, den SwingWorker zu verwenden.
 

volcanos

Bekanntes Mitglied
Nun habe ich die Main-Methode umgeändert und das Borderlayout hinzugefügt.

Java:
// Main:
    public static void main(String... args)
    {
        // Buttons und Labels initialisieren:
        ImageIcon addressBook = new ImageIcon("E:/NetBeansProjects/SpringLayoutDemo/AB.png");
        JPanel blPanel = new JPanel();
        JButton refreshButton = new JButton("Refresh");
        refreshButton.setForeground(Color.orange);
        JButton saveButton = new JButton("Save");
        saveButton.setForeground(Color.blue);
        JButton exitButton = new JButton("Exit");
        exitButton.setForeground(Color.magenta);
        JLabel picture = new JLabel(addressBook);
       
        // Borderlayout-Manager:
        blPanel.setLayout(new BorderLayout());
        blPanel.add(picture, BorderLayout.PAGE_START);
        blPanel.add(refreshButton, BorderLayout.LINE_START);
        blPanel.add(saveButton, BorderLayout.LINE_END);      
        blPanel.add(exitButton, BorderLayout.PAGE_END);      
       
        // Springlayout initialisieren:
        int numPairs = 5;
        JLabel[] labels = new JLabel[numPairs];
        JTextField[] textFields = new JTextField[numPairs];
       
        // Label erstellen (1. Spalte):
        labels[0] = new JLabel("Name");
        // labels[0].setFont(labels[0].getFont().deriveFont(Font.PLAIN, 16f));
        labels[1] = new JLabel("PLZ und Ort");
        labels[2] = new JLabel("Geburts-Datum");
        labels[3] = new JLabel("Email-Adtresse");
        labels[4] = new JLabel("Telefon-Nummer");
     
        // Text-Feld erstellen (2. Spalte):
        for (int i = 0; i < numPairs; i++)
        { textFields[i] = new JTextField(10); }

        // Jedes Label mit seinem Textfeld verknüpfen:
        for (int i = 0; i < numPairs; i++)
        { labels[i].setLabelFor(textFields[i]); }              

        // Aufrufen der createForm-Methode im SpringLayout:
        Container container = createForm(labels, textFields, 5, 5, 5, 5);
       
        // Das SpringLayout (container) zum BorderLayout.CENTER hinzufügen:
        blPanel.add(container, BorderLayout.CENTER);        
       
        // Die ActionListener:
        saveButton.addActionListener(AE ->
        {
            Path directory = Path.of("E:/NetBeansProjects/SpringLayoutDemo/Daten.txt");
            try
            {
                Files.writeString(directory, "\n", StandardOpenOption.APPEND);
               
                for(int x = 0; x < numPairs; x++)
                { Files.writeString(directory, textFields[x].getText() + "\n", StandardOpenOption.APPEND); }              
               
                Files.writeString(directory, "\n", StandardOpenOption.APPEND);                
            }
            catch (IOException e)
            { System.out.println("File not found or no permission to this file !!!"); }
        });        
       
        refreshButton.addActionListener(AE ->
        {
            for(int x = 0; x < numPairs; x++)
            { textFields[x].setText(""); }  
        });      
       
        exitButton.addActionListener(AE ->
        { System.exit(0); });      
               
        
        SwingUtilities.invokeLater(() ->
        {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //frame.setContentPane(container);
            frame.add(blPanel);
            frame.setSize(500, 320);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });       
    }

Grundsätzlich funktioniert es :cool:
 
Zuletzt bearbeitet:

MarvinsDepression

Bekanntes Mitglied
... aber eigentlich wolltest Du die Buttons alle UNTER dem Container haben, oder ?

Java:
    JPanel buttonPanel = new JPanel();
    buttonPanel.add(saveButton);
    buttonPanel.add(refreshButton);
    buttonPanel.add(exitButton);
        
SwingUtilities.invokeLater(() -> {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    frame.setLayout(new BorderLayout());
    frame.add(container, BorderLayout.CENTER);
    frame.add(buttonPanel, BorderLayout.SOUTH);

    frame.setSize(500, 320);
    frame.setLocationRelativeTo(null);
    // frame.pack();
    frame.setVisible(true);
});

sieht hübscher aus, finde ich :)

P.S.: probiere doch mal das frame.pack() aus, dann kommt der Parameter 10 in
Java:
        // Text-Feld erstellen (2. Spalte):
        for (int i = 0; i < numPairs; i++)
        { textFields[i] = new JTextField(10); }
auch zur Geltung.
 

MarvinsDepression

Bekanntes Mitglied
  1. Alle ankommenden Ereignisse (auch solche, die intern vom Programm aus gesendet werden) landen in einer Warteschlage, der sog. Event Queue.
  2. Es gibt einen Thread, der die Ereignisse aus der Queue nimmt und verarbeitet, insbesondere an die betreffenden Swing-Komponenten "verteilt", d. h. entsprechende Methoden aufruft -> der sog. Event Dispatch Thread (EDT)
Bisher habe ich angenommen, das der EDT erst mir new JFrame() gestartet wird. Bereits zuvor erzeugte UI-Elemente (Panels, Buttons, ...) starten keinen EDT. Liege ich da überhaupt richtig und fall 'ja', was startet ggf. noch alles einen EDT?
 

volcanos

Bekanntes Mitglied
"aber eigentlich wolltest Du die Buttons alle UNTER dem Container haben, oder ?"

Ja, zuerst schon, jetzt ist es mir egal, wo sie sind. Hauptsache es funktioniert und es sieht halbwegs gut aus ... für mich.

Aber dein obiges Beispiel (Buttons alle UNTER dem Container ) gefällt mir auch sehr 😃
 
Zuletzt bearbeitet:

MarvinsDepression

Bekanntes Mitglied
Die 10 in JTextfield(10) kann in deiner UI entsprechend Platz für 10 Zeichen beanspruchen. Je nach Font ist das sehr relativ. Es wird vom breitest möglichen ausgegangen (b. B. das W).
Allerdings ist das nicht bindend und z. B. Dein serSize(...) ist stärker.
Das Packen mit frame. pach() kann soetwas wieder zurecht rücken.
 

volcanos

Bekanntes Mitglied
Ich denke, so sieht es richtig gut aus :

// Panel, Buttons und Labels initialisieren:
ImageIcon addressBook = new ImageIcon("E:/NetBeansProjects/SpringLayoutDemo/AdressBuch.png");
JPanel blPanel = new JPanel();
JButton refreshButton = new JButton("Refresh");
refreshButton.setBackground(new Color(107, 106, 104));
refreshButton.setForeground(Color.magenta);
JButton saveButton = new JButton("Save");
saveButton.setBackground(new Color(107, 106, 104));
saveButton.setForeground(Color.magenta);
JButton exitButton = new JButton("Exit");
exitButton.setBackground(new Color(107, 106, 104));
exitButton.setForeground(Color.magenta);
JLabel picture = new JLabel(addressBook);

// Borderlayout-Manager:
blPanel.setLayout(new BorderLayout());
blPanel.add(picture, BorderLayout.PAGE_START);
blPanel.add(refreshButton, BorderLayout.LINE_START);
blPanel.add(saveButton, BorderLayout.LINE_END);
blPanel.add(exitButton, BorderLayout.PAGE_END);
 

volcanos

Bekanntes Mitglied
ok - jetzt habe ich das mit der 10 verstanden.


"auch zur Geltung" habe ich zuerst überlesen...
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Bisher habe ich angenommen, das der EDT erst mir new JFrame() gestartet wird.
Nein, dann würde SwingUtilities.invokeLater() nicht funktionieren :)

Hier ist z. B. meine Swing-Vorlage fürs Forum:
Java:
import javax.swing.*;

public class Test {

    public void run() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Test().run());
    }
}

In main wird also dafür gesorgt, dass der EDT gestartet und das Runnable in die EventQueue gelegt wird.

Bereits zuvor erzeugte UI-Elemente (Panels, Buttons, ...) starten keinen EDT. Liege ich da überhaupt richtig und fall 'ja', was startet ggf. noch alles einen EDT?
Normalerweise sollte es so sein, dass allein die Erzeugung einer Komponente den EDT nicht startet (also auch new JFrame() nicht) aber meine Hand würde ich dafür nicht ins Feuer legen. Daher würde ich empfehlen, auch das Erzeugen der Komponenten im EDT durchzuführen.
 

volcanos

Bekanntes Mitglied
Zur Zeit - das einzige was noch nicht 100%ig funktioniert - ist die Validation der Eingabe, ob überhaupt was eingegeben wurde.
Er validiert erst ab dem zweiten leeren Feld... bei:

Java:
if(textFields[x].getText().isEmpty())

Die anderen Felder sind leer, nur im ersten Feld steht was drinnen: Hier schreibt das Programm in das File Adressbook.txt das erste Feld (den Namen) hinein ! Das soll aber nicht sein !

Wenn das erste Feld leer ist, und steht nur ab dem zweiten Feld was drinnen, dann wird nicht geschrieben, was Richtig ist.

Man kann es zwar unschön lösen mit:

Code:
if (textFields[0].getText().isEmpty() || textFields[1].getText().isEmpty() || textFields[2].getText().isEmpty() || textFields[3].getText().isEmpty() || textFields[4].getText().isEmpty())

Das funktioniert sogar 100%ig, aber es schaut irgendwie aus !

Da müsste es doch eine bessere Lösung geben.

Hier der ganze Action-Listenener:


Code:
// Der ActionListener:
        saveButton.addActionListener((var AE) ->
        {
            Path directory = Path.of("E:/NetBeansProjects/AdressBook/res/AdressBook.txt");
            ok = true;
         
            try
            {                    
                for(int x = 0; x < numPairs; x++)
                {                  
                    if(textFields[x].getText().isEmpty())
                    // if (textFields[0].getText().isEmpty() || textFields[1].getText().isEmpty() || textFields[2].getText().isEmpty() || textFields[3].getText().isEmpty() || textFields[4].getText().isEmpty())
                    {
                        JOptionPane.showMessageDialog(null, "All fields must be fill out !!!!");
                        ok = false;
                        break;
                    }
                    else
                    if(ok == true) { Files.writeString(directory, textFields[x].getText() + "\n", StandardOpenOption.APPEND); }                                  
                }            
                             
                if(ok == true) { Files.writeString(directory, "\n\n", StandardOpenOption.APPEND); }
            }
            catch (FileNotFoundException err1) { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }
            catch (IOException err2)  { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }
        });
 

KonradN

Super-Moderator
Mitarbeiter
Der Ansatz ist falsch. Wenn du etwas in einer Schleife prüfst, dann kannst du davon ausgehen, dass ein if / else falsch ist.

Der Ansatz ist ja immer etwas in der Art:
Du suchst etwas:
Da du noch nicht gesucht hast, hast du noch nichts gefunden, gefunden ist also falsch. (Oder besser: der Status ist „bisher nicht gefunden“)
Nun gehst du die Elemente durch: wenn das Element das gesuchte ist, dann kannst du reagieren und sagen: Ich habe es gefunden (und an der Stelle kannst du ggf abbrechen).
Aber wenn das aktuelle Element nicht das gesuchte ist: da kannst du nichts machen. An dem Status „bisher nicht gefunden“ hat sich ja nichts geändert.

Erst, wenn du alle Elemente durchsucht hast und nichts gefunden hast, dann kannst du sagen: das gesuchte Element ist nicht vorhanden.

Das erst einmal als kleine Generelle Information. Bei Dir kommt aber noch etwas hinzu: du hast mehrere Dinge zusammen gemischt (so ich auf dem Handy dein Code richtig verstanden habe):
a) du validierst die Eingabe
b) wenn alles valide ist, schreibst du die Daten
Mach daraus zwei Methoden! Dann ist es deutlich einfacher und die Chance auf Fehler ist geringer. (KISS: keep it simple & stupid und das per divide and conquer: Teile und Herrsche: Teile ein Problem in kleinere Teilprobleme auf und löse so das ganz Problem.
 

mihe7

Top Contributor
Der ActionListener könnte einfach so aussehen:
Java:
if (validateInputs()) {
    save();
}

Die Methode validateInputs prüft dann eben nur die Eingaben und liefert true, genau dann wenn alle Eingaben in Ordnung sind.
Java:
private boolean validateInputs() {
    for (JTextField textField : textFields) { // Für jedes JTextField textField aus textFields wiederhole ...
        if (textField.getText().isEmpty()) {
            JOptionPane.showMessageDialog(null, "Please fill out all fields.");
            return false;  // sobald ein leeres Textfeld gefunden wurde, ist die Validierung auch schon fehlgeschlagen.
    }
    return true; // alle Felder durch -> Validierung ok.
}

Gut, und save() speichert dann einfach die Datei.
 

volcanos

Bekanntes Mitglied
Der Ansatz ist sehr gut. Nur mit if funktioniert es bei den Feldern anscheinend nicht ! Es kommt nur 1 x die JOptionPane-Fehler-Meldung. Beim 2. 3. oder 4. Feld nicht mehr. Deshalb while... weil hier ist die Funktionalität gegeben. Es kommt immer (bei jedem leeren Feld) die JOptionPane-Meldung. Das ist gut so. Sogar, wenn alle Felder ausgefüllt sind, kommt die Fehler-JOptionPane-Fehler-Meldung NICHT ! Das ist auch gut so.

Nur in das File schreiben... das macht das Programm jetzt nicht mehr. So nach dem Motto: Operation gelungen, Patient tot.


Java:
// Außerhalber der main-Methode
// Validation, ob die Eingabefelder nicht leer sind:
    private static boolean validateInputs()
    {
        for(JTextField textField : textFields)
        {
            if (textField.getText().isEmpty())
            { JOptionPane.showMessageDialog(null, "Please fill out all fields !"); }
            return false;  // sobald ein leeres Textfeld gefunden wurde, ist die Validierung auch schon fehlgeschlagen !
        }
        return true; // alle Felder durch -> Validierung OK !
    }

    // Main-Methode:
    public static void main, usw.
    {
        // Der ActionListener:
        saveButton.addActionListener((var AE) ->
        {
            Path directory = Path.of("E:/NetBeansProjects/AdressBook/res/AdressBook.txt");
                     
            try
            {                      
                while(validateInputs())
                {
                    for(int x = 0; x < numPairs; x++)
                    { Files.writeString(directory, textFields[x].getText() + "\n", StandardOpenOption.APPEND);  }            
                   
                    Files.writeString(directory, "\n\n", StandardOpenOption.APPEND);
                }
            }          
            catch (FileNotFoundException err1) { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }
            catch (IOException err2)  { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }          
        });
    }
 

MarvinsDepression

Bekanntes Mitglied
Java:
Code:
if (validateInputs()) {
    save();
}
analog könnte save() sich von einer weiteren Metode einen fertig formatierten String packen lassen und ihn ein einem Schritt ins File Schreiben.
dann könnte save() etwa so aussehen
Java:
private void save() {
    Path directory = Path.of("E:/NetBeansProjects/AdressBook/res/AdressBook.txt");
    try {
        Files.writeString(directory, getContentFromTextFields() + "\n", StandardOpenOption.APPEND);
    }
    catch (FileNotFoundException err1) { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }
    catch (IOException err2)  { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }
}
und
Java:
private String getContentFromTextFields() {
    StringBuilder content = new StringBuilder();
    for (JTextField textField : textFields) {
        content.append(textField.getText());
        content.append("\n");
    }
    content.append("\n\n");
    
    return content.toString();
}
 

volcanos

Bekanntes Mitglied
Auch in diesem Fall ->Es wird nicht mehr ins file geschrieben...


Java:
 // Validation, ob die Eingabefelder nicht leer sind:
    private static boolean validateInputs()
    {
        for(JTextField textField : textFields)
        {
            if (textField.getText().isEmpty())
            { JOptionPane.showMessageDialog(null, "Please fill out all fields !"); }
            return false;  // sobald ein leeres Textfeld gefunden wurde, ist die Validierung auch schon fehlgeschlagen !
        }
        return true; // alle Felder durch -> Validierung OK !
    }
 
    // Ins File schreiben:
    private static void save()
    {
        Path directory = Path.of("E:/NetBeansProjects/AdressBook/res/AdressBook.txt");
     
        try
        { Files.writeString(directory, getContentFromTextFields() + "\n", StandardOpenOption.APPEND); }
        catch (FileNotFoundException err1) { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }
        catch (IOException err2)  { JOptionPane.showMessageDialog(null, "File not found or no permission to this file !!!"); }
    }
 
 
    // Get Content From Text:
    private static String getContentFromTextFields()
    {    
        StringBuilder content = new StringBuilder();
        for (JTextField textField : textFields)
        { content.append(textField.getText()); content.append("\n"); }
        content.append("\n\n");
 
        return content.toString();
    }

Code:
// Der ActionListener:
saveButton.addActionListener(AE ->
 { if(validateInputs())   save(); });
 

volcanos

Bekanntes Mitglied
Hier schreibt er wieder ins File !


Java:
// Der ActionListener:
saveButton.addActionListener(AE -> { save(); });

Nur da bin ich wieder am Anfang. Er schreibt auch leere Zeilen hinein.
 

volcanos

Bekanntes Mitglied
// Beim ActionListener ohne Validierung:
saveButton.addActionListener(AE -> { save(); });


Leere Zeilen, wenn dass Textfeld leer ist.
Volle Zeilen , wenn das Textfeld voll ist:

Genaus so:
 

Anhänge

  • TB.png
    TB.png
    22,1 KB · Aufrufe: 0

volcanos

Bekanntes Mitglied
// Beim ActionListener mit Validierung: dosn't write in file !
saveButton.addActionListener(AE -> { if(validateInputs()) save(); });

Hier -> gar nix , egal ob was in den Feldern steht oder nicht ! Schreibt auch keine Leerzeilen ins File.
Im gvim kann man die Leerzeilen sehr gut sehen !
 
Zuletzt bearbeitet:

MarvinsDepression

Bekanntes Mitglied
Java:
for(JTextField textField : textFields)
        {
            if (textField.getText().isEmpty())
            { JOptionPane.showMessageDialog(null, "Please fill out all fields !"); } //<== diese Klammer kommt zu früh!!
            return false; // <= hier Codeblock schließen
        }
optimiere Deinen Schreibstiel (Formatierung), dann fällt dir soetwas schneller auf 😁
 

volcanos

Bekanntes Mitglied
Hast recht, war mein Fehler !
Original von mihe7 war es noch richtig:

Java:
private boolean validateInputs() {

    for (JTextField textField : textFields) { // Für jedes JTextField textField aus textFields wiederhole ...

        if (textField.getText().isEmpty()) {

            JOptionPane.showMessageDialog(null, "Please fill out all fields.");

            return false;  // sobald ein leeres Textfeld gefunden wurde, ist die Validierung auch schon fehlgeschlagen.

    }

    return true; // alle Felder durch -> Validierung ok.

}
 

MarvinsDepression

Bekanntes Mitglied
Java:
private boolean validateInputs() {
    
    for (JTextField textField : textFields) {

        if (textField.getText().isEmpty()) {

            JOptionPane.showMessageDialog(null, "Please fill out all fields.");

            return false;
        } // <- schlißt 'if'-Block!! oben fehlt diese
    } // <- schließt 'for'-Block !!

    return true; // alle Felder durch -> Validierung ok.

}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Java 1.6 SpringLayout AWT, Swing, JavaFX & SWT 4
F Frage zu SpringLayout AWT, Swing, JavaFX & SWT 9
D Komponenten mit zusätzlichen Icons AWT, Swing, JavaFX & SWT 2
M Zusätzlichen Maus-Klick erzeugen AWT, Swing, JavaFX & SWT 4
XWing Basic JPanel mit 2 Buttons beutzen. AWT, Swing, JavaFX & SWT 10
jojoge Wie erstelle ich runde Buttons mit Farbe? AWT, Swing, JavaFX & SWT 1
berserkerdq2 Buttons und Shapes sehen ja nach Screengröße klein oder zu groß aus, jemand eine Idee, was man tun kann? AWT, Swing, JavaFX & SWT 1
H Swing Buttons erst nach Klick sichtbar AWT, Swing, JavaFX & SWT 13
K Swing Buttons erst blinken lassen und dann abfragen, ob sie gedrückt worden sind AWT, Swing, JavaFX & SWT 2
Z Switch Case für Buttons AWT, Swing, JavaFX & SWT 8
O Swing JOptionPane.showOptionDialog - Wie kann ich Buttons größer machen AWT, Swing, JavaFX & SWT 10
R mehrere buttons mit forschleife kreieren und individuell bearbeiten AWT, Swing, JavaFX & SWT 1
Z Swing Kann man denn abstand zwischen zwei Buttons berechnen AWT, Swing, JavaFX & SWT 5
B JavaFX DropDown Menu mit ausführbaren Buttons AWT, Swing, JavaFX & SWT 1
VPChief Buttons Reagieren erst wenn ich Fenster minimiere AWT, Swing, JavaFX & SWT 4
ms_cikar Jbutton erzeugt neue Buttons AWT, Swing, JavaFX & SWT 2
K Buttons dynamisch erstellen (NetBeans) AWT, Swing, JavaFX & SWT 10
S Kreis vergrößern/verkleinern mit Buttons AWT, Swing, JavaFX & SWT 1
J JavaFX von einem Array aus Buttons herausfinden auf welcher geklickt wurde aus dem Array. AWT, Swing, JavaFX & SWT 1
xYurisha ActionListener Methoden Buttons zuweisen! AWT, Swing, JavaFX & SWT 16
xYurisha Aus einer Gui Buttons, Label und ProgessBars entfernen AWT, Swing, JavaFX & SWT 4
CptK Wieso wird nur ein Teil meiner Buttons angezeigt? AWT, Swing, JavaFX & SWT 1
J Ziehen eines Buttons im JPanel AWT, Swing, JavaFX & SWT 2
J Drag and Drop eines Buttons AWT, Swing, JavaFX & SWT 0
J TicTacToe Buttons AWT, Swing, JavaFX & SWT 14
J ActionListener bei Buttons AWT, Swing, JavaFX & SWT 14
DaCrazyJavaExpert Swing Extern den Text eines nicht fetsgelegten Buttons bekommen. AWT, Swing, JavaFX & SWT 12
T Swing Double Click bei Buttons in JTable AWT, Swing, JavaFX & SWT 9
C Buttons funtionieren nicht AWT, Swing, JavaFX & SWT 10
S SWT neues Fenster, buttons aus alten etc... AWT, Swing, JavaFX & SWT 0
G vorgefertigte Buttons oder neue Komponente mit MouseListener? AWT, Swing, JavaFX & SWT 0
Neumi5694 Sprache der Standard-Buttons AWT, Swing, JavaFX & SWT 7
Timo_neu_in_java Buttons Erstellen AWT, Swing, JavaFX & SWT 6
H JavaFX TableCell mit Buttons AWT, Swing, JavaFX & SWT 1
A Swing Programm funktioniert aber zwei Buttons werden angezeigt AWT, Swing, JavaFX & SWT 3
kilopack15 Buttons ohne Funktion AWT, Swing, JavaFX & SWT 2
S Keylistener reagiert bei Buttons nicht. AWT, Swing, JavaFX & SWT 8
S ActionListener für alle Buttons AWT, Swing, JavaFX & SWT 26
T Buttons auf Tablet viel kleiner als am PC AWT, Swing, JavaFX & SWT 0
S Buttons und TextField automatisch vergrößern AWT, Swing, JavaFX & SWT 8
R 2D-Grafik Buttons mit Slick2D und LWJGL AWT, Swing, JavaFX & SWT 2
J JavaFX Buttons mit Array erzeugen AWT, Swing, JavaFX & SWT 1
JG12111989 Buttons funktionieren nicht AWT, Swing, JavaFX & SWT 4
A Swing Buttons werden trotz setVisible nicht dargestellt AWT, Swing, JavaFX & SWT 14
M Buttons in JSplitPane hinzufügen AWT, Swing, JavaFX & SWT 6
X Swing Anwendung regaiert auf keine Buttons mehr wärend while(scanner.hasNextLine()) ausgeführt wird. AWT, Swing, JavaFX & SWT 4
T Durch klicken eines Buttons Klasse wechseln AWT, Swing, JavaFX & SWT 2
A Swing JPanel zeigt Buttons nicht an AWT, Swing, JavaFX & SWT 4
V Tastatur KeyListener für mehrere Buttons AWT, Swing, JavaFX & SWT 1
I JavaFX Langes drücken eines Buttons AWT, Swing, JavaFX & SWT 4
I JavaFX Buttons und TableView AWT, Swing, JavaFX & SWT 2
K Swing Durch Methode erzeugte Buttons ansteuern AWT, Swing, JavaFX & SWT 5
D Buttons werden nebeneinander angeordnet AWT, Swing, JavaFX & SWT 9
J Java -8 Action Listener für mehrere Buttons AWT, Swing, JavaFX & SWT 9
D JavaFX Dynamisch erzeugte Buttons sollen Code ausführen. AWT, Swing, JavaFX & SWT 2
D Buttons erscheinen nicht auf Frame AWT, Swing, JavaFX & SWT 2
M 4-Gewinnt mit Buttons AWT, Swing, JavaFX & SWT 1
Y Kann man Buttons in einem JFrame rund machen ? AWT, Swing, JavaFX & SWT 2
K Swing Keine Reaktion auf Tastatureingaben bei mehreren Buttons??? AWT, Swing, JavaFX & SWT 4
wolfgang63 JavaFX Transparenter Hintergrund aber sichtbare Buttons AWT, Swing, JavaFX & SWT 6
C Im ActionListener Buttons disablen, einen Thread starten, dann Buttons enablen AWT, Swing, JavaFX & SWT 2
gamebreiti auf usereingabe warten mit GUI(nur Labels, Buttons etc. keine Texteingaben) AWT, Swing, JavaFX & SWT 3
W Buttons verschieben AWT, Swing, JavaFX & SWT 3
R Swing Buttons werden nicht angezeigt AWT, Swing, JavaFX & SWT 4
P Buttons/Labels auf GUI positionieren AWT, Swing, JavaFX & SWT 2
X Swing setContentPane verdeckt mir alle Buttons Labels etc... AWT, Swing, JavaFX & SWT 14
H Taschenrechnerprojekt in Javafx - Frage zu den Buttons in FXML AWT, Swing, JavaFX & SWT 1
U Swing Beim Bedienen eines Buttons JFrame schließen AWT, Swing, JavaFX & SWT 2
A Radio Buttons sollen den Text der text Area bestimmen AWT, Swing, JavaFX & SWT 9
H org.eclipse.swt.Slider ohne Buttons AWT, Swing, JavaFX & SWT 1
U Buttons schräg implementieren AWT, Swing, JavaFX & SWT 4
X buttons aus externe klasse lesen? AWT, Swing, JavaFX & SWT 3
V Buttons sehen immer "active" aus AWT, Swing, JavaFX & SWT 6
K Event Handling 2 Buttons und Thread stop AWT, Swing, JavaFX & SWT 3
D Buttons erscheinen nicht auf dem zweiten Frame AWT, Swing, JavaFX & SWT 4
D Wie kann ich Buttons und Labels besser anordnen AWT, Swing, JavaFX & SWT 4
C Probleme mit Buttons und einem ActionListener AWT, Swing, JavaFX & SWT 2
A Swing bei Auswahl und klick eines JComboBox buttons die Klasse eines anderen Projekts aufrufen AWT, Swing, JavaFX & SWT 3
M Menü mit Buttons AWT, Swing, JavaFX & SWT 8
H Swing JTabbedPane: Zusätzliche Buttons neben den Tabs AWT, Swing, JavaFX & SWT 7
A Swing Focus der Radio Buttons + text bleibt gleich und gleichzeitige ausgabe zweier Objekte in 1. Fenster AWT, Swing, JavaFX & SWT 3
U Swing Buttons generieren AWT, Swing, JavaFX & SWT 19
G Swing Buttons in Layouts frei platzieren AWT, Swing, JavaFX & SWT 7
S Layouts, mehrere Buttons nebeneinander AWT, Swing, JavaFX & SWT 2
B Buttons auf JLabel? AWT, Swing, JavaFX & SWT 4
J ActionListener für Buttons AWT, Swing, JavaFX & SWT 3
1 Buttons in Kombination mit Linien AWT, Swing, JavaFX & SWT 3
K Aussehen des Buttons resetten AWT, Swing, JavaFX & SWT 4
C Verschiebbare "Buttons" in einer Tabelle AWT, Swing, JavaFX & SWT 3
A JButton - Klicks zählen auf mehreren Buttons AWT, Swing, JavaFX & SWT 2
H Swing Button Klick soll "Untermenü-Buttons" erzeugen AWT, Swing, JavaFX & SWT 2
dzim Toolbar - Problem bei enable/disable von Buttons AWT, Swing, JavaFX & SWT 6
E Netbeans: Buttons mit Label bzw. Rahmen unterlegen AWT, Swing, JavaFX & SWT 8
F Grafik mit Buttons versehen AWT, Swing, JavaFX & SWT 8
J JOptionPane mit zwei Buttons?! AWT, Swing, JavaFX & SWT 3
K Schachbrett mit buttons AWT, Swing, JavaFX & SWT 2
B Buttons entfernen / hinzufügen AWT, Swing, JavaFX & SWT 5
TheWhiteShadow Swing Buttons in Liste AWT, Swing, JavaFX & SWT 7
C AWT Buttons verschwinden, wenn Fenster Vollbild gesetzt wird AWT, Swing, JavaFX & SWT 38
C AWT Verwendung von Buttons in Spielen AWT, Swing, JavaFX & SWT 8

Ähnliche Java Themen

Neue Themen


Oben