# Resizeverhalten BorderLayout



## daubor (1. Okt 2009)

Hallo, 

bin neu im Forum und alle meine Fragen konnten bisher über Google und Co beantwortet werden. 
Aber das folgende ist mir ein Rätsel. ???:L

Ich habe ein JPanel mit BorderLayout. Im CENTER sitzt eine JScrollPane. Im SOUTH liegt ein weiteres JPanel.

Nun besitzt mein BorderLayout-Panel eine ComponentTitledBorder (die Klasse hab ich irgendwo im Netz gefunden, sollte relativ leicht zu finden sein). Diese überschreibt jedenfalls die paintBorder() Methode und ruft darin SwingUtilities.paintComponent() auf, um eine beliebig übergebene LigthweightComponent auf die Border zu zeichnen.
Bei mir ist das eine JCheckBox.

Soweit so gut...beim verkleinern des JFrames schiebt sich nun allerdings die JScrollPane, welche im CENTER liegt, unter das JPanel welches im SOUTH liegt. Also der ScrollPane wird nicht bescheid gesagt, dass sich der CENTER Bereich verkleinert...;(
Sieht scheise aus!

Kommentiere ich in der ComponentTitledBorder das SwingUtilities.paintComponent() aus, funktioniert wieder alles , aber die JCheckBox wird nicht mehr gezeichnet :autsch:

Jemand ne Idee?!


----------



## daubor (2. Okt 2009)

Hm..keiner ne Idee?! 
Hab mal ne "Probier"-Klasse rangehangen! Einmal wird mit und einmal ohne die ComponentTitledBorder der Frame geöffnet!
In der ComponentTitledBorder-Klasse sieht man auch das böse SwingUtilities.paintComponent() 
Wenn ihr das ganze startet und die beiden Frames verkleinert, werdet ihr sehen, dass der Resize mit der Border kaputt ist!


```
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;

/*
 * Created on 02.10.2009
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */

public class Probier
{

	public void buildGuiWithoutCOmponentTitledBorder()
	{
		JFrame frame = new JFrame();
		Dimension dim = frame.getToolkit().getScreenSize(); 
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setLocation((dim.width - frame.getWidth()) / 2, (dim.height - frame.getHeight()) / 2); 
		frame.setTitle("Without");

		JPanel mMainPanel = (JPanel) frame.getContentPane();

		JPanel border1 = new JPanel();
		JList list = new JList();
		DefaultListModel lmodel = new DefaultListModel();
		list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		list.setLayoutOrientation(JList.VERTICAL);

		for (int i = 0; i < 100; i++)
			lmodel.addElement(i);

		list.setModel(lmodel);

		//set Layouts
		border1.setLayout(new BorderLayout());

		//build panels
		border1.setBorder(BorderFactory.createTitledBorder("border1"));
		border1.add(new JLabel("border1_south"), BorderLayout.SOUTH);
		border1.add(new JScrollPane(list), BorderLayout.CENTER);

		mMainPanel.add(border1, BorderLayout.CENTER);

		frame.pack();
		frame.setVisible(true); 
	}

	public void buildGuiWithCOmponentTitledBorder()
	{
		JFrame frame = new JFrame();
		Dimension dim = frame.getToolkit().getScreenSize(); 
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setLocation((dim.width - frame.getWidth()) / 2, (dim.height - frame.getHeight()) / 2); 
		frame.setTitle("With");

		JPanel mMainPanel = (JPanel) frame.getContentPane();

		JPanel border1 = new JPanel();
		JList list = new JList();
		DefaultListModel lmodel = new DefaultListModel();
		list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		list.setLayoutOrientation(JList.VERTICAL);

		for (int i = 0; i < 100; i++)
			lmodel.addElement(i);

		list.setModel(lmodel);

		//set Layouts
		border1.setLayout(new BorderLayout());

		//build panels
		border1.setBorder(new ComponentTitledBorder(new JCheckBox(), border1, BorderFactory.createTitledBorder("border1"),
				ComponentTitledBorder.RIGHT));
		border1.add(new JLabel("border1_south"), BorderLayout.SOUTH);
		border1.add(new JScrollPane(list), BorderLayout.CENTER);

		mMainPanel.add(border1, BorderLayout.CENTER);

		frame.pack();
		frame.setVisible(true); 
}

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		Probier p = new Probier();

		p.buildGuiWithCOmponentTitledBorder();
		p.buildGuiWithoutCOmponentTitledBorder();

	}

	public class ComponentTitledBorder implements Border, MouseListener, SwingConstants
	{
		int offset = 5;
		int justification = -1;

		public static final int LEFT = 0;
		public static final int RIGHT = 1;

		Component comp;
		JComponent container;
		Rectangle rect;
		Border border;

		public ComponentTitledBorder(Component comp, JComponent container, Border border, int justification)
		{
			this.comp = comp;
			this.container = container;
			this.border = border;
			this.justification = justification;
			container.addMouseListener(this);
		}

		public ComponentTitledBorder(Component comp, JComponent container, Border border)
		{
			this.comp = comp;
			this.container = container;
			this.border = border;
			container.addMouseListener(this);
		}

		public boolean isBorderOpaque()
		{
			return true;
		}

		public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
		{
			Insets borderInsets = border.getBorderInsets(c);
			Insets insets = getBorderInsets(c);
			int temp = (insets.top - borderInsets.top) / 2;
			border.paintBorder(c, g, x, y + temp, width, height - temp);
			Dimension size = comp.getPreferredSize();

			//right alligned
			if (justification > 0)
				offset = width - 5 - size.width;

			rect = new Rectangle(offset, 0, size.width, size.height);

			SwingUtilities.paintComponent(g, comp, (Container) c, rect);
		}

		public Insets getBorderInsets(Component c)
		{
			Dimension size = comp.getPreferredSize();
			Insets insets = border.getBorderInsets(c);
			insets.top = Math.max(insets.top, size.height);
			return insets;
		}

		private void dispatchEvent(MouseEvent me)
		{
			if (rect != null && rect.contains(me.getX(), me.getY()))
			{
				Point pt = me.getPoint();
				pt.translate(-offset, 0);
				comp.setBounds(rect);
				comp.dispatchEvent(new MouseEvent(comp, me.getID(), me.getWhen(), me.getModifiers(), pt.x, pt.y, me
						.getClickCount(), me.isPopupTrigger(), me.getButton()));
				if (!comp.isValid())
				{
					container.repaint();
				}
			}
		}

		public void mouseClicked(MouseEvent me)
		{
			dispatchEvent(me);
		}

		public void mouseEntered(MouseEvent me)
		{
			dispatchEvent(me);
		}

		public void mouseExited(MouseEvent me)
		{
			dispatchEvent(me);
		}

		public void mousePressed(MouseEvent me)
		{
			dispatchEvent(me);
		}

		public void mouseReleased(MouseEvent me)
		{
			dispatchEvent(me);
		}

	}

}
```


----------



## Marco13 (2. Okt 2009)

So eine "Probier"-Klasse (auch bekannt als KSKB) erhöht die Wahrscheinlichkeit eine Antwort zu erhalten fast immer.

Auch in diesem Fall.

Der Grund für das fehlerhafte Verhalten ist die SwingUtilities.paintComponent-Methode. Die nervt mich tierisch  eigentlich soll sie nur ein Component zeichnen, aber sie macht noch allen möglichen anderen Scheiß ... die Bounds der gezeichneten Component ändern, und neue Components (CellRenderPane) zum Container hinzufügen...

In diesem Fall scheint es zu helfen, wenn man das, was die Methode macht, "per Hand" durchführt, und keine CellRenderPane erstellt... Die paintBorder-Methode würde dann so aussehen

```
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
        {
            Insets borderInsets = border.getBorderInsets(c);
            Insets insets = getBorderInsets(c);
            int temp = (insets.top - borderInsets.top) / 2;
            border.paintBorder(c, g, x, y + temp, width, height - temp);
            Dimension size = comp.getPreferredSize();

            //right alligned
            if (justification > 0)
                offset = width - 5 - size.width;

            rect = new Rectangle(offset, 0, size.width, size.height);
            comp.setBounds(rect);
            g.translate(offset,0);
            comp.paint(g);
            g.translate(-offset,0);
        }
```
Ist nur kurz getestet, aber scheint erstma zu gehen...


----------



## daubor (2. Okt 2009)

Des geht :toll:

Danke für die super Erklärung, was die paintComponent() da im Hintergrund alles treibt!


----------

