Swing dynamisches Image-Panel in Layout einbinden

Loep

Aktives Mitglied
Hi!

Ich habe ein JPanel, das das anzuzeigende Image an die Größe des JPanel anpasst.
Das will ich nun im LINE_END eines BorderLayouts einbinden, aber das passt sich die Größe nicht mehr wie gewünscht an. Vermutlich liegt es an der PreferredSize des JPanel, aber ich konnte das Problem noch nicht lösen und stehe mittlerweile auf dem Schlauch.

Der Header soll wie im GridBagLayout angegeben 10% des Fensters belegen. Das Image soll sie maximale Höhe des Headers ausnutzen.
Der relevante Code beginnt wohl in der Methode createAndInitHeader() und geht dann über addContentTo(header) zu createAndInitHeaderlogo():
Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.LayoutManager;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class BorderLayoutDemo extends JFrame {
	private static final long serialVersionUID = 2863765494455240239L;

	private boolean SHOW_TEXT_INSTEAD_OF_LOGO = false;
	
	private Dimension startupSize = new Dimension(1024, 768);
	private GridBagConstraints c = new GridBagConstraints();
	
	private static JComponent imageWrapper; 
	private static ImageIcon image = new ImageIcon("images/rrc_logo.gif");
	
	public static void main(String[] args) {
		JFrame demoApp = new BorderLayoutDemo();
		demoApp.setVisible(true);
	}
	
	public BorderLayoutDemo() {
		initialize();
		addHeader();
		addContent();
		
		DynamicImagePanel dynImage = new DynamicImagePanel(image.getImage());
		JFrame imageOnly = new JFrame();
		imageOnly.add(dynImage);

		imageOnly.setSize(234, 100);
		imageOnly.setVisible(true);
		imageOnly.setDefaultCloseOperation(EXIT_ON_CLOSE);

	}
	
	private void initialize() {
		initializeFrame();
		initialzeLayoutContraints();
	}
	
	private void initializeFrame() {
		LayoutManager frameLayout = new GridBagLayout();
		setLayout(frameLayout);
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setSize(startupSize);
	}
	
	private void initialzeLayoutContraints() {
	}
	
	private void addHeader() {
		JPanel header = createAndInitHeader();
		c.gridx = 0;
		c.gridy = 0;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.weighty = 0.1;
		add(header, c);
	}

	private JPanel createAndInitHeader() {
		JPanel header = new JPanel(new BorderLayout());
		header.setBorder(BorderFactory.createEtchedBorder());
		addContentTo(header);
		return header;
	}

	private void addContentTo(JPanel container) {
		JPanel maincontent = createAndInitHeadertext();
		container.add(maincontent, BorderLayout.CENTER);
		JComponent logo = createAndInitHeaderlogo();
		container.add(logo, BorderLayout.LINE_END);
	}

	private JPanel createAndInitHeadertext() {
		int numberOfHeaderRows = 3;
		JPanel headertext = new JPanel(new GridLayout(0, 1));
		headertext.setBorder(BorderFactory.createTitledBorder("text"));
		for(int i=0; i<numberOfHeaderRows; i++) {
			addLabelTo(headertext, "header row", i);
		}
		return headertext;
	}
	
	private JPanel createAndInitHeaderlogo() {
		LayoutManager logolayout = new FlowLayout();
		JPanel container = new JPanel(logolayout);
		container.setBorder(BorderFactory.createTitledBorder("logo"));
		if(SHOW_TEXT_INSTEAD_OF_LOGO) {
			imageWrapper = new JLabel("Logo");
		} else {
			imageWrapper = new DynamicImagePanel(image.getImage());
		}
		imageWrapper.setBorder(BorderFactory.createEtchedBorder());
		container.add(imageWrapper);
		container.add(Box.createRigidArea(new Dimension(50, 0)));
		return container;
	}
	
	private void addContent() {
		JPanel content = createAndInitContent();
		c.gridx = 0;
		c.gridy = 1;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.weighty = 0.9;
		add(content, c);
	}
	
	private JPanel createAndInitContent() {
		int numberOfContentAreas = 2;
		JPanel container = new JPanel(new GridLayout(0, numberOfContentAreas));
		container.setBorder(BorderFactory.createTitledBorder("content"));
		for(int i=0; i<numberOfContentAreas; i++) {
			addLabelTo(container, "main content", i);
		}
		return container;
	}
	
	private void addLabelTo(JPanel container, String textprefix, int number) {
		JLabel row = new DynamicFontLabel(textprefix+ " "+ number);
		row.setHorizontalAlignment(JLabel.CENTER);
		row.setVerticalAlignment(JLabel.CENTER);
		row.setBorder(BorderFactory.createEtchedBorder());
		container.add(row);
	}
	
	public class DynamicFontLabel extends JLabel {
		private static final long serialVersionUID = 5037485673099026994L;
		private Insets margin = new Insets(0, 5, 0, 5);
		
		public DynamicFontLabel() {
			super();
		}

		public DynamicFontLabel(String string) {
			super(string);
		}

		@Override
		protected void paintComponent(Graphics g) {
			calcFont(g);
			super.paintComponent(g);
		}

		private void calcFont(Graphics g) {
			Insets insets = getInsets();
//			Insets margin = getMargin();	// just for a JButton
			int x = insets.left + margin.left;
			int y = insets.top + margin.top;
			// Breite und Höhe bestimmen
			Dimension size = getSize();
			int w = size.width - x - insets.right - margin.right;
			int h = size.height - y - insets.bottom - margin.bottom;
			Font font = g.getFont();
			String text = getText();
			FontMetrics fm = g.getFontMetrics(font);
			while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) {
				font = font.deriveFont(font.getSize2D() + 0.5f);
				fm = g.getFontMetrics(font);
			}
			g.setFont(font);
		}
		
	}

	class DynamicImagePanel extends JPanel {
		private static final long serialVersionUID = 1928634527591569084L;
		private Image background;

		public DynamicImagePanel(Image image) {
			background = image;
		}

		public void paintComponent(Graphics g) {
			int width = getWidth();
			int height = getHeight();
			g.drawImage(background, 0, 0, width, height, this);
			BorderLayoutDemo.imageWrapper.setPreferredSize(new Dimension(image.getIconWidth()+50, image.getIconHeight()));

		}
	}

}
 

Marco13

Top Contributor
Ja, ist etwas chaotisch (dort extends JFrame und erstellen eines neuen Frames und so)... aber mit das wichtigste dürfte sein: setPreferredSize NICHT in der paintComponent aufrufen. Einmal am Anfang, oder bei Größenänderungen des Frames (vielleicht mit einem ComponentListener). Da soll anscheinend sehr viel "dynamisch-automatisch angepasst" sein, da muss man aufpassen...
 

Loep

Aktives Mitglied
Ey, chaotisch?!? ;) Eigentlich sind alle JFrames extended. Das eine erstellte illustiert nur im separaten Fenster, dass das ImageResize eigenständig funktioniert.

Ich habe es jetzt mal über nen ComponentListener versucht. Das Seitenverhältnis der als Parameter verwendeten Dimension passt zum Seitenverhältnis des ursprünglichen ImageIcon. Aber nach setPreferredSize() stimmt das Seitenverhältnis nicht mit der Dimension überein...
Hab schon rumgetestet, aber noch nicht den richtigen Kniff gefunden. Wüsste auch nicht wie mich bei sowas der Debugger weiterhelfen könnte:
Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class BorderLayoutDemo extends JFrame implements ComponentListener {
	private static final long serialVersionUID = 2863765494455240239L;

	private boolean SHOW_TEXT_INSTEAD_OF_LOGO = false;
	
	private Dimension startupSize = new Dimension(1024, 768);
	private GridBagConstraints c = new GridBagConstraints();
	
	private static ImageIcon image = new ImageIcon("images/rrc_logo.gif");
	private JComponent logo;
//	private JPanel logoWrapper;
	private Dimension dynamicCalculatedImagesize;
	
	public static void main(String[] args) {
		JFrame demoApp = new BorderLayoutDemo();
		demoApp.setVisible(true);
	}
	
	public BorderLayoutDemo() {
		initialize();
		addHeader();
		addContent();
		
		DynamicImagePanel dynImage = new DynamicImagePanel(image.getImage());
		JFrame imageOnly = new JFrame();
		imageOnly.add(dynImage);

		imageOnly.setSize(234, 100);
		imageOnly.setVisible(true);
		imageOnly.setDefaultCloseOperation(EXIT_ON_CLOSE);

	}
	
	private void initialize() {
		initializeFrame();
		initialzeLayoutContraints();
	}
	
	private void initializeFrame() {
		LayoutManager frameLayout = new GridBagLayout();
		setLayout(frameLayout);
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setSize(startupSize);
		addComponentListener(this);
	}
	
	private void initialzeLayoutContraints() {
	}
	
	private void addHeader() {
		JPanel header = createAndInitHeader();
		c.gridx = 0;
		c.gridy = 0;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.weighty = 0.1;
		add(header, c);
	}

	private JPanel createAndInitHeader() {
		JPanel header = new JPanel(new BorderLayout());
		header.setBorder(BorderFactory.createEtchedBorder());
		addContentTo(header);
		return header;
	}

	private void addContentTo(JPanel container) {
		JPanel maincontent = createAndInitHeadertext();
		container.add(maincontent, BorderLayout.CENTER);
		JComponent logo = createAndInitHeaderlogo();
		container.add(logo, BorderLayout.LINE_END);
	}

	private JPanel createAndInitHeadertext() {
		int numberOfHeaderRows = 3;
		JPanel headertext = new JPanel(new GridLayout(0, 1));
		headertext.setBorder(BorderFactory.createTitledBorder("text"));
		for(int i=0; i<numberOfHeaderRows; i++) {
			addLabelTo(headertext, "header row", i);
		}
		return headertext;
	}
	
	private JComponent createAndInitHeaderlogo() {
//		LayoutManager logolayout = new BorderLayout();
//		logoWrapper = new JPanel(logolayout);
//		logoWrapper.setBorder(BorderFactory.createTitledBorder("logoWrapper"));
		if(SHOW_TEXT_INSTEAD_OF_LOGO) {
			logo = new JLabel("Logo");
		} else {
			logo = new DynamicImagePanel(image.getImage());
		}
		logo.setBorder(BorderFactory.createTitledBorder("logo"));
//		logoWrapper.add(logo, BorderLayout.CENTER);
//		logoWrapper.add(Box.createRigidArea(new Dimension(100, 0)), BorderLayout.LINE_END);
//		return logoWrapper;
		return logo;
	}
	
	private void addContent() {
		JPanel content = createAndInitContent();
		c.gridx = 0;
		c.gridy = 1;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.weighty = 0.9;
		add(content, c);
	}
	
	private JPanel createAndInitContent() {
		int numberOfContentAreas = 2;
		JPanel container = new JPanel(new GridLayout(0, numberOfContentAreas));
		container.setBorder(BorderFactory.createTitledBorder("content"));
		for(int i=0; i<numberOfContentAreas; i++) {
			addLabelTo(container, "main content", i);
		}
		return container;
	}
	
	private void addLabelTo(JPanel container, String textprefix, int number) {
		JLabel row = new DynamicFontLabel(textprefix+ " "+ number);
		row.setHorizontalAlignment(JLabel.CENTER);
		row.setVerticalAlignment(JLabel.CENTER);
		row.setBorder(BorderFactory.createEtchedBorder());
		container.add(row);
	}
	
	@Override
	public void componentResized(ComponentEvent e) {
		logo.setMinimumSize(dynamicCalculatedImagesize);
		logo.setPreferredSize(dynamicCalculatedImagesize);
//		logoWrapper.setPreferredSize(dynamicCalculatedImagesize);
		System.out.println("image: "+ (double)image.getIconWidth() / image.getIconHeight());
		System.out.println("dimension: "+ (double)dynamicCalculatedImagesize.getWidth() / dynamicCalculatedImagesize.getHeight());
		System.out.println("size: "+ (double)logo.getWidth()/logo.getHeight());
		System.out.println();
	}

	@Override
	public void componentHidden(ComponentEvent e) {
	}

	@Override
	public void componentMoved(ComponentEvent e) {
	}

	@Override
	public void componentShown(ComponentEvent e) {
	}

	public class DynamicFontLabel extends JLabel {
		private static final long serialVersionUID = 5037485673099026994L;
		private Insets margin = new Insets(0, 5, 0, 5);
		
		public DynamicFontLabel() {
			super();
		}

		public DynamicFontLabel(String string) {
			super(string);
		}

		@Override
		protected void paintComponent(Graphics g) {
			calcFont(g);
			super.paintComponent(g);
		}

		private void calcFont(Graphics g) {
			Insets insets = getInsets();
//			Insets margin = getMargin();	// just for a JButton
			int x = insets.left + margin.left;
			int y = insets.top + margin.top;
			// Breite und Höhe bestimmen
			Dimension size = getSize();
			int w = size.width - x - insets.right - margin.right;
			int h = size.height - y - insets.bottom - margin.bottom;
			Font font = g.getFont();
			String text = getText();
			FontMetrics fm = g.getFontMetrics(font);
			while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) {
				font = font.deriveFont(font.getSize2D() + 0.5f);
				fm = g.getFontMetrics(font);
			}
			g.setFont(font);
		}
		
	}

	class DynamicImagePanel extends JPanel {
		private static final long serialVersionUID = 1928634527591569084L;
		private Image background;

		public DynamicImagePanel(Image image) {
			background = image;
		}

		@Override
		public void paintComponent(Graphics g) {
			int originalImageHeight = image.getIconHeight();
			int originalImageWidth = image.getIconWidth();
			int newHeight = getHeight();
			double scaleFactor = (double)originalImageWidth / originalImageHeight;
			int newWidth = (int)Math.round(newHeight * scaleFactor);
			dynamicCalculatedImagesize = new Dimension(newWidth, newHeight);
			g.drawImage(background, 0, 0, newWidth, newHeight, this);
		}
	}

}

Edit: Ja, die Anzeige soll in allen Fenstergrößen den Platz optimal/maximal ausnutzen. Layout und Schrift sind ja schon synamisch, nur das Logo fehlt mir grad noch :(
 
Zuletzt bearbeitet:

Marco13

Top Contributor
So ganz klar ist es noch nicht. Wenn das Bild 100x100 groß ist, und der Header (weil das Fenster eine Höhe von ~500 hat) nur 50 Pixel Platz hat - dann soll das Bild auch mit einer Größe von 50x50 angezeigt werden? Wenn man das ganz dem GridBagLayout überlassen will, könnte man dem DynamicImagePanel eine Methode geben
Java:
        @Override
        public Dimension getPreferredSize()
        {
            return new Dimension(getHeight(),1);
        }
aber ich bin nicht sicher, ob das gemeint ist und in ALLEN Fällen wie gewünscht funktioniert...
 

Loep

Aktives Mitglied
Der Header hat momentan ein BorderLayout, in dessen LINE_END steckt das Logo. Ich meinte es mal mit nem GridLayout versucht zu haben, aber da war der Logobereich immer zu breit (bin mir aber nicht sicher und kann es leider grad nicht testen).

Wenn das Fenster 500 Pixel hat, soll der Header 50 Pixel haben. Die Höhe des Logos soll der Höhe des Header entsprechen. Wann das Logo 100x80 Pixel ist, dann soll es auf 50x40 Pixel skaliert werden (Seitenverhältnis des Logos soll also beachtet werden).
 

Marco13

Top Contributor
Hmja... (vielleicht hätte ich zu dem oberen noch einen Disclaimer schreiben sollen: Üblicherweise versuche ich schon, Dinge zu schreiben, derer ich mir sicher bin ... aber das war etwas, was ich eher zufällig ausprobiert hatte, und was funktioniert, ... aber wovon ich spontan nicht sagen könnte, warum ... :oops: ). Ich meinte, dass das GridBagLayout mit diesen 10% für den Header ja die "erste" Vorgabe macht. Danach richtet sich (fest vorgegeben) die Breite des Logos und damit der ganze Rest. Bei einem GridLayout sind immer alle Components gleich groß, deswegen wäre das für den Header wohl ungeeignet, aber ein BorderLayout mit dem Logo im EAST (bzw. LINE_END) sollte ja OK sein...
 

Loep

Aktives Mitglied
Das klappt leider nur für Logos im Hochformat und auch da ist rechts bei der ersten Anzeige rechts ein Freiraum, der erst bei nem Resize verschwindet (womit ich leben könnte).
Logos im Querformat werden allerdings abgeschnitten :( Ich probiere hier schon rum, weil ich gelesen habe, dass getHeigth/getWidht erst einen Wert zurückgeben, nachdem die Komponente tatsächlich gezeichnet wurde, also nach pack()/setVisible(), aber das überschreiben von setVisible hat nicht geholfen.

Interessant ist auch das Verhalten, wenn das Fenster maximiert gestartet wird:
  1. erst ist das Logo abgeschnitten
  2. nach man das Maximieren aufgehoben hat (Fenstericon "Verkleinern") hat es einen Freiraum
  3. nach dem Resize per Drag&Drop passt das Logo
Java:
package tmp;

import gui.DynamicImagePanel;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.LayoutManager;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class BorderLayoutDemo extends JFrame {
	private static final long serialVersionUID = 2863765494455240239L;

	private Dimension startupSize = new Dimension(800, 600);
	private GridBagConstraints c = new GridBagConstraints();
	
//	private ImageIcon image = new ImageIcon("images/0_querformat.jpg");
//	private ImageIcon image = new ImageIcon("images/0_hochformat.jpg");
	private ImageIcon logoImage;
	private JComponent logoContainer;
	
	public static void main(String[] args) {
		BorderLayoutDemo demoHochformat = new BorderLayoutDemo();
		demoHochformat.setImage(new ImageIcon("images/0_hochformat.jpg"));
		demoHochformat.setVisible(true);
		BorderLayoutDemo demoQuerformat = new BorderLayoutDemo();
		demoQuerformat.setImage(new ImageIcon("images/0_querformat.jpg"));
		demoQuerformat.setVisible(true);
	}
	
	public BorderLayoutDemo() {
//		initialize();
//		addHeader();
//		addContent();
	}
	
	public void setImage(ImageIcon image) {
		this.logoImage = image;
	}
	
	@Override
	public void setVisible(boolean visible) {
		System.out.println("setVisible: "+ visible);
		this.pack();
		super.setVisible(visible);
		initialize();
		addHeader();
		addContent();
	}
	
	private void initialize() {
		initializeFrame();
		initialzeLayoutContraints();
	}
	
	private void initializeFrame() {
		LayoutManager frameLayout = new GridBagLayout();
		setLayout(frameLayout);
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setSize(startupSize);
		setMinimumSize(startupSize);
		setExtendedState(Frame.MAXIMIZED_BOTH);
	}
	
	private void initialzeLayoutContraints() {
	}
	
	private void addHeader() {
		JPanel header = createAndInitHeader();
		c.gridx = 0;
		c.gridy = 0;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.weighty = 0.1;
		add(header, c);
	}

	private JPanel createAndInitHeader() {
		JPanel header = new JPanel(new BorderLayout());
		header.setBorder(BorderFactory.createEtchedBorder());
		addContentTo(header);
		return header;
	}

	private void addContentTo(JPanel container) {
		JPanel maincontent = createAndInitHeadertext();
		container.add(maincontent, BorderLayout.CENTER);
		JComponent logo = createAndInitHeaderlogo();
		container.add(logo, BorderLayout.LINE_END);
	}

	private JPanel createAndInitHeadertext() {
		int numberOfHeaderRows = 3;
		JPanel headertext = new JPanel(new GridLayout(0, 1));
		headertext.setBorder(BorderFactory.createTitledBorder("text"));
		for(int i=0; i<numberOfHeaderRows; i++) {
			addLabelTo(headertext, "header row", i);
		}
		return headertext;
	}
	
	private JComponent createAndInitHeaderlogo() {
		logoContainer = new DynamicImagePanel(logoImage.getImage());
		logoContainer.setBorder(BorderFactory.createTitledBorder("logo"));
		return logoContainer;
	}
	
	private void addContent() {
		JPanel content = createAndInitContent();
		c.gridx = 0;
		c.gridy = 1;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 0.5;
		c.weighty = 0.9;
		add(content, c);
	}
	
	private JPanel createAndInitContent() {
		int numberOfContentAreas = 2;
		JPanel container = new JPanel(new GridLayout(0, numberOfContentAreas));
		container.setBorder(BorderFactory.createTitledBorder("content"));
		for(int i=0; i<numberOfContentAreas; i++) {
			addLabelTo(container, "main content", i);
		}
		return container;
	}
	
	private void addLabelTo(JPanel container, String textprefix, int number) {
		JLabel row = new DynamicFontLabel(textprefix+ " "+ number);
		row.setHorizontalAlignment(JLabel.CENTER);
		row.setVerticalAlignment(JLabel.CENTER);
		row.setBorder(BorderFactory.createEtchedBorder());
		container.add(row);
	}
	
	public class DynamicFontLabel extends JLabel {
		private static final long serialVersionUID = 5037485673099026994L;
		private Insets margin = new Insets(0, 5, 0, 5);
		
		public DynamicFontLabel() {
			super();
		}

		public DynamicFontLabel(String string) {
			super(string);
		}

		@Override
		protected void paintComponent(Graphics g) {
			calcFont(g);
			super.paintComponent(g);
		}

		private void calcFont(Graphics g) {
			Insets insets = getInsets();
//			Insets margin = getMargin();	// just for a JButton
			int x = insets.left + margin.left;
			int y = insets.top + margin.top;
			// Breite und Höhe bestimmen
			Dimension size = getSize();
			int w = size.width - x - insets.right - margin.right;
			int h = size.height - y - insets.bottom - margin.bottom;
			Font font = g.getFont();
			String text = getText();
			FontMetrics fm = g.getFontMetrics(font);
			while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) {
				font = font.deriveFont(font.getSize2D() + 0.5f);
				fm = g.getFontMetrics(font);
			}
			g.setFont(font);
		}
		
	}

}
Java:
package gui;

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

import javax.swing.JPanel;

public class DynamicImagePanel extends JPanel {
	private static final long serialVersionUID = 1928634527591569084L;
	private Image background;

	private Dimension scaledBackgroundSize;
	
	public DynamicImagePanel(Image image) {
		background = image;
		System.out.print("constructor: ");
		calculateNewBackgroundSize();
	}

	@Override
	public void setVisible(boolean visible) {
		super.setVisible(visible);
		System.out.print("setVisible: ");
		calculateNewBackgroundSize();
	}
	
	private void calculateNewBackgroundSize() {
		int originalImageHeight = background.getHeight(this);
		int originalImageWidth = background.getWidth(this);
		int newHeight = getHeight();
		double scaleFactor = (double)originalImageWidth / originalImageHeight;
		int newWidth = (int)Math.round(newHeight * scaleFactor);
		scaledBackgroundSize = new Dimension(newWidth, newHeight);
		System.out.println(newWidth +" x "+ newHeight);
	}
	
	@Override
	public void paintComponent(Graphics g) {
		System.out.print("paintComponent: ");
		calculateNewBackgroundSize();
		int newWidth = scaledBackgroundSize.width;
		int newHeight = scaledBackgroundSize.height;
		g.drawImage(background, 0, 0, newWidth, newHeight, this);
	}
	
    @Override
    public Dimension getPreferredSize()
    {
    	Dimension preferredSize;
    	if(scaledBackgroundSize.width == 0) {
    		preferredSize = new Dimension(getHeight(), 1);
    	} else {
    		preferredSize = new Dimension(scaledBackgroundSize.width, 1);
    	}
    	System.out.println("getPreferredSize: "+ preferredSize.width +" x "+ preferredSize.height);
    	return preferredSize;
    }
    
}
Java:
package gui;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class DynamicFontLabel extends JLabel {
	private static final long serialVersionUID = -6029717230072874871L;

	private Insets margin = new Insets(0, 5, 0, 5);	// avoid textsubstituation like displaying "blabl..." instead of "blablub"
	
	private String nameForEmptyLabels = "unnamed";
	private int maxBorderTitleLength = nameForEmptyLabels.length();
	private final static boolean setBorder = true;
	
	public DynamicFontLabel() {
		super();
		setDefaultStyle();
	}

	public DynamicFontLabel(String string) {
		super(string);
		setDefaultStyle();
	}

	private void setDefaultStyle() {
		setHorizontalAlignment(JLabel.CENTER);
		setVerticalAlignment(JLabel.CENTER);
		String bordertitle = getText();
		if(setBorder) {
			if(bordertitle.length() > maxBorderTitleLength) {
				bordertitle = bordertitle.substring(0, maxBorderTitleLength);
			} else if(bordertitle.isEmpty()) {
				bordertitle = nameForEmptyLabels;
			}
			setBorder(BorderFactory.createTitledBorder(bordertitle));
		}
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		calcFont(g);
		super.paintComponent(g);
	}

	private void calcFont(Graphics g) {
		Insets insets = getInsets();
//		Insets margin = getMargin();	// just for a JButton
		int x = insets.left + margin.left;
		int y = insets.top + margin.top;
		// Breite und Höhe bestimmen
		Dimension size = getSize();
		int w = size.width - x - insets.right - margin.right;
		int h = size.height - y - insets.bottom - margin.bottom;
		Font font = g.getFont();
		String text = getText();
		FontMetrics fm = g.getFontMetrics(font);
		while (fm.stringWidth(text) < w && fm.getMaxAscent() + fm.getMaxDescent() < h) {
			font = font.deriveFont(font.getSize2D() + 0.5f);
			fm = g.getFontMetrics(font);
		}
		g.setFont(font);
	}
	
	public static void main(String[] args) {
		JFrame window = new JFrame();
		window.add(new DynamicFontLabel("test"));
		window.pack();
		window.setVisible(true);
	}

}
 

Marco13

Top Contributor
Hmja, das ist alles ziemlich kompliziert: Üblicherweise ist der Ablauf beim Layout (stark vereinfacht):
- Der LayoutManager fragt die Components nach ihrer PreferredSize
- Die Components geben ihre PreferredSize auf Basis ihres Inhalts zurück
(dabei wird. ggf IHR Layoutmanager wieder ihre Untercomponents fragen)
- Wenn alle Wunschgrößen feststehen, versucht der LayoutManager, diese Wünsche zu erfüllen
(sofern das nicht seiner "Natur" widerspricht - beim GridLayout sind z.B. immer alle gleich groß)

In diesem Fall ändert sich ja alles ständig, und die Wunschgrößen stehen erst fest, wenn das Layout einmal komplett durchgeführt wurde - da beißt sich die Katze in den Schwanz. Ich befürchte, dass man da immer mit Artefakten rechnen muss (d.h. abgeschnittene Components, falsche Seitenverhältnisse oder "sprunghafte" Größenänderungen). Ggf. könnte ich in den nächsten Tagen nochmal genauer drüberschauen, aber vielleicht sehen sich "die üblichen Verdächtigen" (Beni, Andre & Co) diesen Thread vorher schonmal an und haben hilfreiche Tipps dazu....
 

bERt0r

Top Contributor
Ich hab versucht es mit dem MigLayout hinzukriegen, weil man da bequem die höhe auf 10% festlegen kann, hab es aber nicht hingekriegt (Das logo wird kleiner als der header beim verkleinern des Frames).
Mit dem GroupLayout, mit dem du wahrscheinlich nix anfangen kannst gehts aber wunderbar:
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;


public class ResizeImage extends JFrame {

	private JPanel contentPane;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					ResizeImage frame = new ResizeImage();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public ResizeImage() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		
		ResizeableImageComponent logo=new ResizeableImageComponent(new BufferedImage(200,100,BufferedImage.TYPE_3BYTE_BGR));
		contentPane.add(logo);
		
		JPanel header = new JPanel();
		header.setLayout(new FlowLayout(FlowLayout.LEFT));
		header.setBackground(Color.YELLOW);
		
		JLabel label = new JLabel("Ich bin ein lustiger Header");
		header.add(label);
		
		JPanel content=new JPanel();
		content.setBackground(Color.red);
		content.setPreferredSize(new Dimension(400,300));
		
		GroupLayout layout = new GroupLayout(contentPane);
		layout.setHorizontalGroup(
				layout.createParallelGroup(Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
							.addComponent(header, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
							.addComponent(logo, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
							)
				.addComponent(content)
		);
		layout.setVerticalGroup(
				layout.createSequentialGroup()
					.addGroup(
							layout.createParallelGroup(Alignment.LEADING)
								.addComponent(header, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
								.addComponent(logo, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
								)
					.addComponent(content)
		);
		layout.linkSize(SwingUtilities.VERTICAL,header,logo);
		contentPane.setLayout(layout);	
	}
	
	public int get10PercentHeight()
	{
		return getHeight()/10;
	}
	
	class ResizeableImageComponent extends JPanel
	{
		Image image;
		double verhaeltnis;
		ResizeableImageComponent(Image i)
		{
			image=i;
			verhaeltnis=(double)image.getWidth(null)/(double)image.getHeight(null);
			addComponentListener(new ComponentAdapter()
			{
				@Override
				public void componentResized(ComponentEvent e)
				{
					image=image.getScaledInstance((int) (verhaeltnis*getHeight()), getHeight(), Image.SCALE_DEFAULT);
				}
			});
		}

		@Override
		public Dimension getPreferredSize()
		{
			int height=ResizeImage.this.get10PercentHeight();
			int width=(int) (height*verhaeltnis);
			return new Dimension(width,height);
		}
		
		@Override
		public void paintComponent(Graphics g)
		{
			g.drawImage(image, 0,0,null);
		}
	}
}
 

Loep

Aktives Mitglied
Danke, aber setz mal in Zeile 50 ein echtes Bild ein ;)
Java:
ResizeableImageComponent logo = new ResizeableImageComponent(new ImageIcon("images/0_querformat.jpg").getImage());
Initial wird es gar nicht gezeichnet und beim Resize ist der Inhalt des Image nur noch zu erahnen :(

Ich hätte mir nicht träumen lassen, dass das so kompliziert ist... hab heute morgen auch wieder dran rumgespielt, bin aber nicht weiter gekommen. Hab mir auch mal den WindowBuilder installiert um dort eventuell auf Componenten zu stoßen, die ich bisher noch nicht kannte.
 

bERt0r

Top Contributor
Ich hab mich natürlich nur auf die Layoutsache konzentriert, natürlich kann man das mit dem Bild besser machen, da hättest du aber auch selber drauf kommen können (marginale Änderungen):
Java:
class ResizeableImageComponent extends JPanel
	{
		Image original;
		Image showImage;
		double verhaeltnis;
		ResizeableImageComponent(Image i)
		{
			original=i;
			showImage=original;
			verhaeltnis=(double)original.getWidth(null)/(double)original.getHeight(null);
			addComponentListener(new ComponentAdapter()
			{
				@Override
				public void componentResized(ComponentEvent e)
				{
					showImage=original.getScaledInstance((int) (verhaeltnis*getHeight()), getHeight(), Image.SCALE_SMOOTH);
				}
			});
		}

		@Override
		public Dimension getPreferredSize()
		{
			int height=ResizeImage.this.get10PercentHeight();
			int width=(int) (height*verhaeltnis);
			return new Dimension(width,height);
		}
		
		@Override
		public void paintComponent(Graphics g)
		{
			g.drawImage(showImage, 0,0,null);
		}
	}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
U dynamisches JTree erstellen AWT, Swing, JavaFX & SWT 2
D Swing Dynamisches Dialog UI AWT, Swing, JavaFX & SWT 8
B 2D-Grafik Dynamisches Erstellen von Images und deren Animation AWT, Swing, JavaFX & SWT 4
M Swing Dynamisches Layout AWT, Swing, JavaFX & SWT 10
T dynamisches Koordinatenkreuz mit scalierung AWT, Swing, JavaFX & SWT 7
C Scollpane an dynamisches GridLayout anpassen? AWT, Swing, JavaFX & SWT 3
N Swing Dynamisches Verhalten bei Änderung Fenstergröße AWT, Swing, JavaFX & SWT 6
trash Dynamisches Interface AWT, Swing, JavaFX & SWT 6
H LayoutManager Dynamisches Layout AWT, Swing, JavaFX & SWT 3
T Swing Dynamisches Bild AWT, Swing, JavaFX & SWT 8
T RCP-SWT dynamisches ScrolledComposite AWT, Swing, JavaFX & SWT 2
B dynamisches Spektrogramm in Java-Webanwendung AWT, Swing, JavaFX & SWT 3
G LookAndFeel Dynamisches Einlesen von LookAndFeels - NullPointerException AWT, Swing, JavaFX & SWT 4
M Dynamisches generieren und ausrichten von Komponenten AWT, Swing, JavaFX & SWT 11
T Dynamisches hinzufügen und entfernen von Bildern AWT, Swing, JavaFX & SWT 3
L Dynamisches Ändern der Größe in JPanel mit paint()-Methode AWT, Swing, JavaFX & SWT 8
J Dynamisches füllen von GridBagLayout: Größe der Komponenten AWT, Swing, JavaFX & SWT 4
S GUI, dynamisches Wechseln von JPanels in einem JFrame AWT, Swing, JavaFX & SWT 2
L Dynamisches Erzeugen eines Button AWT, Swing, JavaFX & SWT 2
M Schwieriges Label - Font - Problem "Dynamisches Label&a AWT, Swing, JavaFX & SWT 7
C Dynamisches Zuweisen von Daten an eine JTable zur Laufzeit AWT, Swing, JavaFX & SWT 4
C ActionListener für dynamisches Menü AWT, Swing, JavaFX & SWT 8
XWing Swing Image anzeigen und probleme mit klassen AWT, Swing, JavaFX & SWT 3
Telisti Javafx Image wird nicht richtig integiert AWT, Swing, JavaFX & SWT 8
K JavaFX Bildergalerie aus Image Ordner laden AWT, Swing, JavaFX & SWT 3
JMölleri Swing Image wird unscharf dargestellt AWT, Swing, JavaFX & SWT 2
L AWT .gif image transparent machen AWT, Swing, JavaFX & SWT 3
kodela angezeigtes Image entfernen AWT, Swing, JavaFX & SWT 1
R Java, GUI, Hintergrundbild, Image, AWT, Swing, JavaFX & SWT 4
R Swing Background Image in JFrame implementieren AWT, Swing, JavaFX & SWT 40
T Swing Buffered Image anzeigen AWT, Swing, JavaFX & SWT 45
L Image kann nicht gefunden werden AWT, Swing, JavaFX & SWT 1
S Stretch Image in ImageView AWT, Swing, JavaFX & SWT 4
N Swing Image aus Web laden und in Icon umwandeln AWT, Swing, JavaFX & SWT 4
Fiedlerdan Image-Pfad Probleme nach Export aus Eclipse AWT, Swing, JavaFX & SWT 31
L JavaFX Image mit Blureffect AWT, Swing, JavaFX & SWT 2
Bluedaishi JavaFX Button Image aus Datenbank AWT, Swing, JavaFX & SWT 13
F javaxt.io.Image getBufferedImage liefert null AWT, Swing, JavaFX & SWT 1
Yjuq JavaFX Custom Control - Image resize AWT, Swing, JavaFX & SWT 0
D Java FX Image in einer Webanwendung annotieren und den Bereich ausschneiden AWT, Swing, JavaFX & SWT 0
I Bild über FXML (ImageView, Image) anzeigen AWT, Swing, JavaFX & SWT 1
T Image Loader lädt Bild nicht AWT, Swing, JavaFX & SWT 10
J 2D-Grafik Background Image Klasse AWT, Swing, JavaFX & SWT 14
Q AWT TicTacToe Image auf Button hinzufügen AWT, Swing, JavaFX & SWT 5
BreakdownBob Swing JLabel verschwindet hinter Image AWT, Swing, JavaFX & SWT 2
L JavaFX leeres weißes Image - javafx.scene.image.Image AWT, Swing, JavaFX & SWT 2
L JavaFX Image im ImageView auf Scroll Listener reagieren AWT, Swing, JavaFX & SWT 5
Naxon89 JavaFX Image wird nicht korrekt geladen AWT, Swing, JavaFX & SWT 3
W Javafx - Image soll sich mit der Camera mitbewegen AWT, Swing, JavaFX & SWT 1
B Graphics to Image AWT, Swing, JavaFX & SWT 3
L Image in anderes kopieren AWT, Swing, JavaFX & SWT 0
T Swing Image wird nicht geladen AWT, Swing, JavaFX & SWT 1
S JavaFX Image Skalierung in Scrollpane, Scrollpane resized sich nicht AWT, Swing, JavaFX & SWT 5
I Image im PopupMenu vom SystemTray AWT, Swing, JavaFX & SWT 8
F JavaFX Position von Image angeben/verändern AWT, Swing, JavaFX & SWT 2
M JavaFX Image View Würfel berechnen AWT, Swing, JavaFX & SWT 3
L JButton mit Image AWT, Swing, JavaFX & SWT 5
F Swing Image einem Button hinzufügen AWT, Swing, JavaFX & SWT 5
B Resize von Image nach Resize von Button AWT, Swing, JavaFX & SWT 1
T Image aus "nicht-src-ordner" AWT, Swing, JavaFX & SWT 5
vodkaz (javafx) Image Problem AWT, Swing, JavaFX & SWT 2
C Image laden und Speichern - Image wird auf JPanel nicht angezeigt AWT, Swing, JavaFX & SWT 4
M Image in JTable einfügen AWT, Swing, JavaFX & SWT 9
M Image aus MS Access anzeigen lassen AWT, Swing, JavaFX & SWT 9
H Image im Array per Knopfdruck ändern AWT, Swing, JavaFX & SWT 6
H Swing JList/JTable mit JButton, JTextField, Image, JComboBox und JLable AWT, Swing, JavaFX & SWT 2
P Image oder Icon auf Tooltip zeichnen AWT, Swing, JavaFX & SWT 4
G JavaFX Image vergrößern AWT, Swing, JavaFX & SWT 5
U Image mit Zeichenbereich rotieren AWT, Swing, JavaFX & SWT 3
P Speicherproblem SWT.Image in Nebula-Gallery AWT, Swing, JavaFX & SWT 3
L JavaFX: Bild in Image einlesen AWT, Swing, JavaFX & SWT 11
D Image soll langsam sichtbar werden AWT, Swing, JavaFX & SWT 4
D JLabel Image ausrichten AWT, Swing, JavaFX & SWT 2
Z Flackern trotz Offscreen Image / Doublebuffer, (+ Frage zu Pixelvergleich) AWT, Swing, JavaFX & SWT 25
bluerob Problem beim Image zeichnen via andere Klasse AWT, Swing, JavaFX & SWT 7
H Image Icon ersetzen AWT, Swing, JavaFX & SWT 8
I Image Button AWT, Swing, JavaFX & SWT 4
U IntBuffer zum Image konvertieren. AWT, Swing, JavaFX & SWT 9
S Eigene JComponent Image zeichnen AWT, Swing, JavaFX & SWT 3
T 2D-Grafik Slideshow (DoubleBuffering und Image transformieren/bewegen) AWT, Swing, JavaFX & SWT 6
K Swing Warum bleibt das Image immer gleich AWT, Swing, JavaFX & SWT 4
R Image laden sehr langsam AWT, Swing, JavaFX & SWT 7
D Image.getScaledInstance() vs. Netzwerkverbindung??? AWT, Swing, JavaFX & SWT 2
reibi SWT Image viewer AWT, Swing, JavaFX & SWT 2
lumo SWT Image funktion auf ImageDaten AWT, Swing, JavaFX & SWT 9
A Applet .gif in applet Image nicht animiert angezeigt AWT, Swing, JavaFX & SWT 4
M Image wird nicht neugezeichnet nach dem Wechsel AWT, Swing, JavaFX & SWT 2
lumo SWT Image Pattern AWT, Swing, JavaFX & SWT 5
P Image mehrfach in ein BufferedImage zeichnen AWT, Swing, JavaFX & SWT 7
M Swing Image in JPanel als Componente AWT, Swing, JavaFX & SWT 2
P nicht sichtbares JPanel / JFrame als Image speichern AWT, Swing, JavaFX & SWT 3
T Image skaliert in Variable speichern AWT, Swing, JavaFX & SWT 6
S Image wird nicht (immer) in paintComponent gezeichnet? AWT, Swing, JavaFX & SWT 6
S Swing Image wird nicht geladen AWT, Swing, JavaFX & SWT 2
0 Mousecurser mit Image hinterlegen AWT, Swing, JavaFX & SWT 4
B Swing Drag&Drop mit Feedback (Image am Mauszeiger) AWT, Swing, JavaFX & SWT 7
N Java Choice Bilderausgabe - images - - image - AWT, Swing, JavaFX & SWT 2
D iText PdfPCell mit Image AWT, Swing, JavaFX & SWT 3
S 2D-Grafik Icon in Image (System Icons) AWT, Swing, JavaFX & SWT 2
S Button mit Image AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen

Neue Themen


Oben