Discussion:
JFrame - Größe an Komponente anpassen
(zu alt für eine Antwort)
Roland Budischin
2005-07-25 12:15:12 UTC
Permalink
Hi,
ich habe einen JFrame, in den ich mittels BorderLayout.Center ein JPanel
einfüge, (welches eine
Grafik beinhaltet, nur so nebenbei).
Ich möchte, dass sich die Größe des Frames automatisch anpasst, wenn sich
das JPanel geändert hat.
Nun hab ich die paint-Methode von JFrame so überschrieben:

public void paint(Graphics g) {
// Werte für Rahmen mit einberechnen
int it = this.getInsets().top;
int il = this.getInsets().left;
int ir = this.getInsets().right;
int ib = this.getInsets().bottom;
// die aktuelle Größe des Bildes (im JPanel)
Dimension d = ic.getImageSize();
int w = (int)d.getWidth()+il+ir;
int h = (int)d.getHeight()+it+ib;
// Bildkomponente neu zeichnen, muss ausgeführt werden, ansonsten
ist nach Minimierung/Wiederherstellung nix mehr zu //sehen
ic.repaint();
// Framegröße anpassen
this.setSize(w, h);
this.validate();
this.setLocationRelativeTo(null);
}

Das Ganze funktioniert, ich hätte aber gern gewusst,
ob man das ganze nicht noch optimieren kann,

mfg, Roland
Roland Budischin
2005-07-25 13:46:23 UTC
Permalink
Ok,
nachdem ich überlegt habe, warum ich ic.repaint() aufrufen muss,
half ein kurzer Blick in die API :-) :
es sollte immer super.paint(g) aufgerufen werden, damit innere Komponenten
neu gezeichnet werden.
Post by Roland Budischin
Hi,
ich habe einen JFrame, in den ich mittels BorderLayout.Center ein JPanel
einfüge, (welches eine
Grafik beinhaltet, nur so nebenbei).
Ich möchte, dass sich die Größe des Frames automatisch anpasst, wenn sich
das JPanel geändert hat.
public void paint(Graphics g) {
// Werte für Rahmen mit einberechnen
int it = this.getInsets().top;
int il = this.getInsets().left;
int ir = this.getInsets().right;
int ib = this.getInsets().bottom;
// die aktuelle Größe des Bildes (im JPanel)
Dimension d = ic.getImageSize();
int w = (int)d.getWidth()+il+ir;
int h = (int)d.getHeight()+it+ib;
// Bildkomponente neu zeichnen, muss ausgeführt werden, ansonsten
ist nach Minimierung/Wiederherstellung nix mehr zu //sehen
ic.repaint();
// Framegröße anpassen
this.setSize(w, h);
this.validate();
this.setLocationRelativeTo(null);
}
Das Ganze funktioniert, ich hätte aber gern gewusst,
ob man das ganze nicht noch optimieren kann,
mfg, Roland
Michael Paap
2005-07-25 21:41:58 UTC
Permalink
Post by Roland Budischin
ich habe einen JFrame, in den ich mittels BorderLayout.Center ein JPanel
einfüge, (welches eine Grafik beinhaltet, nur so nebenbei).
Ich möchte, dass sich die Größe des Frames automatisch anpasst, wenn sich
das JPanel geändert hat.
Uijeh. Überschreibe einfach die Methode getPreferredSize() deines
JPanels so, dass sie die Größe der Grafik einbezieht und rufe nach
Änderungen des JPanels pack() auf dem JFrame auf.
Post by Roland Budischin
Das Ganze funktioniert, ich hätte aber gern gewusst,
ob man das ganze nicht noch optimieren kann,
Siehe oben.

Gruß,
Michael
--
Die Adresse im From existiert, wird aber nicht gelesen. Sollte
eine Mail-Antwort auf ein Posting vonnöten sein, bitte folgende
Adresse verwenden: newsreply@<DOMAIN_AUS_DEM_FROM_DIESES_POSTINGS>.
Roland Budischin
2005-07-26 08:04:55 UTC
Permalink
Hallo Michael,

danke für deine Antwort,
funktioniert wunderbar,

Gruß, Roland
Post by Michael Paap
Post by Roland Budischin
ich habe einen JFrame, in den ich mittels BorderLayout.Center ein JPanel
einfüge, (welches eine Grafik beinhaltet, nur so nebenbei).
Ich möchte, dass sich die Größe des Frames automatisch anpasst, wenn sich
das JPanel geändert hat.
Uijeh. Überschreibe einfach die Methode getPreferredSize() deines
JPanels so, dass sie die Größe der Grafik einbezieht und rufe nach
Änderungen des JPanels pack() auf dem JFrame auf.
Post by Roland Budischin
Das Ganze funktioniert, ich hätte aber gern gewusst,
ob man das ganze nicht noch optimieren kann,
Siehe oben.
Gruß,
Michael
--
Die Adresse im From existiert, wird aber nicht gelesen. Sollte
eine Mail-Antwort auf ein Posting vonnöten sein, bitte folgende
Wanja Gayk
2005-07-26 01:33:50 UTC
Permalink
Roland Budischin said...
Post by Roland Budischin
Hi,
ich habe einen JFrame, in den ich mittels BorderLayout.Center ein JPanel
einfüge, (welches eine
Grafik beinhaltet, nur so nebenbei).
Ich möchte, dass sich die Größe des Frames automatisch anpasst, wenn sich
das JPanel geändert hat.
public void paint(Graphics g) {
// Werte für Rahmen mit einberechnen
int it = this.getInsets().top;
int il = this.getInsets().left;
int ir = this.getInsets().right;
int ib = this.getInsets().bottom;
// die aktuelle Größe des Bildes (im JPanel)
Dimension d = ic.getImageSize();
int w = (int)d.getWidth()+il+ir;
int h = (int)d.getHeight()+it+ib;
// Bildkomponente neu zeichnen, muss ausgeführt werden, ansonsten
ist nach Minimierung/Wiederherstellung nix mehr zu //sehen
ic.repaint();
// Framegröße anpassen
this.setSize(w, h);
this.validate();
this.setLocationRelativeTo(null);
}
Das Ganze funktioniert, ich hätte aber gern gewusst,
ob man das ganze nicht noch optimieren kann,
1. Was Swing angeht, überschreibt man am besten nicht paint(Graphics g)
sondern paintComponent(Graphics g)
2. super.paintComponent(g) sollte mal als erstes ausfüren.
3. Ich würde den Frame wirklich nur als Container für JPanels nehmen,
statt von ihm abzuleiten, das macht dei Sache flexibler, weil du deine
Oberfläche nicht nur als JFrame benutzen kannst, sondern beliebig in
anderen Layouts einbinden kannst.
4. Ich verwedne für Bilder eine eigene Komponente, deren Größe ich an
die Bildgröße anpasse, ich überschreibe dafür *nicht* getPreferredSize
(), wie hier vorgeschlagen wurde, sondern ich setze diese nur im
Konstruktor und skaliere das Bild auf die Größe der Komponente.

Ein Beispiel folgt:

(ich entschuldige mich für die schlechte Formatierung, ist einfach
Copy/Paste aus meiner IDE)


* Created on 24.07.2005
*/
package imaging;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;

import javax.swing.JComponent;

/**
* A {@link JComponent} that shows an {@link Image}.<BR>
* The image will allways fill the ImagePanel's
* {@link JComponent#getBounds(java.awt.Rectangle) bounds}.
* By default the ImagePanel's
* {@link JComponent#getPreferredSize() size} will be
* {@link java.awt.Component#setSize(java.awt.Dimension) set} to
* the Image's
* {@link Image#getWidth(java.awt.image.ImageObserver) size}.
* By default the ImagePanel itself will be non-opaque
* ({@link JComponent#setOpaque(boolean) setOpaque(false)})<BR>
* @author Wanja Gayk
*/
public class ImageComponent extends JComponent {

private static final long serialVersionUID = 2448362363184581L;

private final Image image;

/**
* Creates a new {@link ImageComponent} object.<BR>
* The created {@link ImageComponent} will have the given
* {@link Image image's}
* {@link JComponent#getPreferredSize() preferred size}.<BR>
* The {@link ImageComponent} itself will be non-opaque
* ({@link JComponent#setOpaque(boolean) setOpaque(false)})<BR>
* @param image the {@link Image} to display.
* @throws IllegalArgumentException if the
* passed {@link Image} is null;
*/
public ImageComponent(final Image image) {
if(image == null){
throw new IllegalArgumentException("Image must not be
null");}
this.image = image;
setOpaque(false);
final Dimension imageSize = new Dimension(image.getWidth
(this), image.getHeight(this));
setPreferredSize(imageSize);
setSize(imageSize);
}

@Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}

}


Anwendung der Komponente:

class Demo{
public static void main(final String[] args){
final MediaTracker tracker = new MediaTracker(new JPanel());
final Image image =
Toolkit.getDefaultToolkit().getImage(
getClass().getResource("image.png"));
tracker.addImage(image , 0);
try {
tracker.waitForAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
final ImageComponent imageComp = new ImageComponent(image);

final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBackground(Color.black);
frame.setContentPane(imageComp);
frame.pack();
frame.setVisible(true);
}
}

Gruß,
-Wanja-
--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
Kommentar, meine Geschichte'. [..] Es wäre besser, wenn sie sagten:
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]
Roland Budischin
2005-07-26 07:56:04 UTC
Permalink
Hallo Wanja,

Dein Beispiel funzt wunderbar,
musste allerdings ne Kleinigkeit anpassen:

final Image image = Toolkit.getDefaultToolkit().getImage(
Demo.class.getResource("image.png"));

getClass() wollte in der main-Methode nicht so richtig ;-)

Wenn ich das richtig verstanden habe,
dann braucht man die Größe des Frames nicht explizit setzen, sondern
einfach pack() aufrufen, welche sich die Größe von ImageComponent holt ?

Gruß, Roland
Post by Wanja Gayk
Roland Budischin said...
Post by Roland Budischin
Hi,
ich habe einen JFrame, in den ich mittels BorderLayout.Center ein JPanel
einfüge, (welches eine
Grafik beinhaltet, nur so nebenbei).
Ich möchte, dass sich die Größe des Frames automatisch anpasst, wenn sich
das JPanel geändert hat.
public void paint(Graphics g) {
// Werte für Rahmen mit einberechnen
int it = this.getInsets().top;
int il = this.getInsets().left;
int ir = this.getInsets().right;
int ib = this.getInsets().bottom;
// die aktuelle Größe des Bildes (im JPanel)
Dimension d = ic.getImageSize();
int w = (int)d.getWidth()+il+ir;
int h = (int)d.getHeight()+it+ib;
// Bildkomponente neu zeichnen, muss ausgeführt werden, ansonsten
ist nach Minimierung/Wiederherstellung nix mehr zu //sehen
ic.repaint();
// Framegröße anpassen
this.setSize(w, h);
this.validate();
this.setLocationRelativeTo(null);
}
Das Ganze funktioniert, ich hätte aber gern gewusst,
ob man das ganze nicht noch optimieren kann,
1. Was Swing angeht, überschreibt man am besten nicht paint(Graphics g)
sondern paintComponent(Graphics g)
2. super.paintComponent(g) sollte mal als erstes ausfüren.
3. Ich würde den Frame wirklich nur als Container für JPanels nehmen,
statt von ihm abzuleiten, das macht dei Sache flexibler, weil du deine
Oberfläche nicht nur als JFrame benutzen kannst, sondern beliebig in
anderen Layouts einbinden kannst.
4. Ich verwedne für Bilder eine eigene Komponente, deren Größe ich an
die Bildgröße anpasse, ich überschreibe dafür *nicht* getPreferredSize
(), wie hier vorgeschlagen wurde, sondern ich setze diese nur im
Konstruktor und skaliere das Bild auf die Größe der Komponente.
(ich entschuldige mich für die schlechte Formatierung, ist einfach
Copy/Paste aus meiner IDE)
* Created on 24.07.2005
*/
package imaging;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JComponent;
/**
* The image will allways fill the ImagePanel's
* By default the ImagePanel's
* the Image's
* By default the ImagePanel itself will be non-opaque
*/
public class ImageComponent extends JComponent {
private static final long serialVersionUID = 2448362363184581L;
private final Image image;
/**
*/
public ImageComponent(final Image image) {
if(image == null){
throw new IllegalArgumentException("Image must not be
null");}
this.image = image;
setOpaque(false);
final Dimension imageSize = new Dimension(image.getWidth
(this), image.getHeight(this));
setPreferredSize(imageSize);
setSize(imageSize);
}
@Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
}
class Demo{
public static void main(final String[] args){
final MediaTracker tracker = new MediaTracker(new JPanel());
final Image image =
Toolkit.getDefaultToolkit().getImage(
getClass().getResource("image.png"));
tracker.addImage(image , 0);
try {
tracker.waitForAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
final ImageComponent imageComp = new ImageComponent(image);
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBackground(Color.black);
frame.setContentPane(imageComp);
frame.pack();
frame.setVisible(true);
}
}
Gruß,
-Wanja-
--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]
Wanja Gayk
2005-07-26 08:48:50 UTC
Permalink
Roland Budischin said...
Post by Roland Budischin
Hallo Wanja,
Dein Beispiel funzt wunderbar,
final Image image = Toolkit.getDefaultToolkit().getImage(
Demo.class.getResource("image.png"));
getClass() wollte in der main-Methode nicht so richtig ;-)
Erm.. ja.. das war ein Fehler von mir, habe den Code stumpf aus dem
Konstruktor einer meiner Klassen kopiert, da kommt sowas mal vor.
Post by Roland Budischin
Wenn ich das richtig verstanden habe,
dann braucht man die Größe des Frames nicht explizit setzen, sondern
einfach pack() aufrufen, welche sich die Größe von ImageComponent holt ?
Genau.
Die Größe des Frames versucht sich mit Frame#pack nach der Größe des
Inhalts zu richten.

Jede Komponmente hat eine preferredSize, und sie hat ggf eine eine
maximumSize und eine minimumSize. Die meisten Layoutmanager versuchen
die preferredSize irgendwie zu beachten, der Default-Layoutmanager von
Panels und contentPanes ist das FlowLayout, siehe:
http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html

Der Vorteil der geposteten Klasse:
Wenn du nachträglich die Größe änderst, so ziehst du das Bild auf die
Größe des Panels. In dem geposteten Beispiel versuch z.B. mal die Größe
des Frames mit der Mouse zu ändern..

Gruß,
-Wanja-
--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
Kommentar, meine Geschichte'. [..] Es wäre besser, wenn sie sagten:
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]
Loading...