Java Seitenverhältnis einer Komponente festlegen

Seitenverhältnis einer Komponente festlegen

Es gibt Komponenten, die man nur in einem bestimmten, festen Seitenverhältnis anzeigen möchte, z. B. nur quaratisch (Seitenverhältnis 1:1).

Wenn man dies nicht über getMinimumsize und getMaximumSize auf eine feste Pixelzahl festlegen möchte, so helfen die LayoutManager des Java APIs nicht weiter.
Auf Veränderungen der Größe der Komponente mittels ComponentListener zu reagieren, wenn diese in einem Container mit LayoutManager eingebettet ist, ist keine gute Idee, da die Komponente dann anfängt zu flackern, wenn der LayoutManager die Größe ständig anders festlegen möchte.
Das einzige, was hier vernünftig weiterhilft, ist ein eigener, einfacher LayoutManager.

AspectLayout

Wir entwickeln einen einfachen LayoutManager, der genau eine Komponente aufnehmen kann und diese dann innerhalb des verfügbaren Platzes mit einem vorgegebenen Seitenverhältnis (zum Beispiel 1:1 für quadratisches Layout) so groß wie möglich darstellt.
So kann man eine Komponente mit festem Seitenverhältnis beispielsweise im CENTER-Bereich eines BorderLayouts so groß wie möglich darstellen, indem man in das BorderLayout einen eigenen Container legt, und diesem das AspectLayout und die darzustellende Komponente gibt.

Der Benutzer Marco13 im Java-Forum war so nett, eine einfache Implementierung zu veröffentlichen.
Diese wird hier, leicht gekürzt, wiedergegeben (das Original ist hier zu finden):


package [...];

import java.awt.*;

/**
 * An implementation of the LayoutManager interface, for containers
 * that contain a single component that should be as large as
 * possible under the constraint that a given aspect ratio
 * (width/height) is maintained.
 */
public class AspectLayout implements LayoutManager {
    /**
     * The current aspect that should be maintained (width/height)
     */
    private final float aspect;

    /**
     * The alignment in horizontal or vertical direction.
     * If there is extra space in either direction, then
     * the component will aligned according to this value
     */
    private final float alignment;

    /**
     * Creates a new AspectLayout.
     *
     * @param aspect The aspect for the contained component
     */
    public AspectLayout() {
        this(1.0f, 0.5f);
    }

    /**
     * Creates a new AspectLayout for the given aspect
     *
     * @param aspect The aspect for the contained component
     */
    public AspectLayout(final float aspect) {
        this(aspect, 0.5f);
    }

    /**
     * Creates a new AspectLayout for the given aspect and
     * alignment
     *
     * @param aspect The aspect for the contained component
     * @param alignment The alignment for the contained component
     */
    public AspectLayout(final float aspect, final float alignment) {
        this.aspect = aspect;
        this.alignment = alignment;
    }

    /**
     * {@inheritDoc}
     */
    public void addLayoutComponent(final String name, final Component comp) {
    }

    /**
     * {@inheritDoc}
     */
    public void layoutContainer(final Container parent) {
        synchronized (parent.getTreeLock()) {
            if (parent.getComponentCount() >= 0) {
                final Component component = parent.getComponent(0);
                final Insets insets = parent.getInsets();
                final int maxWidth1 = parent.getWidth() - (insets.left + insets.right);
                final int maxHeight1 = parent.getHeight() - (insets.top + insets.bottom);
                final int maxWidth2 = (int)(aspect * maxHeight1);
                final int maxHeight2 = (int)((float)maxWidth1 / aspect);
                final int newWidth = Math.min(maxWidth1, maxWidth2);
                final int newHeight = Math.min(maxHeight1, maxHeight2);
                final int hGap = (int)(alignment * (parent.getWidth() - newWidth));
                final int vGap = (int)(alignment * (parent.getHeight() - newHeight));
                component.setBounds(hGap, vGap, newWidth, newHeight);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public Dimension minimumLayoutSize(final Container parent) {
        if (parent.getComponentCount() == 0) {
            return new Dimension(0,0);
        } else {
            return parent.getComponent(0).getMinimumSize();
        }
    }

    /**
     * {@inheritDoc}
     */
    public Dimension preferredLayoutSize(final Container parent) {
        if (parent.getComponentCount() == 0) {
            return new Dimension(0,0);
        } else {
            return parent.getComponent(0).getPreferredSize();
        }
    }

    /**
     * {@inheritDoc}
     */
    public void removeLayoutComponent(final Component comp) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return getClass().getName() + "[aspect=" + aspect + "]";
    }
}



Nach oben, Inhaltsverzeichnis, Impressum Admin: Artikel editieren