LayoutManager GridLayout verschiebt sich

Lokilein

Mitglied
Hallo alle zusammen,

ich habe folgendes Problem: Ich möchte gerne einen Kalender schreiben und grundsätzlich funktioniert das auch schon ganz gut - zumindest wenn ich den Kalender das erste Mal aufrufe. Beim Wechsel des Monats oder des Jahres ändert sich aber mein GridLayout von 8 Spalten und 7 Zeilen in ein 7x7-Bereich. Ich habe es schon mit setVisible und pack() probiert, aber das hilft mir leider auch nicht. Beim Debuggen behauptet er aber weiterhin, dass sein layout 8 spalten hätte.

Hier mal der Quelltext, vielleicht weiß ja jemand, woran es liegt. Die entsprechende Methode ist
Code:
einzeichnenLabels()

Java:
public class Kalender extends javax.swing.JPanel 
{

    private JLabel[] tage = new JLabel[56];
    private int maxLabels = -1;
    private GridLayout gL = new GridLayout(7,8);
    /**
     * Creates new form Kalender
     */
    public Kalender() {
        initComponents();
        fuellenJahresauswahl();
        palTage.setLayout(gL);
        Calendar c = Calendar.getInstance();
        cboMonat.setSelectedIndex(c.get(Calendar.MONTH));
        cboJahr.setSelectedItem(String.valueOf(c.get(Calendar.YEAR)));
        fuellenKalender();
    }
    
    private void einzeichnenLabels()
    {
        palTage.setVisible(false);
        palTage.removeAll();
        palTage.setLayout(gL);
        palTage.setVisible(true);
        for(int i=0; i <= maxLabels; i++)
        {
            tage[i].setHorizontalAlignment(JLabel.CENTER);
            palTage.add(tage[i]);
        }
        palTage.setVisible(true);
    }
    
    private void fuellenJahresauswahl()
    {
        cboJahr.removeAllItems();
        for(int i = 1900; i < 2100; i++)
        {
            cboJahr.addItem(String.valueOf(i));
        }
    }
    
    private void fuellenKalender()
    {
        tage = new JLabel[56];
        fuellenUeberschriften();
        fuellenTage();
        einzeichnenLabels();
        palTage.repaint();
    }
    
    private void fuellenUeberschriften()
    {
        tage[0] = new JLabel("");
        tage[1] = new JLabel("Mo");
        tage[2] = new JLabel("Di");
        tage[3] = new JLabel("Mi");
        tage[4] = new JLabel("Do");
        tage[5] = new JLabel("Fr");
        tage[6] = new JLabel("Sa");
        tage[7] = new JLabel("So");
    }
    
    private void fuellenTage()
    {
        //Der erste des ausgewählten Monats
        Calendar c = Calendar.getInstance();
        c.set(Integer.parseInt(cboJahr.getSelectedItem().toString()), cboMonat.getSelectedIndex(), 1);
        c.get(Calendar.DATE); 
        c.get(Calendar.MONTH);
        c.get(Calendar.YEAR);
        
        int zaehler = 9; // der erste Tag im Monat, der eingetragen werden kann
        zaehler = zaehler + wochentag(c.get(Calendar.DAY_OF_WEEK));
        for(int i = 8; i <= 56; i++)
        {
            //Soll eine Woche eingetragen werden oder ein Tag?
            if(i % 8 == 0)
            {
                tage[i] = new JLabel(String.valueOf(c.get(Calendar.WEEK_OF_YEAR)));
            }else{
                if(i < zaehler)
                {
                    tage[i] = new JLabel("");
                }else{
                    tage[i] = new JLabel(String.valueOf(c.get(Calendar.DAY_OF_MONTH)));
                    c.add(Calendar.DAY_OF_MONTH, 1);
                }
            }
            //Wenn der Monat sich geändert hat, abbrechen
            if(c.get(Calendar.MONTH) != cboMonat.getSelectedIndex())
            {
                maxLabels = i;
                break;
            }
        }
    }
    
    private int wochentag(int dayOfWeek)
    {
        switch(dayOfWeek)
        {
            case Calendar.MONDAY   : return 0;
            case Calendar.TUESDAY  : return 1;  
            case Calendar.WEDNESDAY: return 2;
            case Calendar.THURSDAY : return 3;
            case Calendar.FRIDAY   : return 4;  
            case Calendar.SATURDAY : return 5;
            case Calendar.SUNDAY   : return 6;   
            default: return 0;
        }
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        palAuswahl = new javax.swing.JPanel();
        cboMonat = new javax.swing.JComboBox();
        cboJahr = new javax.swing.JComboBox();
        palTage = new javax.swing.JPanel();

        setLayout(new java.awt.BorderLayout());

        palAuswahl.setPreferredSize(new java.awt.Dimension(526, 30));
        palAuswahl.setLayout(new java.awt.GridLayout(1, 2));

        cboMonat.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
        cboMonat.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" }));
        cboMonat.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cboMonatActionPerformed(evt);
            }
        });
        palAuswahl.add(cboMonat);

        cboJahr.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
        cboJahr.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cboJahrActionPerformed(evt);
            }
        });
        palAuswahl.add(cboJahr);

        add(palAuswahl, java.awt.BorderLayout.PAGE_START);

        palTage.setLayout(new java.awt.GridLayout());
        add(palTage, java.awt.BorderLayout.CENTER);
    }// </editor-fold>                        

    private void cboMonatActionPerformed(java.awt.event.ActionEvent evt) {                                         
        fuellenKalender();
    }                                        

    private void cboJahrActionPerformed(java.awt.event.ActionEvent evt) {                                        
        fuellenKalender();
    }                                       
                
    private javax.swing.JComboBox cboJahr;
    private javax.swing.JComboBox cboMonat;
    private javax.swing.JPanel palAuswahl;
    private javax.swing.JPanel palTage;              
}

(Ich habe die NetBeans-Swing-Oberfläche dafür genutzt)

Ich hoffe jemand kann mir dabei helfen

Mit freundlichen Grüßen
Svenja
 
Liegt am nicht sofort verständlichen Verhalten des GridLayout bzw. daran, dass je nach Monat unterschiedlich viele JLabels hinzugefügt werden.

Eine Möglichkeit:
[JAVA=6]private GridLayout gL = new GridLayout(7,8);[/code]
ändern in:
[JAVA=6]private GridLayout gL = new GridLayout(0,8);[/code]
 
Danke für die Antwort. Leider hat das nicht geholfen. Das führt nun dazu, dass 9 Felder angezeigt werden: Die Überschriftenfelder (8) und die erste Kalenderwoche (1). Selbst das ist ja noch falsch: Hier sollten nur 8 angezeigt werden, oder?
Ich habe auch versucht, das Grid dynamisch beim hochzählen der Wochen zu erweitern, allerdings erfolglos.

Gibt es eine andere Möglichkeit?

lg
 
das Layout reagiert immer gleich, hättest du am Anfang einen anderen Startmonat, dann sieht es genauso aus,
nur der Juli weicht zufällig ab, September 2013 ist aber z.B. auch so

das Layout füllt lieber Reihen statt Spalten, wenn du nur 7 Einträge hättest, würden alle untereinander stehen, statt in der ersten Zeile nebeneinander,
die meisten Monate haben zuwenig Einträge, fülle z.B. am Ende mit leeren JLabel auf, dann gehts

testweise etwa
Java:
        while (maxLabels < 50) {
           maxLabels++;
           tage[maxLabels] = new JLabel("");
        }

auf setVisible(false/true) verzichte lieber, stattdessen reicht ein validate() vor dem repaint() nach Änderung der Komponenten,

--------

noch besser:
generell solltest du nicht ständig neue JLabel erzeugen, das ist für sich unschön, mit neuberechneten Layout umso mehr,
erstelle von Anfang an 7x8 JLabel, dann hättest du mit dem Layout überhaupt keine Probleme mehr nachdem es einmal funktioniert,
das obige inklusive meiner Schleife könnte wegfallen,

die Wochentage musst du auch nicht mehr ständig neu befüllen, nur die restlichen JLabel alle durcharbeiten,
mit setText() entweder neue Zahl oder Leerstring "" setzen,
setVisible, validate und repaint sind dann alle unnötig
 
Zuletzt bearbeitet von einem Moderator:
Anmerkungen von SlaterB kann ich natürlich nur unterschreiben. Trotzdem würde mich interssieren, wie man in einem Container mit
Code:
GridLayout(0,8)
9 Spalten (ist vermutlich mit Feldern gemeint) angezeigt bekommt.
 
Vielen Dank euch beiden!

Die Kombination aus beidem machts. Wenn ich die Objekte zu Beginn alle bereits erstelle, funktioniert es auch nur, wenn man das layout auf (0,8) setzt. Bei (7,8) verwirft er es weiterhin.
Jetzt ist aber alles an der richtigen Stelle und so wie es sein soll. Ist aber auch an sich eine gute Idee, es so zu machen, ich werde den Quelltext jetzt nochmal überarbeiten, dass es noch etwas schicker wird

@IMartin: Was ich meinte, waren sozusagen zwei Reihen und 8 Spalten. Er hat die erste reihe richtig gemacht, bei der zweiten hat er nach dem 1. Feld aufgehört. Das wundert mich eigentlich, warum er da so halbe sachen macht...
 
Aha, ok. Kann es zwar nicht nachstellen, aber solange es 8 Spalten sind, kann ich es verschmerzen 😉
 

Zurück
Oben