Swing , GridLayout, Größenbestimmung der Komponenten im Layout

HarryR

Mitglied
Hallo zusammen,

ich programmiere schon eine Weile Java-Programme und bin immer froh, wenn ich keine GUI benötige 🙂
Die Möglichkeiten eine GUI zu gestalten sind in swing mannigfaltig, aber es ist mir noch nie gelungen
eine zufriedenstellende Lösung zu implementieren.
Da ich ungern unzufrieden bin brauche ich eure Hilfe um dieses Thema engültig richtig zu verstehen und dann auch etwas ansprechendes hinzubekommen.
Genug der Vorrrede, gehen wir ins Detail.
Ich verwende gerne das GridLayout, wenn ich die einzelnen Komponenten vorausberechnen kann.
Nehmen wir als Beispiel eine Matrix aus 3x3 JLabel.
Diese wird initiiert und jedes Label bekommt eine voreingestelle Größe.
Zur Laufzeit bleibt die Höhe (height) immer gleich, die Breite (width soll sich aber ändern können).
Warum ?
Zur Laufzeit wird unterschiedlich langer Text mit setText gesetzt. Der gesamte Text (dessen Länge vorher nur größenordnungsmässig bekannt ist ,
also sowas wie "unter 50 Zeichen") soll sichtbar sein, also muss das JLabel breiter werden, wenn der Text neu gesetzt wird.
Ob sich dann die anderen JLabels ebenfalls in der Größe ändern wäre egal. Falls die Gesamtbreite der Matrix (bzw hier im Beispiel eine Zeile der Matrix)
sich ändert, auch egal, dann wird halt gescrollt.
Das klappt auch gut ..
Aber die automatische Änderung der JLabel gar nicht.
Hier mal ein Codeschnipsel, der demonstriert, was ich bisher versucht habe:

[CODE lang="java" title="Eine Zeile der Matrix"]final static int maxGap = 20;


private static Font myFont = new Font("SansSerif", Font.BOLD, 12);

GridLayout panelLayout = new GridLayout(0,columns+1);

JPanel line = new JPanel();

// Ich weiß vorher nicht, wie breit die Zeile wird, columns kann "fast" beliebig sein, daher wird hier einfach mal etwas gesetzt, was irgendwie passt
line.setSize(1000, 100);
line.setLayout(panelLayout);
line.setBorder(raisedetched);

// Eine spalte mehr, da ich noch eine Nummerirerung der Zeilen voranstelle
for (int i = 0;i<= columns;i++)
{
//Nummerierung
if (i == 0)
{
l = new JLabel(LText);
l.setBackground(Color.darkGray);
l.setForeground(Color.white);
}
else // variable Texte in den JLabel
// hier müsste eigentlich die Variabilität schon als Eigenschaft reiinkommen, aber wie ?
{
l = new JLabel(Integer.toString(i)); // Nur der "Init-Text, zur Laufzeit wird es länger"
l.setBackground(Color.gray);
}
l.setOpaque(true);
// irgendeien Schätzwert, der sich bewährt hat, empirisch ermittelt
l.setPreferredSize(new Dimension((int)(buttonSize.getWidth() )+maxGap,
(int)(buttonSize.getHeight()*0.5 )+maxGap));

l.setFont(myFont);
l.setBorder(blackline);
line.add(l);
}[/CODE]

So, zur Laufzeit passiert daann folgendes, ein String (nehemn wir an 20 Zeichen) soll via setText
gesetzt werden (klappt, da ich mir die JLabels in einem Array "merke" und dann einfach indiziert
auf das jeweilige JLabel zugreife.

Es passiert also nichts weiter ausser folgendes,
meine bisher untauglichen Versuche brauche ich nicht zu zeigen ...:

Java:
// das könnte das 3. oder letzte JLabel aus dem Code von "oben" sein.
label.setText("ein langer String der anzuzeigen ist");
// danach sollte das Label den gesamten Text anzeigen

Wie bekomme ich das so hin, dass sich die JLabel in der Breite anpassen,
(und das JPanel line dann notwendigerwese auch) ?

Ups, was nicht zu vergessen ist .. wo kommt die Matrix dann wie hin:
Der entsprechende Code wäre/ist ungefähr so:

Java:
public JPanel createLableLinePanel(int rows,int columns)
{
    JPanel taskViewer = new JPanel());
            
       taskViewer().setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    // ?
    //c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.gridy = 0;
            
    for (int i=0;i<rows;i++)
    {
         // labelLine.createLabelLine ist im Grunde der Code von oben und erstellt ein JPanel aus columns JLabels
        // und ein wenig nicht swing-Brimborium
          taskViewer().add(i,labelLine.createLabelLine(columns,i,formatedInt(i+1,3,true)));           
       }
    return(taskViewer());
   }


Ich hoffe/denke, dass das für einige von euch trivial ist und ihr mir auf die Sprünge helft.

Viele Grüße und bleibt gesund
Harry
 
Du verwendest ein GridLayout, da wird die Breite der Spalten durch deren Anzahl bestimmt, nicht durch das, was darin ist.
Z.B. in einem GridbagLayout oder einem FlowLayout werden die Breiten automatisch angepasst, wenn du den Text änderst.

Keine Ahnung, was taskviewer() liefert oder welches Layout der verwendet.
 
ps:
Java:
l.setPreferredSize(...)
Ganz schlechte Idee, dies setzt jeden etwaigen Automatismus außer Kraft. Damit wird fix diese Größe verwendet, komme was wolle (es sei denn natürlich, das Ding hat keinen Platz im Container).
 
Du verwendest ein GridLayout, da wird die Breite der Spalten durch deren Anzahl bestimmt, nicht durch das, was darin ist.
Z.B. in einem GridbagLayout oder einem FlowLayout werden die Breiten automatisch angepasst, wenn du den Text änderst.

Keine Ahnung, was taskviewer() liefert oder welches Layout der verwendet.
Okay, ich nehme mal das GridBagLayout (was mir aber auch Problemem bereitet, aber as wird ein andere Thread)
 
ps:
Java:
l.setPreferredSize(...)
Ganz schlechte Idee, dies setzt jeden etwaigen Automatismus außer Kraft. Damit wird fix diese Größe verwendet, komme was wolle (es sei denn natürlich, das Ding hat keinen Platz im Container).
Also einfach weglassen ?
Das Layout wird nicht immer neu berechnet. Dazu müsstest Du ein (re)validate() auf dem Panel aufrufen.
okay, das bekomme ich hin ..
 
Mit setPreferredSize setzt du manuell eine Größe, das braucht man im Normalfall wirklich nur dann, wenn der Layoutmanager versagt oder bestimmte Komponenten immer gleich groß bleiben müssen, auch wenn dann nicht der ganze Text angezeigt wird.

Vielleicht solltest du mal den kompletten Formularcode posten, mir ist nicht ganz klar, wie und wo die Komponente mit dem Gridlayout eingebettet ist, das Problem kann ja auch dort zu suchen sein.
 
Mal ein kleines Beispiel mit GridLayout:
Java:
import java.awt.*;
import javax.swing.*;

public class Test {
    public void run() {
        JPanel inner = new JPanel(new GridLayout(0,3));

        JLabel[] labels = new JLabel[9];
        for (int i = 0; i < labels.length; i++) {
            labels[i] = new JLabel("Label #" + (i+1));
            inner.add(labels[i]);
        }

        JTextField tf = new JTextField(30);
        JButton button = new JButton("OK");
        button.addActionListener(e -> {
            labels[0].setText(tf.getText());
            inner.revalidate();
        });

        JPanel input = new JPanel();
        input.add(tf);
        input.add(button);

        JPanel outer = new JPanel(new BorderLayout());        
        outer.add(input, BorderLayout.NORTH);
        outer.add(inner, BorderLayout.SOUTH);

        JPanel container = new JPanel(new BorderLayout());
        container.add(outer, BorderLayout.NORTH);
    
        
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(new JScrollPane(container));
        frame.setSize(450, 300);
        frame.setVisible(true);
    }

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

Neue Themen


Zurück
Oben