# Dynamisches Ändern der Größe in JPanel mit paint()-Methode



## lorion42 (10. Sep 2008)

Hallo,
erstmal ärgerlich, dass ich nicht Pain(t) im Titel benutzen darf :lol:
ich will dynamisch Informationen zu bestimmten Inhalten erzeugen. Das Fenster soll dabei eine passende Größe haben. Ist der Inhalt in keiner paint Methode und besteht nur aus JLabels, ist dies ganz einfach:

```
informationFrame = new JFrame("Informationen");
        JPanel information = new InformationPanel();
        informationFrame.add(information);
        informationFrame.setVisible(true);
        informationFrame.pack();
```

Nun habe ich das InformationPanel ein wenig geändert und es hat besagte Paint-Methode. Der Paint Teil hat aber keine spezifische Größe, weswegen ich mir versucht hab mit ein paar Variablen zu helfen:


```
public class InformationPanel extends JPanel {

    @Override
    public void paint(Graphics g) {
        super.paintComponent(g);
        int width = 0;
        int height = 0;
        if (this.connection == null) {
            String displayString = "keine Informationen vorhanden";
            g.drawString(displayString, 5, 15);
            width += fontMetrics.stringWidth(displayString) + 5;
            height += fontMetrics.getHeight() + 15;
        }
        this.setSize(new Dimension(width, height));
    }
```

Der Teil mit den FontMetrics hat jetzt erstmal keine Bedeutung und soll nur ein Beispiel sein, wie sich die Fenstergröße dynamisch ändern könnte. Das Wichtige ist das setSize, denn das funktioniert nicht so, wie ich das möchte - bzw es hat gar keine Auswirkung. Hat jemand eine Ahnung, was man hier machen kann? Ich versuch schon wie ein verrückter repaint oder revalidate aufzurufen, aber es hat keine Auswirkungen.
Ich hoffe ihr versteht mein Problem


----------



## Wildcard (10. Sep 2008)

Erstmal: überschreib nicht paint, sondern paintComponent
Aber das wichtigste: eine paint Methode darf keinen Zustand verändern. Welches Problem willst du denn lösen, da gibt es sicher einen anderen Weg.


----------



## lorion42 (10. Sep 2008)

das war auch nur die erste Idee... ich will, dass die Fenstergröße abhängig von dem Teil ist, der in paintComponent (paint geht auch, ist aber weniger schön, aber in diesem Beispiel egal) berechnet wird.
Einzige Alternative, die mir einfällt, ist dass ich die Berechnung noch ein zweites Mal in einer anderen Methode durchführe, die nur ausrechnet, wie groß das Fenster sein müsste, um alles darzustellen, was in der paintMethode erschaffen wird... das finde ich aber sehr unschön... kennt jemand eine Alternative?


----------



## Wildcard (10. Sep 2008)

Ein Beispiel aus der BasicLabelUI die die Größe eines JLabels berechnet:

```
public Dimension getPreferredSize(JComponent c) 
    {
        JLabel label = (JLabel)c;
        String text = label.getText();
        Icon icon = (label.isEnabled()) ? label.getIcon() :
                                          label.getDisabledIcon();
        Insets insets = label.getInsets(viewInsets);
        Font font = label.getFont();

        int dx = insets.left + insets.right;
        int dy = insets.top + insets.bottom;

        if ((icon == null) && 
            ((text == null) || 
             ((text != null) && (font == null)))) {
            return new Dimension(dx, dy);
        }
        else if ((text == null) || ((icon != null) && (font == null))) {
            return new Dimension(icon.getIconWidth() + dx, 
                                 icon.getIconHeight() + dy);
        }
        else {
            FontMetrics fm = label.getFontMetrics(font);

            iconR.x = iconR.y = iconR.width = iconR.height = 0;
            textR.x = textR.y = textR.width = textR.height = 0;
            viewR.x = dx;
            viewR.y = dy;
            viewR.width = viewR.height = Short.MAX_VALUE;

            layoutCL(label, fm, text, icon, viewR, iconR, textR);
            int x1 = Math.min(iconR.x, textR.x);
            int x2 = Math.max(iconR.x + iconR.width, textR.x + textR.width);
            int y1 = Math.min(iconR.y, textR.y);
            int y2 = Math.max(iconR.y + iconR.height, textR.y + textR.height);
            Dimension rv = new Dimension(x2 - x1, y2 - y1);

            rv.width += dx;
            rv.height += dy;
            return rv;
        }
    }
```
Dein JPanel sollte also getPreferredSize überschreiben so das es einen sinnvollen Wert zurückliefert. Ändert sich nun die Datenbasis die du zeichnen möchtest, rufst du einfach revalidate auf und der LayoutManager wird deine überschrieben getPreferredSize Methode konsultieren.


----------



## lorion42 (10. Sep 2008)

Das ist schonmal ganz praktisch... aber eigentlich geht es mir nicht um JLabel... das hab ich da nur eingefügt, damit das Beispiel nicht so aufgebläht wirkt... eigentlich bastel ich eine Visualisierung für einen Graphen
also auf die paintComponent Methode werd ich nicht verzichten können...
ich mach es jetzt einfach mit einer Standartgröße und einer JScrollBar drum herum - anscheinend kann man die Größe von etwas Gezeichnetem nicht so leicht bestimmen...


----------



## Wildcard (10. Sep 2008)

Das label sollte doch auch nur ein Beispiel sein. Deshalb sagte ich auch du sollst die getPreferredSize Methode sinnvoll ausfüllen.
Angenommen du möchtest eine Liste von Shapes zeichnen.
Dann gehst du in einer Schleife über deine Liste, holst dir die Bounds des ersten, addest die des zweiten hinzu, die des dritten und so weiter. Am ende hast du die BoundingBox die deiner benötigten Größe entspricht.


----------



## AlexDozer (10. Sep 2008)

lorion42 hat gesagt.:
			
		

> Hallo,
> erstmal ärgerlich, dass ich nicht Pain(t) im Titel benutzen darf :lol:




Wieso eigentlich?

Gruß Alex


----------



## Wildcard (10. Sep 2008)

Ungeschicktes Blacklist Script aus Spamschutzgründen. Wird mit der neuen Software hoffentlich besser.


----------



## lorion42 (11. Sep 2008)

Ah ok, ich hab's verstanden... danke


----------

