Komponenten werden nicht angezeigt

Status
Nicht offen für weitere Antworten.

marasek

Aktives Mitglied
Ich bin jetzt schon mehrfach über ein Verhalten von Java gestolpert: wenn man bei einer Komponente setLayout(null) macht und dann die Position nicht mit setBounds() u. ä. angibt, wird sie nicht angezeigt. Das Verhalten find ich gaga, ich würde erwarten, dass es entweder eine Fehlermeldung gibt oder die Komponente mit Standardwerten angezeigt wird. So kann ja fröhliches Bugsuchen beginnen - die Komponente könnte ja ebenso gut nicht angezeigt werden, weil man irgendwo eine falsche Kondition drin hat usw. usf.

Fast noch schlimmer als (null), wie seht ihr das?
 
Ich bin jetzt schon mehrfach über ein Verhalten von Java gestolpert: wenn man bei einer Komponente setLayout(null) macht und dann die Position nicht mit setBounds() u. ä. angibt, wird sie nicht angezeigt. Das Verhalten find ich gaga, ich würde erwarten, dass es entweder eine Fehlermeldung gibt oder die Komponente mit Standardwerten angezeigt wird. So kann ja fröhliches Bugsuchen beginnen - die Komponente könnte ja ebenso gut nicht angezeigt werden, weil man irgendwo eine falsche Kondition drin hat usw. usf.

Fast noch schlimmer als (null), wie seht ihr das?
Die Bounds, also die Position und Grösse einer Komponente, sind Sache des Layoutmanagers. Deshalb raten wir, immer einen solchen zu benutzen. Wenn wir absolute Positionierung benötigen, ist es oft besser einen Layoutmanager zu benutzen, der das macht und die PreferredSize respektiert, anstatt keinen Layoutmanager zu benutzen. Hier ist ein Beispiel eines solchen Layoutmanagers:
Code:
import java.awt.*;
import java.util.*;

public class AbsoluteLayout implements LayoutManager2 {

    protected Vector components = new Vector();

    public void addLayoutComponent(final String name, final Component component) {
        addLayoutComponent(component, null);
    }

    public void addLayoutComponent(final Component component, final Object constraints) {
        if (component == null) {
            return;
        }
        components.add(component);
    }

    public void removeLayoutComponent(final Component component) {
        if (component != null) {
            components.remove(component);
        }
    }

    public Dimension minimumLayoutSize(final Container parent) {
        return preferredLayoutSize(parent);
    }

    public Dimension preferredLayoutSize(final Container parent) {
        Rectangle limits = null;
        Rectangle bounds = null;
        for (int i = 0; i < components.size(); i++) {
            Component c = (Component) components.get(i);
            bounds = getPreferredBounds(c);
            if (limits == null) {
                limits = bounds;
            } else {
                limits = limits.union(bounds);
            }
        }
        if (limits == null) {
            return new Dimension();
        }
        Insets insets = parent.getInsets();
        if (insets == null) {
            insets = new Insets(0, 0, 0, 0);
        }
        int w = limits.width + insets.left + insets.right;
        int h = limits.height + insets.top + insets.bottom;
        return new Dimension(w, h);
    }

    public Dimension maximumLayoutSize(final Container parent) {
        return preferredLayoutSize(parent);
    }

    public void layoutContainer(final Container parent) {
        Insets insets = parent.getInsets();
        if (insets == null) {
            insets = new Insets(0, 0, 0, 0);
        }
        int a = insets.left;
        int b = insets.top;
        for (int i = 0; i < components.size(); i++) {
            Component c = (Component) components.get(i);
            if (c == null) {
                continue;
            }
            Rectangle bounds = getPreferredBounds(c);
            bounds.x += a;
            bounds.y += b;
            c.setBounds(bounds);
        }
    }

    public float getLayoutAlignmentY(final Container target) {
        return 0.5f;
    }

    public float getLayoutAlignmentX(final Container target) {
        return 0.5f;
    }

    public void invalidateLayout(final Container parent) {
        parent.repaint();
    }

    public static Rectangle getPreferredBounds(final Component c) {
        if (c == null) {
            return new Rectangle();
        }
        Point corner = c.getLocation();
        Rectangle bounds = c.getBounds();
        bounds.x = corner.x;
        bounds.y = corner.y;
        Dimension d;
        Dimension e;
        if (c instanceof Container) {
            Container x = (Container) c;
            d = x.getPreferredSize();
            bounds.width = d.width;
            bounds.height = d.height;
        } else {
            d = c.getMinimumSize();
            e = c.getSize();
            bounds.width = Math.max(d.width, e.width);
            bounds.height = Math.max(d.height, e.height);
        }
        return bounds;
    }
}
Mehr über Layoutmanager finden wir hier:
http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html
 
Ich bin jetzt schon mehrfach über ein Verhalten von Java gestolpert: wenn man bei einer Komponente setLayout(null) macht und dann die Position nicht mit setBounds() u. ä. angibt, wird sie nicht angezeigt. Das Verhalten find ich gaga, ich würde erwarten, dass es entweder eine Fehlermeldung gibt oder die Komponente mit Standardwerten angezeigt wird. So kann ja fröhliches Bugsuchen beginnen - die Komponente könnte ja ebenso gut nicht angezeigt werden, weil man irgendwo eine falsche Kondition drin hat usw. usf.

Fast noch schlimmer als (null), wie seht ihr das?
vorsichtig mit dem "gaga". Nur weil etwas nicht deinen Vorstellungen entspricht, muss es nicht gleich falsch sein. Per Default haben die Componenten die Ausmaße (0,0,0,0). Einige haben zwar PreferredSize gesetzt, aber das wird nur von LayoutManagern beachtet, die dann mit setSize die Endgröße bestimmen. Manchmal ist es erwünscht, dass aktive bzw. hinzugefügte Componenten die Ausmaße (X,Y,0,0) annehmen können, wenn diese z.B. temporär geschrumpft werden oder per Animation die Größe ändern. Ein Beispiel wäre JSplitPane, wo man eine Seite auf 100% vergrößern können soll. So wäre es eher falsch, wenn AWT/Swing für alle Sachen eine Mindestgröße vorgeben oder Exceptions werfen würde, den dann könnte man vielleicht nicht die gewünscht Funktionalität umsetzen.

Das man vielleicht wegen solchen Verhaltens Fehler nicht gleich merkt, ist eine Sache der Übung. Erstens sollte man fast immer einen LayoutManager verwenden, auch wenn man für seine Funktionalität selber einen schreiben muss. Wenn man keinen LayoutManager verwendet, sollte es schon seine Gründe haben und dann muss man sich damit gut auskennen. Ich hatte, nach dem ich AWT/Swing gelernt habe, damit jedenfalls keine Probleme gehabt. Irgendwann entwickelt man ein Gefühl woran es liegt, wenn der Bildschirm nicht so aussieht, wie geplant.

Slawa
 
Zuletzt bearbeitet:
Tja, wie soll ich sagen - den Faktor "Übung" versuche ich in meinen eigenen Sachen soweit als möglich auszuklammern. Ich habe früher mit Funktionen, Globalen und Arrays, die einer bestimmten Konvention folgen, programmiert. Das kann man recht gut kontrollieren, man hat ja Übung. Aber nicht zwei Jahre später, wenn man mal was abändern muss.

Ich bin da strikt - ganz oder gar nicht. Insofern finde ich es auch von Übel, dass man in Java straffrei jede Variable mit null befüllen kann.
 
Man kann sich aber auch -- anstatt sich zu beschweren -- mal mit Komponentenlayout in AWT/Swing auseinandersetzen. Außerdem hilft es schon, keine null-Layouts zu verwenden. Nicht umsonst wird null-Layout in jeder vernünftigen Quelle als absolute Ausnahme gehandhabt. Informationen zum Komponentlayout gibt's zum Beispiel im Sun Java Tutorial » Lesson: Laying Out Components Within a Container. Deine Erwartungen oben sind im übrigen weder durchdacht noch zweckführend.

EDIT: Huch, André Uhres hat schon sehr interessante Sachen oben geschrieben und wird vom Eingangsschreiberling sträflich misachtet... Dann hätte ich mir ja meinen Beitrag sparen können...

Ebenius
 
Man kann sich aber auch -- anstatt sich zu beschweren -- mal mit Komponentenlayout in AWT/Swing auseinandersetzen. Außerdem hilft es schon, keine null-Layouts zu verwenden. Nicht umsonst wird null-Layout in jeder vernünftigen Quelle als absolute Ausnahme gehandhabt. Informationen zum Komponentlayout gibt's zum Beispiel im Sun Java Tutorial » Lesson: Laying Out Components Within a Container. Deine Erwartungen oben sind im übrigen weder durchdacht noch zweckführend.

Ich habe eine Ansicht geäussert und um Kommentare gebeten und mich nicht nur einfach beschwert.
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben