560 likes | 1.33k Views
Java Swing Layout Management. Laying out components. Manage realized components Determine size and position Each container has a layout manager (usually). Layout managers – general aspects. Creating a layout manager Consulting managers Types of managers Choosing managers
E N D
Laying out components • Manage realized components • Determine size and position • Each container has a layout manager • (usually)
Layout managers –general aspects • Creating a layout manager • Consulting managers • Types of managers • Choosing managers • Other features of component layout • All Covered very well here: • http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html
Creating a layout manager • Default layout managers • JFrame, JDialog, JApplet have BorderLayout • JPanel has FlowLayout • Except when used as a Content Pane (Border Layout) • Setting the layout manager for a container • JFrame frame = new JFrame(); frame.setLayout(new FlowLayout()); • JPanel contentPane = new JPanel(); contentPane.setLayout(new BorderLayout());
Consulting layout managers (1) • Consulted automatically when container may need to change its appearance. • These methods result in consultation, but DON’T trigger new layout • add(), remove(), removeAll() • getAlignmentX(), getAlignmentY() • getPreferredSize(), getMinimumSize(), getMaximumSize()
Consulting layout managers (2) • These methods actually result in the manager performing layout. • JFrame.pack(); • Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. • JFrame.show() & JFrame.setVisible(true); • Shows the component • JComponent.revalidate(); • This method will automatically be called on this component when a property value changes. Looks for all dependent components and calls validate() on them. Validate() causes a container to lay out its subcomponents again
Layout managers - types • BorderLayout • BoxLayout • FlowLayout • GridLayout • GridBagLayout • CardLayout
BorderLayout • Five areas • NORTH, SOUTH, EAST, WEST and CENTER • Not all areas must be used • Do not assume a default area for components • Centre gets as much area as possible • Specify location as argument of add method • pane.setLayout(new BorderLayout()); • pane.add(new JButton(“Button 1 (NORTH)”), BorderLayout.NORTH); • Setting gaps between components (default = 0) • BorderLayout.setHgap(int gap); • BorderLayout.setVgap(int gap); • BorderLayout(int horizontalGap, int verticalGap) - Constructor
BorderLayout import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BorderWindow extends JFrame { public BorderWindow() { //--- use default content pane Container contentPane = getContentPane(); //--- Use the content pane's default BorderLayout. //--- contentPane.setLayout(new BorderLayout()); //unnecessary //--- under 1.5 can just commented out line as content pane //--- is implcitly obtained //--- add(new JButton("Button 1 (NORTH)"), //--- BorderLayout.NORTH); contentPane.add(new JButton("Button 1 (NORTH)"), BorderLayout.NORTH); contentPane.add(new JButton("2 (CENTER)"), BorderLayout.CENTER); contentPane.add(new JButton("Button 3 (WEST)"), BorderLayout.WEST); contentPane.add(new JButton("Long-Named Button 4 (SOUTH)"), BorderLayout.SOUTH); contentPane.add(new JButton("Button 5 (EAST)"), BorderLayout.EAST); setDefaultCloseOperation(EXIT_ON_CLOSE); } public static void main(String args[]) { BorderWindow window = new BorderWindow(); window.setTitle("BorderLayout"); window.pack(); window.setVisible(true); } }
BorderLayout contentPane.add(new JButton("Button 1 (NORTH)"), BorderLayout.NORTH); contentPane.add(new JButton("2 (CENTER)"), BorderLayout.CENTER); contentPane.add(new JButton("Button 3 (WEST)"), BorderLayout.WEST); contentPane.add(new JButton("Long-Named Button 4 (SOUTH)"), BorderLayout.SOUTH); contentPane.add(new JButton("Button 5 (EAST)"), BorderLayout.EAST); setDefaultCloseOperation(EXIT_ON_CLOSE); }
BorderLayout public static void main(String args[]) { BorderWindow window = new BorderWindow(); window.setTitle("BorderLayout"); window.pack(); window.setVisible(true); } }
BoxLayout (1) • Components on top / next to each other • Direction is your choice • Tries to size components at preferred height for Y_AXIS or width for X_AXIS • Width as largest component width • See above picture
BoxLayout (2) • Space fillers • Rigid - fixed-size space between two components • Glue - taking up no space unless you pull apart the components that it's sticking to. Helps reposition extra space (default is at end) • Custom - Use this to specify a component with whatever minimum, preferred, and maximum sizes you want
BoxLayout (3) • Component sizes • Respect Max, Min and Preferred Sizes of components • Alignment • Comes into play when not all components are the same width • Can specify Left (0), Centre (0.5) or Right (1). Or Top Middle Bottom • If you are having layout problems, first treat as an Alignment issue, then examine sizes.
BoxLayout import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BoxWindow extends JFrame { public BoxWindow() { Container contentPane = getContentPane(); contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); addAButton("Button 1", contentPane); addAButton("2", contentPane); addGlue(contentPane); addAButton("Button 3", contentPane); addCustomFiller(contentPane); addAButton("Long-Named Button 4", contentPane); addAButton("Button 5", contentPane); setDefaultCloseOperation(EXIT_ON_CLOSE); } private void addAButton(String text, Container container) { JButton button = new JButton(text); button.setAlignmentX(Component.CENTER_ALIGNMENT); container.add(button); } public void addGlue(Container container) { container.add(Box.createVerticalGlue()); } public void addCustomFiller(Container container) { Dimension minSize = new Dimension(300, 30); Dimension prefSize = new Dimension(300, 30); Dimension maxSize = new Dimension(Short.MAX_VALUE, 30); container.add(new Box.Filler(minSize, prefSize, maxSize)); } public static void main(String args[]) { BoxWindow window = new BoxWindow(); window.setTitle("BoxLayout"); window.pack(); window.setVisible(true); } }
BoxLayout import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BoxWindow extends JFrame { public BoxWindow() { Container contentPane = getContentPane(); contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); addAButton("Button 1", contentPane); addAButton("2", contentPane); addGlue(contentPane); addAButton("Button 3", contentPane); addCustomFiller(contentPane); addAButton("Long-Named Button 4", contentPane); addAButton("Button 5", contentPane); setDefaultCloseOperation(EXIT_ON_CLOSE); }
BoxLayout import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BoxWindow extends JFrame { public BoxWindow() { private void addAButton(String text, Container container) { JButton button = new JButton(text); button.setAlignmentX(Component.CENTER_ALIGNMENT); container.add(button); } public void addGlue(Container container) { container.add(Box.createVerticalGlue()); }
BoxLayout import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BoxWindow extends JFrame { public static void main(String args[]) { BoxWindow window = new BoxWindow(); window.setTitle("BoxLayout"); window.pack(); window.setVisible(true); } }
FlowLayout • Very simple - JPanel’s default • Components in row(s) • At preferred size • Alignment • FlowLayout.LEFT • FlowLayout.CENTRE • FlowLayout.RIGHT • Gaps • Default = 5 • Specifying - setter hGap vGap methods or via constructor
FlowLayout public class FlowWindow extends JFrame { public FlowWindow() { Container contentPane = getContentPane(); //contentPane.setLayout(new FlowLayout()); //default = centre, 5, 5 contentPane.setLayout(new FlowLayout(FlowLayout.RIGHT, 30, 5)); contentPane.add(new JButton("Button 1")); contentPane.add(new JButton("2")); contentPane.add(new JButton("Button 3")); contentPane.add(new JButton("Long-Named Button 4")); contentPane.add(new JButton("Button 5")); setDefaultCloseOperation(EXIT_ON_CLOSE); }
FlowLayout public static void main(String args[]) { FlowWindow window = new FlowWindow(); window.setTitle("FlowLayout"); window.pack(); window.setVisible(true); } }
GridLayout • Grid of cells - all same size • Components take all space in a cell • Gaps • default = 5 • use setter methods hGap and vGap • or via arguments to constructor • Re-sizing • Cells resize to be as large as possible in given window / container
GridLayout public class GridWindow extends JFrame { public GridWindow() { Container contentPane = getContentPane(); //contentPane.setLayout(new GridLayout(0,2)); contentPane.setLayout(new GridLayout(0,3,20,20)); contentPane.add(new JButton("Button 1")); contentPane.add(new JButton("2")); contentPane.add(new JButton("Button 3")); contentPane.add(new JButton("Long-Named Button 4")); contentPane.add(new JButton("Button 5")); setDefaultCloseOperation(EXIT_ON_CLOSE); }
GridBagLayout (1) • Very flexible (and complex!) • Rows can have different heights • Columns can have different lengths • Uses cells in a grid GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); JPanel pane = new JPanel(); pane.setLayout(gridbag); //--- For each component to be added to this container: //--- ...Create the component... //--- ...Set instance variables in the GridBagConstraints instance... gridbag.setConstraints(theComponent, c); pane.add(theComponent);
GridBagLayout (2) • Constraints • set in an instance of a gridBagConstraints Object • gridx and gridy - The row and column of the upper left of the component • Anchor - Where to display within cell when component is smaller than it • fill - How to size component when cell is larger than components requested size • insets - External padding - min space between component and cell edges • ipadx, ipady - Internal padding - What to add to min size of components • weightx and weighty - How to distribute extra space (padding) • gridwidth and gridheight - Number of columns or rows the component uses • More explanation here: • http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbagConstraints.html • Example explained very well here: • http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbagExample.html
GridBagLayout public class GridBagWindow extends JFrame { public GridBagWindow() { JButton button; Container contentPane = getContentPane(); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); contentPane.setLayout(gridbag); //set all components to fill all available Horzontal space c.fill = GridBagConstraints.HORIZONTAL; button = new JButton("Button 1"); c.weightx = 0.5; c.gridx = 0; c.gridy = 0; gridbag.setConstraints(button, c); contentPane.add(button); button = new JButton("2"); c.weightx = 1.0; c.gridx = 1; c.gridy = 0; gridbag.setConstraints(button, c); contentPane.add(button); button = new JButton("Button 3"); c.weightx = 1.0; c.gridx = 2; c.gridy = 0; gridbag.setConstraints(button, c); contentPane.add(button); button = new JButton("Long-Named Button 4"); c.ipady = 40; //make this component tall c.weightx = 1.0; c.gridwidth = 2; c.gridx = 0; c.gridy = 1; gridbag.setConstraints(button, c); contentPane.add(button); button = new JButton("Button 5"); c.ipady = 0; //reset to default c.weighty = 1.0; //request any extra vertical space c.anchor = GridBagConstraints.NORTH; //bottom of space c.insets = new Insets(10,0,0,0); //top padding c.gridx = 1; //aligned with button 2 c.gridwidth = 2; //2 columns wide c.gridy = 2; //third row gridbag.setConstraints(button, c); contentPane.add(button); setDefaultCloseOperation(EXIT_ON_CLOSE); }
CardLayout • Manages objects (usually JPanels) in sets • Works much like tabbed pane • Choose cards by • Asking for card in order added to container • Going backwards or forwards • Specifying card by name
CardLayout public class CardWindow extends JFrame implements ItemListener { JPanel cards; final static String BUTTONPANEL = "JPanel with JButtons"; final static String TEXTPANEL = "JPanel with JTextField"; public CardWindow() { Container contentPane = getContentPane(); //Put the JComboBox in a JPanel to get a nicer look. String comboBoxItems[] = { BUTTONPANEL, TEXTPANEL }; JPanel cbp = new JPanel(); JComboBox c = new JComboBox(comboBoxItems); c.setEditable(false); c.addItemListener(this); cbp.add(c); //Use the default layout manager, BorderLayout contentPane.add(cbp, BorderLayout.NORTH); cards = new JPanel(); cards.setLayout(new CardLayout()); JPanel p1 = new JPanel(); p1.add(new JButton("Button 1")); p1.add(new JButton("Button 2")); p1.add(new JButton("Button 3")); JPanel p2 = new JPanel(); p2.add(new JTextField("TextField", 20)); cards.add(p1, BUTTONPANEL); cards.add(p2, TEXTPANEL); contentPane.add(cards, BorderLayout.CENTER); setDefaultCloseOperation(EXIT_ON_CLOSE); } public void itemStateChanged(ItemEvent evt) { CardLayout cl = (CardLayout)(cards.getLayout()); cl.show(cards, (String)evt.getItem()); }
Choosing layout managers (1) • In order to display a component in as much space as it can get, consider: • BorderLayout • Component in centre • GridBagLayout • fill=GridBagConstraints.BOTH • BoxLayout • Component specifies very large preferred/maximum sizes
Choosing layout managers (2) • To display a few components in a compact row: • JPanel’s default FlowLayout • BoxLayout • Display a few components of the same size in rows and columns • GridLayout
Choosing layout managers (3) • Display a few components in a row or column, with different spacing between them and custom component sizes • BoxLayout • Display a complex layout that has many components • GridBagLayout • Using JPanel grouping and hierarchies
Layout managers - other layout features • Absolute positioning of components • When • How • Customising layout managers • When • How
Absolute positioning (1) • Don’t do it; unless… • component size isn’t affected by container size or font & look’n’feel changes • e.g. desktop panes containing internal frames • custom container performs size & position calculations particular to container • e.g. split panes
Absolute positioning (2) • Key points from NoneWindow.java • Instruct window to use no Layout: • .contentPane.setLayout(null); • Set components size and position with • XYZ.setBounds(x, y, width, height); • Set window size with: • window.setSize(x, y);
Absolute positioning public class NoneWindow extends JFrame { private JButton b1, b2, b3; public NoneWindow() { Container contentPane = getContentPane(); contentPane.setLayout(null); b1 = new JButton("one"); contentPane.add(b1); b2 = new JButton("two"); contentPane.add(b2); b3 = new JButton("three"); contentPane.add(b3); b1.setBounds(25, 5, 75, 20); b2.setBounds(55, 35, 75, 20); b3.setBounds(300, 200, 75, 30); setDefaultCloseOperation(EXIT_ON_CLOSE); }
Custom layout managers (1) • Ensure no existing manager does the job • GridBagLayout / BoxLayout • Layout manager downloads • If your trying to do it, chances are someone else has done it already… • DECLARE use of external code in coursework
Custom layout managers (2) • Create class which implements Layout Manager interface • e.g. public class myManager implements LayoutManager • Must have 5 methods required by interface • void addLayoutComponent(String, Component) • void removeLayoutComponent(Component) • Dimension preferredLayoutSize(Container) • Dimension minimumLayoutSize(Container) • void layoutContainer(Container) • See below URL for more documentation • http://java.sun.com/docs/books/tutorial/uiswing/layout/custom.html
Summary • Creating a layout manager • Consulting managers • Types of managers • BorderLayout GridLayout • BoxLayout GridBagLayout • FlowLayout CardLayout • Choosing managers • Absolute positioning • Custom layout managers • Next : Abstract Model Widgets