[Swing] Anordnung von Komponenten mit GridLayout Manager

Diskutiere [Swing] Anordnung von Komponenten mit GridLayout Manager im AWT, Swing, JavaFX & SWT Bereich.
D

DerBär

Hi,
ich versuche mich aktuell an Swing, komme aber leider bei der Anordnung meiner Komponenten mithilfe des GridLayout Managers nicht so recht voran.
ich habe eine kleine GUI zum Ausrechnen von Preisdifferenzen von zwei Websites erstellt.
Die Elemente innerhalb der GUI habe ich in 4 verschiedene Panels unterteilt und für jedes der Panels eine eigene Instanz des GridLayout Managers erstellt um den Inhalt der Panels anzuordnen.
Mein erstes Problem ist jedoch, dass der GridLayout Manager die Komponenten innerhalb der Panels immer linksbündig ausrichtet, ich würde diese aber gerne mittig im Zentrum der jeweiligen Panel Zelle ausrichten.
Mein zweites Problem ist, dass die JTextfields und JTextAreas immer eine komplette Zelle des jeweiligen Panels ausfüllen, schöner wäre es wenn ich irgendwie die Größe bestimmen könnte (Lt. meinen Recherchen geht das aber wohl nur mit einem anderern LayoutManager wie dem GridBagLayout) ist die Anpassung der Größe mittels GridLayout Manager wirklich unmöglich?
Ich habe mal die GUI als Bild angefügt damit ihr euch ein Bild machen könnt, sollte Code benötigt werden liefere ich diesen natürlich gerne nach:

csumrechner.PNG

Vielen Dank für eure Hilfe!
 
L

LimDul

Kurz und knapp: Es geht nicht mit dem GridLayout, siehe auch die API-Doc:
All components in the layout are given equal size.

Du kannst das natürlich erreichen, indem du die Komponenten nicht direkt ins Gridlayout packst, sondern z.B. voher in ein JPanel packst, so dass sie innerhalb der JPanels so sind, wie du es möchtest - aber sinnvoller fände ich da das GridBagLayout direkt zu verwenden.
 
D

DerBär

Kurz und knapp: Es geht nicht mit dem GridLayout, siehe auch die API-Doc:


Du kannst das natürlich erreichen, indem du die Komponenten nicht direkt ins Gridlayout packst, sondern z.B. voher in ein JPanel packst, so dass sie innerhalb der JPanels so sind, wie du es möchtest - aber sinnvoller fände ich da das GridBagLayout direkt zu verwenden.
Alles klar, danke für die Antwort.
Wie sieht es denn mit der Ausrichtung der Komponenten innerhalb der Panels aus (Damit diese z.B. zentriert statt immer linksbündig ausgerichtet werden). Ist das mit dem GridLayout Manager möglich?
 
MoxxiManagarm

MoxxiManagarm

Kannst du eventuell mit einem UI-Planungstool aufmalen wie es aussehen soll? Ich werde leider aus der Beschreibung nicht ganz so schlau.
 
D

DerBär

Kannst du eventuell mit einem UI-Planungstool aufmalen wie es aussehen soll? Ich werde leider aus der Beschreibung nicht ganz so schlau.
Also bei der jetzigen GUI die ich als Bild angefügt habe sind ja z.B. die JLABEL ("Preis Cs.deals") und ("Preis Buff163") immer linksbündig angeordnet.
Ich meine damit, dass diese etwas weiter nach rechts verschoben werden und damit eher mittig angeordnet sind.
 
MoxxiManagarm

MoxxiManagarm

Also bei der jetzigen GUI die ich als Bild angefügt habe sind ja z.B. die JLABEL ("Preis Cs.deals") und ("Preis Buff163") immer linksbündig angeordnet.
Ich meine damit, dass diese etwas weiter nach rechts verschoben werden und damit eher mittig angeordnet sind.
Was spricht dagegen nicht die Position des Labels zu ändern, sondern Text Alignment innerhalb des Labels?

Java:
label.setHorizontalAlignment(SwingConstants.CENTER);
 
M

MayorB26

Hi,
ich versuche mich aktuell an Swing, komme aber leider bei der Anordnung meiner Komponenten mithilfe des GridLayout Managers nicht so recht voran.
ich habe eine kleine GUI zum Ausrechnen von Preisdifferenzen von zwei Websites erstellt.
Die Elemente innerhalb der GUI habe ich in 4 verschiedene Panels unterteilt und für jedes der Panels eine eigene Instanz des GridLayout Managers erstellt um den Inhalt der Panels anzuordnen.
Mein erstes Problem ist jedoch, dass der GridLayout Manager die Komponenten innerhalb der Panels immer linksbündig ausrichtet, ich würde diese aber gerne mittig im Zentrum der jeweiligen Panel Zelle ausrichten.
Mein zweites Problem ist, dass die JTextfields und JTextAreas immer eine komplette Zelle des jeweiligen Panels ausfüllen, schöner wäre es wenn ich irgendwie die Größe bestimmen könnte (Lt. meinen Recherchen geht das aber wohl nur mit einem anderern LayoutManager wie dem GridBagLayout) ist die Anpassung der Größe mittels GridLayout Manager wirklich unmöglich?
Ich habe mal die GUI als Bild angefügt damit ihr euch ein Bild machen könnt, sollte Code benötigt werden liefere ich diesen natürlich gerne nach:

Anhang anzeigen 13428

Vielen Dank für eure Hilfe!
Ja, bitte schick mir den code, natürlich mit dem alignment befehl dabei.

Also die codeversion nach der lösung des zentrierproblems ;) ;) ;)

Mit freundlichen Grüßen

Gunnar
 
D

DerBär

Code:
/*Werte von Buff zu Cs.deals umrechnen (Und umgedreht je nachdem was per Dropdown menü ausgewählt ist)
Einmal Prozentwert und einmal Gewinn pro verkaufter Einheit ausrechnen (Bei mehreren Einheiten sollen auch mehrere einheiten per texteld aufgenommen und gewinn für alle ausgerechnet werden).
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class CsUmrechner extends JFrame {
    //labels
    JLabel label_price_csdeals,label_price_buff,label_procent,label_profit,label_sellonbuff,label_selloncsdeals;
    //Eingabefelder
    JTextField insert_price_csdeals,insert_price_buff;
    //Ausgabefelder
    JTextArea output_procent,output_profit;
    //Button "berechnen" zum auslösen des actionevents
    JButton button_berechnen;
    //Checkboxen um zu prüfen ob item auf csdeals oder buff verkauft wird (Um Kommission 1% csdeals oder 1.8% buff zu bestimmen).
    JCheckBox checkbox_sellonbuff;
    JCheckBox checkbox_selloncsdeals;



    public class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            double price_csdeals,price_buff;
            String procent_output;
            String profit_output;
            double procent_buff_to_csdeals,profit_unit;
            boolean disable_profit_output= false;
            try {

                 price_csdeals = Double.parseDouble(insert_price_csdeals.getText());
                 price_buff = Double.parseDouble(insert_price_buff.getText());

            }
            catch (NumberFormatException nfe) {
                output_procent.setText("Error please insert number");
                output_profit.setText("Error please insert number");
                return;
            }

            if (checkbox_sellonbuff.isSelected() && !checkbox_selloncsdeals.isSelected()) {
                procent_buff_to_csdeals = getProcentBuffToCsdeals(price_buff, price_csdeals,false);
                //Profit Output Feld wird bei Verkauf auf Buff nicht benötigt
                disable_profit_output=true;
                profit_unit=0;

            }
            else if (checkbox_selloncsdeals.isSelected() && !checkbox_sellonbuff.isSelected()) {
                procent_buff_to_csdeals = getProcentBuffToCsdeals(price_buff, price_csdeals,true);
                profit_unit = getProfitPerUnit(price_buff, price_csdeals);
                disable_profit_output=false;
            }
            else {
                //Initialisierung weil compiler sonst meckert
                procent_buff_to_csdeals= 0;
                profit_unit=0;
                //Fehler ausgeben
                output_procent.setText("Error pls select one checkbox");
                output_profit.setText("Error pls select one checkbox");
                return;
            }

            try {
                procent_output = String.valueOf(procent_buff_to_csdeals);
                profit_output = String.valueOf(profit_unit);


            } catch (Exception st_convert) {
                output_procent.setText("Internal error while converting double to String");
                output_profit.setText("Internal error while converting double to String");
                return;
            }
            output_procent.setText(procent_output);
            if(!disable_profit_output) {
                output_profit.setText(profit_output);
            }
            else {
                output_profit.setText("/");
            }


        }
    }




    /*class TextfieldListener implements ActionListener {

       //Hier die Funktionen zur Umrechnung, Prozentrechnung etc. implementieren
        @Override
        public void actionPerformed(ActionEvent e) {






            //Listener um Enter Eingabe des JTextfields abzufangen, wird aber nicht benötigt da erstmal ein Button "Rechnen" zum auslösen des events verwendet wird
             String action_command;
            action_command=e.getActionCommand();
            if (action_command.equals("csdeals_price")) {
                String price_csdeals = insert_price_csdeals.getText();
                //output_procent.append(price_csdeals);


            }

            else if(action_command.equals("buff_price")) {
                String buff_price = insert_price_buff.getText();
                //output_procent.setText(buff_price);

            }

            //Hier die Funktionen zur Umrechnung, Prozentrechnung etc. ausführen und die Werte der JLabels anschließend unpassen zur Ausgabe der Werte
        }
   }


   */

    CsUmrechner(String title) {
        super(title);
        button_berechnen = new JButton("calculate");
        //Alle Labels fürs Programm instanzieren
        label_price_csdeals = new JLabel("Price Cs.deals:");
        label_price_buff = new JLabel("Price Buff163:");
        label_procent = new JLabel(" %Buff/Cs.deals price:");
        label_profit = new JLabel ("Profit $ per unit:");
        //Alignment für die labels auf Center setzen, damit diese mittig angezeigt werden
        label_price_csdeals.setHorizontalAlignment(SwingConstants.CENTER);
        label_profit.setHorizontalAlignment(SwingConstants.CENTER);
        label_price_buff.setHorizontalAlignment(SwingConstants.CENTER);
        label_procent.setHorizontalAlignment(SwingConstants.CENTER);
       // label_sellonbuff = new JLabel("Sell item on Buff");
        //label_selloncsdeals = new JLabel("Sell item on csdeals");
        //Alle Eingabefelder  fürs Programm instanzieren
        insert_price_csdeals = new JTextField(5); //colum größe 5 ist egal,wird eh durch layout manager überschrieben
        insert_price_buff = new JTextField(5);
        /*
        //Für JTextfield müssen ActionCommands selber definiert werden damit man diese im Action Listener abfangen kann aktuell auskommentiert, da ein Button für events genutzt wird.
        insert_price_csdeals.setActionCommand("csdeals_price");
        insert_price_buff.setActionCommand("buff_price");
         */
        //Alle Ausgabefelder instanzieren
        output_procent = new JTextArea(1,1);
        output_profit = new JTextArea();
        //User soll in text Ausgabefeldern selbst keine Eingaben tätigen können
        output_procent.setEditable(false);
        output_profit.setEditable(false);
        //Checkboxen instanzieren
        checkbox_sellonbuff = new JCheckBox("Sell item on buff",false);
        checkbox_selloncsdeals = new JCheckBox(" Sell item on csdeals",true);
        checkbox_selloncsdeals.setHorizontalAlignment(SwingConstants.CENTER);
        checkbox_sellonbuff.setHorizontalAlignment(SwingConstants.CENTER);
        //ButtonGroup erstellen und beide checkboxen registrieren, dies bewirkt, dass immer nur eine Checkbox gleichzeitig angehakt sein kann
        ButtonGroup checkbox_group = new ButtonGroup();
        checkbox_group.add(checkbox_sellonbuff);
        checkbox_group.add(checkbox_selloncsdeals);
        //Layout fürs Main Fenster definieren
        setLayout(new GridLayout(4,0,0,25));
        //Panels zur Aufnahme der In/Out Felder instanzieren
        JPanel panel_button =new JPanel();
        JPanel panel_insert =new JPanel();
        JPanel panel_output= new JPanel();
        JPanel panel_checkboxes = new JPanel();
        //Layout Manager für Panels definieren, später nochmal mit gridbaglayout versuchen um textfelder kleiner zu machen, war mir nur grad etwas zu komplex
        panel_button.setLayout(new GridLayout(0,1,0,2));
        panel_insert.setLayout(new GridLayout(0,2,0,2));
        panel_output.setLayout(new GridLayout(0,2,0,5));
        panel_checkboxes.setLayout(new GridLayout(0,2,0,0));
        //Labels und Textfelder dem ersten Panel zuordnen
        panel_insert.add(label_price_csdeals);
        panel_insert.add(insert_price_csdeals);
        panel_insert.add(label_price_buff);
        panel_insert.add(insert_price_buff);
        //Labels und Textfelder dem zweiten Label zuordnen
        panel_output.add(label_procent);
        panel_output.add(output_procent);
        panel_output.add(label_profit);
        panel_output.add(output_profit);
        //Button(s) dem ButtonPanel hinzufügen
        panel_button.add(button_berechnen);
        //Checkboxen dem PanelCheckbox hinzufügen
        panel_checkboxes.add(checkbox_selloncsdeals);
        panel_checkboxes.add(checkbox_sellonbuff);
        //Panels dem Main Window hinzufügen
        add(panel_insert);
        add(panel_checkboxes);
        add(panel_button);
        add(panel_output);
        //Listener für button instanzieren und gleichzeitig registrieren
        button_berechnen.addActionListener(new ButtonListener() );



        /*

        //Wird benötigt, wenn ActionListener (Enter) der JTextfields genutzt werden soll, aktuell wird aber nur der Listener des Button benutzt
        TextfieldListener insertlistener= new TextfieldListener();
        insert_price_buff.addActionListener(insertlistener);
        insert_price_csdeals.addActionListener(insertlistener);
         */




        //default close operation fürs main window(Schließen und Prog beenden)
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    } //Ende Konstruktur der abgeleiteten JFrame Klasse

    private double getProcentBuffToCsdeals(double price_buff,double price_csdeals,boolean sell_on_csdeals) {
        double result;
        //Wenn auf Csdeals verkauft wird 1% comission
        if (sell_on_csdeals) {
            return result = price_buff / (price_csdeals*0.99);
        }
        //Wenn auf Buff verkauft wird 1.8% comission für dota2 items
        else {

            return result = (price_buff*0.982) / price_csdeals;
        }
    }

    private double getProfitPerUnit(double price_buff, double price_csdeals) {
        //Profit von auf buff gekaufter und auf csdeals verkaufter einheit
        //Es wird hier als standard Cashin Wert auf Buff 0.945% angenommen (Üblicher Preisverlust bei kauf von arcs auf csdeals und verkauf auf Buff in usd)
        double result;
        final double buff_cash_in = 0.945;
            return result = (price_csdeals*0.99) - (price_buff / buff_cash_in); //Bedeutet verkaufspreis/ buff cash in Preis (den man auf csdeals fürs cash in bei buff zahlt) (Also den Gewinn den man erhält)
    }

    private double getProfitPerUnit(double price_buff,double price_csdeals,final double procent_buff_cash_in) {
        //Funktion für später, wenn man den Prozentwert zum Cash In auf Buff selber per Textfield angeben will
        double result;
        return result = (price_csdeals*0.99) - (price_buff / procent_buff_cash_in);

    }


    public static void main(String[] args) {
        CsUmrechner mainwindow= new CsUmrechner("CS Umrechner");
        mainwindow.pack();
        mainwindow.setSize(300,300);
        mainwindow.setVisible(true);
    }


}
Ja, bitte schick mir den code, natürlich mit dem alignment befehl dabei.

Also die codeversion nach der lösung des zentrierproblems ;) ;) ;)

Mit freundlichen Grüßen

Gunnar
Hier der komplette Code. Das Alignment setze ich sowohl für die JLabels als auch für die JCheckboxes direkt nach Instanzierung im Konstruktur .
Da dies allerdings meine allererste GUI mit Swing ist würde ich mir kein Beispiel daran nehmen, vermutlich wimmelt es nur so von Fehlern ;) .
Das Programm soll mir einfach den Prozentsatz beim Verkauf von items ermitteln und auch einen Prozentsatz angeben, damit ich das nicht immer manuell ausrechnen muss.
Wenn irgendwer Verbesserungsvorschläge hat oder ich irgendwelche ganz groben Schnitzer eingebaut habe die man nicht machen sollte bin ich natürlich über jeden Tipp dankbar!
Ich werde mich dennoch die Tage mal mit dem GridBagLayout Manager befassen weil es mich etwas stört, dass man die JTextFields und JTextAreas mit dem GridLayout Manager nicht in der Größe anpassen kann.

Btw. mal so als OFF Topic Frage arbeitet ihr eigentlich selbst noch mit Swing, oder wird mittlerweile hauptsächlich(ausschließlich) JavaFX als Gui Framework im professionellen Bereich verwendet?
 
L

LimDul

Privat bei Hobbyprojekten hab ich bisher auf Swing gesetzt und da zu 90% auf das GridBagLayout - weil ich das für mächtig empfinde und mit etwas Vorplanung auch sehr einfach handlebar finde. Im Endeffekt ist das GridBagLayout ja auch nur ein Grid - mit dem Unterschied:
- Ich kann Objekte mit x und y Koordinaten (bzgl. des Grids) im Grid plazieren
- Ich kann Objekte über mehrere Zeilen und Spalten ausdehnen
- Ich kann für jede Zelle, das Alignment der Komponente in der Zelle festlegen (Links/Rechts/Oben/Unten etc.)
- Ich kann für jede Zelle festlegen ob die Komponente sich in x und/oder y Richtung vergößern soll.

Nachteil ist, dass da sehr viel geschwätziger Code rausfällt.

Im professionellen Bereich würde ich sagen, macht den Löwenanteil an Java Entwicklung Webanwendungen aus und nicht Desktop-Anwendungen.
 
D

DerBär

Ich habe mich heute mal etwas am GridBagLayout versucht und habe so langsam den Dreh raus. Ich habe mit dem Beispiel Code von Orakel rumgespielt um die Constraints etwas besser zu verstehen, allerdings verstehe ich einfach nicht wie es mit dem resizen des Windows richtig funktioniert.
Ich habe folgenden Code von Orakel zum testen genutzt:
Code:
package layout;

/*
* GridBagLayoutDemo.java requires no other files.
*/

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

public class GridBagLayoutDemo {
    final static boolean shouldFill = true;
    final static boolean shouldWeightX = true;
    final static boolean RIGHT_TO_LEFT = false;

    public static void addComponentsToPane(Container pane) {
        if (RIGHT_TO_LEFT) {
            pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        }

        JButton button;
    pane.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    if (shouldFill) {
    //natural height, maximum width
    c.fill = GridBagConstraints.HORIZONTAL;
    }

    button = new JButton("Button 1");
    if (shouldWeightX) {
    c.weightx = 0.5;
    }
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.gridy = 0;
    pane.add(button, c);

    button = new JButton("Button 2");
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 0.5;
    c.gridx = 1;
    c.gridy = 0;
    pane.add(button, c);

    button = new JButton("Button 3");
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 0.5;
    c.gridx = 2;
    c.gridy = 0;
    pane.add(button, c);

    button = new JButton("Long-Named Button 4");
    c.fill = GridBagConstraints.HORIZONTAL;
    c.ipady = 40;      //make this component tall
    c.weightx = 0.0;
    c.gridwidth = 3;
    c.gridx = 0;
    c.gridy = 1;
    pane.add(button, c);

    button = new JButton("5");
    c.fill = GridBagConstraints.HORIZONTAL;
    c.ipady = 0;       //reset to default
    c.weighty = 1.0;   //request any extra vertical space
    c.anchor = GridBagConstraints.PAGE_END; //bottom of space
    c.insets = new Insets(10,0,0,0);  //top padding
    c.gridx = 1;       //aligned with button 2
    c.gridwidth = 2;   //2 columns wide
    c.gridy = 2;       //third row
    pane.add(button, c);
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("GridBagLayoutDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Set up the content pane.
        addComponentsToPane(frame.getContentPane());

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
Ich habe verstanden, dass man mit weightx/weighty das resizing verhalten beeinflussen kann und im Beispiel soll Button5 ja aufgrund von weighty=1 alles an vertikalem Platz zugeordnet bekommen. Dadurch wird aber nicht der Button selbst vertikal größer sondern über dem Button ist beim resize einfach nur extrem viel "leerer" Platz der zwischen Button4 und 5 dazukommt. Ich verstehe leider überhaupt nicht wie ich nun den Button selbst beim resize vertikal vergrößern kann. Kann mir das irgendwer hier erklären?
Ich würde eigentlich am liebsten haben, dass alle Buttons beim resize gleichmäßig größer werden, aber auch wenn ich bei allen Komponenten weighty=1 setze werden die Buttons selbst nicht größer sondern es wird zwischen allen Buttons einfach leerer Platz(weiß) dazwischengesetzt, die Buttons selbst bleiben aber bei der gleichen Vertikalen Größe. Horizontal werden die Buttons richtig angepasst nur irgendwie eben nicht vertikal.
Hier ist die Seite von der das Beispiel stammt https://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
 
Zuletzt bearbeitet:
L

LimDul

Java:
    c.fill = GridBagConstraints.HORIZONTAL;
Du sagst ja, die sollen nur Horizontal wachsen - BOTH wäre das richtige, was du willst.
 
D

DerBär

Java:
    c.fill = GridBagConstraints.HORIZONTAL;
Du sagst ja, die sollen nur Horizontal wachsen - BOTH wäre das richtige, was du willst.
Hi vielen Dank für die Antwort ich hätte mal richtig lesen sollen habe es grade auch bemerkt. Wenn ich fill auf both für die Komponenten setze funktioniert das perfekt die vertikale mit weighty zu bestimmen.
Vielen Dank dennoch für die schnelle Antwort ich stand grade echt etwas auf dem Schlauch :( .
Ich glaube damit habe ich erstmal alles was ich brauche um meine GUI auf GridBagLayout anzupassen, vielen Dank an alle die geholfen haben werde morgen mal versuchen die GUI aufs GridBagLayout umzustellen.
 
D

DerBär

So da bin ich doch nochmal. Habe angefangen mein Programm umzustellen und das Padding mit Angabe der Pixel (z.B. durchs Instanzieren eines Insets Objekts) is ja schön und gut wenn die GUI in der Standardmäßig definierten größe bleibt. Ich würde aber gerne haben, dass die Abstände zwischen den Komponenten sich beim vergrößern auch proportional mitverändern.
Ein Beispiel:
Ich habe eine GUI mit 100x100 default Größe. Darin enthalten 2 Buttons die nebeneinander in der selben Reihe sind. Ich erstelle nun ein Insets Objekt um die Buttons mit 10 Pixel Abstand nebeneinander zu platzieren. Wenn ich meine GUI nun auf 200x200 Pixel resize sind die Buttons aber immernoch nur 10Pixel voneinander entfernt, ich hätte aber gerne, dass dieser Abstand sich beim resizen auch proportional verändert (Auf 20Pixel Abstand in diesem Szenario). Die einzige Möglichkeit die ich aktuell sehe das zu realisieren wäre die Buttons auf mehrere Spalten (z.B. drei Spalten pro Button) aufzuteilen und in der Mitte beider Buttons eine Spalte mit leerem JLabel zu definieren. Wäre das die einzige Lösung, oder gibt es für das Problem eine bessere Lösung?
 
Thema: 

[Swing] Anordnung von Komponenten mit GridLayout Manager

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben