# Java Swings/Swing Layouts

* Java Swing
* Overview
* AWT
* Dive into Swings
* First Examples
* Swing Top Level Containers
* Swing Layouts
* Event Handling
* MVC architecture
* Responsive Swing Application
* Large Examples
Appendix
The layout of components is dictated by the layout manager used. There are 7 layout managers built into Java. Most UIs are built using some combination of them, typically by nesting layout managers. The most commonly used layouts are FlowLayout, BorderLayout and BoxLayout.
* LayoutManagers are a concept from AWT that is also used in Swing. This means they can be used in rendering AWT-based UIs as well as Swing-based UIs. They are mentioned here because they are an integral part of Swing UI development but they are not exclusive to Swing. The built in LayoutManagers all reside in the java.awt package.

## BorderLayout

* Used to arrange components around a center panel.
* Sizes components to use all available space for their region.
** North / South components will be as tall as their preferred height and as wide as the width of the component they're in.
** East / West components will be as wide as their preferred width and as tall as the height of the component they're in minus the preferred heights of the North and South components.
** Center will use all remaining space in the component after the North / South / East / West components have been sized.
* BorderLayout
* import javax.swing.JButton;
* import javax.swing.JFrame;
* import javax.swing.SwingUtilities;
* import java.awt.BorderLayout;
* import java.awt.Container;
* public class BorderLayoutDemo {
* public static void main(String args) {
* Swing events run in the EventDispatchThread. All swing components
* and models must be modified only from the EventDispatchThread.
* SwingUtilities.invokeLater(...) and SwingUtilities.invokeAndWait(...)
* both will execute a Runnable in the EDT.
* SwingUtilities.invokeLater(new Runnable {
* public void run {
* JFrame borderLayoutFrame = new JFrame("Border Layout");
* You shouldn't add components directly to a JFrame. As of Java 5 (1.5?)
* you're allowed to but it won't be backwards compatible. Add to the
* contentPane instead.
* Container contentPane = borderLayoutFrame.getContentPane;
* contentPane.setLayout(new BorderLayout);
* contentPane.add(new JButton("East Button"), BorderLayout.EAST);
* contentPane.add(new JButton("West Button"), BorderLayout.WEST);
* contentPane.add(new JButton("North Button"), BorderLayout.NORTH);
* contentPane.add(new JButton("South Button"), BorderLayout.SOUTH);
* contentPane.add(new JButton("Center"), BorderLayout.CENTER);
* borderLayoutFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
* borderLayoutFrame.setSize(400, 200);
* borderLayoutFrame.setVisible(true);

## FlowLayout

* Used to arrange components in a straight horizontal line.
* If there is not enough space for all the components to fit, they'll be moved to the next line.
* Components are set at their preferred sizes.
* FlowLayout
* import javax.swing.JButton;
* import javax.swing.JFrame;
* import javax.swing.SwingUtilities;
* import java.awt.Container;
* import java.awt.Dimension;
* import java.awt.FlowLayout;
* public class FlowLayoutDemo {
* public static void main(String args) {
* Swing events run in the EventDispatchThread. All swing components
* and models must be modified only from the EventDispatchThread.
* SwingUtilities.invokeLater(...) and SwingUtilities.invokeAndWait(...)
* both will execute a Runnable in the EDT.
* SwingUtilities.invokeLater(new Runnable {
* public void run {
* JFrame flowLayoutFrame = new JFrame("Flow Layout");
* You shouldn't add components directly to a JFrame. As of Java 5 (1.5?)
* you're allowed to but it won't be backwards compatible. Add to the
* contentPane instead.
* Container contentPane = flowLayoutFrame.getContentPane;
* contentPane.setLayout(new FlowLayout);
* contentPane.add(new JButton("Button A"));
* // buttonB will not be resized smaller than 200x40 pixels
* JButton buttonB = new JButton("Button B");
* buttonB.setPreferredSize(new Dimension(200, 40));
* contentPane.add(buttonB);
* contentPane.add(new JButton("Button C"));
* contentPane.add(new JButton("Button D"));
* flowLayoutFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
* flowLayoutFrame.setSize(400, 200);
* flowLayoutFrame.setVisible(true);

## BoxLayout

* Used to arrange components vertically or horizontally. BoxLayout is essentially a replacement for FlowLayout that is more powerful if thats what you're going for. However with great power comes great responsibility... or something like that. The trade off for having more power is you have to do a bit more work, but you can get things to look closer to what you really want. To demonstrate we'll go through several examples.
* Though the comments about running in the EDT and adding to the content pane aren't in these examples, note we're still doing all the work on the components in the EDT and adding components to the content pane.
BoxLayouts come in two basic flavors. Vertical or horizontal. These are represented by the constants BoxLayout.X_AXIS, BoxLayout.Y_AXIS, BoxLayout.LINE_AXIS, BoxLayout.PAGE_AXIS. X/Y_AXIS specify to always layout the components along the X or Y axis of the container. The components are then arranged left to right (X_AXIS) or top to bottom (Y_AXIS). LINE/PAGE_AXIS will do exactly the same thing as X/Y_AXIS assuming the ComponentOrientation field of the parent container is left to right oriented. If not, LINE_AXIS will add components from right to left, and PAGE_AXIS will by default align components on the right side of the panel. If you are planning to support locale specific layouts, PAGE_AXIS is the one for you.
Talking about alignments is fun, but lets see a demo. The below demo will create a main window which will allow you to create child windows laid out with the proper alignments.
* BoxLayout
* import javax.swing.BoxLayout;
* import javax.swing.ButtonGroup;
* import javax.swing.JButton;
* import javax.swing.JComponent;
* import javax.swing.JFrame;
* import javax.swing.JLabel;
* import javax.swing.JRadioButton;
* import javax.swing.JSeparator;
* import javax.swing.SwingUtilities;
* import java.awt.Component;
* import java.awt.ComponentOrientation;
* import java.awt.Container;
* import java.awt.event.ActionEvent;
* import java.awt.event.ActionListener;
* public class BoxLayoutDemo {
* private int alignment;
* private ComponentOrientation orientation;
* private static final String X_AXIS = "X_AXIS";
* private static final String Y_AXIS = "Y_AXIS";
* private static final String LINE_AXIS = "LINE_AXIS";
* private static final String PAGE_AXIS = "PAGE_AXIS";
* private static final String LEFT_TO_RIGHT = "Left to Right";
* private static final String RIGHT_TO_LEFT = "Right to Left";
* private static final String DEFAULT_ORIENTATION = "Default Orientation";
* private ActionListener alignmentListener = new ActionListener {
* public void actionPerformed(ActionEvent e) {
* if (X_AXIS.equals(e.getActionCommand)) {
* alignment = BoxLayout.X_AXIS;
* } else if (Y_AXIS.equals(e.getActionCommand)) {
* alignment = BoxLayout.Y_AXIS;
* } else if (LINE_AXIS.equals(e.getActionCommand)) {
* alignment = BoxLayout.LINE_AXIS;
* } else if (PAGE_AXIS.equals(e.getActionCommand)) {
* alignment = BoxLayout.PAGE_AXIS;
* } else if (LEFT_TO_RIGHT.equals(e.getActionCommand)){
* orientation = ComponentOrientation.LEFT_TO_RIGHT;
* } else if (RIGHT_TO_LEFT.equals(e.getActionCommand)){
* orientation = ComponentOrientation.RIGHT_TO_LEFT;
* } else if (DEFAULT_ORIENTATION.equals(e.getActionCommand)){
* orientation = null;
* public JFrame buildMainFrame{
* JFrame boxLayoutDemoFrame = new JFrame("BoxLayoutFrame");
* boxLayoutDemoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
* Container contentPane = boxLayoutDemoFrame.getContentPane;
* contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
* ButtonGroup alignmentGroup = new ButtonGroup;
* JRadioButton xAxisButton = buildAlignmentButton(alignmentGroup, X_AXIS);
* xAxisButton.setSelected(true);
* JRadioButton yAxisButton = buildAlignmentButton(alignmentGroup, Y_AXIS);
* JRadioButton lineAxisButton = buildAlignmentButton(alignmentGroup, LINE_AXIS);
* JRadioButton pageAxisButton = buildAlignmentButton(alignmentGroup, PAGE_AXIS);
* final ButtonGroup orientationGroup = new ButtonGroup;
* JRadioButton defaultOrientation = buildAlignmentButton(orientationGroup, DEFAULT_ORIENTATION);
* defaultOrientation.setSelected(true);
* JRadioButton leftToRight = buildAlignmentButton(orientationGroup, LEFT_TO_RIGHT);
* JRadioButton rightToLeft = buildAlignmentButton(orientationGroup, RIGHT_TO_LEFT);
* JButton openFrameButton = new JButton("Build window");
* openFrameButton.addActionListener(new ActionListener {
* public void actionPerformed(ActionEvent e) {
* JFrame demoFrame = new JFrame("Demo Frame");
* Container contentPane = demoFrame.getContentPane;
* contentPane.setLayout(new BoxLayout(contentPane, alignment));
* if(orientation != null){
* contentPane.setComponentOrientation(orientation);
* JButton buttonA;
* JButton buttonB;
* JButton buttonC;
* JButton buttonD;
* if(alignment == BoxLayout.PAGE_AXIS || alignment == BoxLayout.Y_AXIS){
* buttonA = new JButton("Left Aligned");
* buttonA.setAlignmentX(JComponent.LEFT_ALIGNMENT);
* buttonB = new JButton("Right Aligned");
* buttonB.setAlignmentX(JComponent.RIGHT_ALIGNMENT);
* buttonC = new JButton("Center Aligned");
* buttonC.setAlignmentX(JComponent.CENTER_ALIGNMENT);
* buttonD = new JButton("Default Aligned");
* } else {
* buttonA = new JButton("Top Aligned");
* buttonA.setAlignmentY(Component.TOP_ALIGNMENT);
* buttonB = new JButton("Bottom Aligned");
* buttonB.setAlignmentY(Component.BOTTOM_ALIGNMENT);
* buttonC = new JButton("Center Aligned");
* buttonC.setAlignmentY(Component.CENTER_ALIGNMENT);
* buttonD = new JButton("Default Aligned");
* contentPane.add(buttonA);
* contentPane.add(buttonB);
* contentPane.add(buttonC);
* contentPane.add(buttonD);
* demoFrame.pack;
* demoFrame.setVisible(true);
* contentPane.add(new JLabel("Alignment Options"));
* contentPane.add(xAxisButton);
* contentPane.add(yAxisButton);
* contentPane.add(lineAxisButton);
* contentPane.add(pageAxisButton);
* contentPane.add(new JSeparator);
* contentPane.add(new JLabel("Orientation"));
* contentPane.add(defaultOrientation);
* contentPane.add(leftToRight);
* contentPane.add(rightToLeft);
* contentPane.add(new JSeparator);
* contentPane.add(openFrameButton);
* boxLayoutDemoFrame.setSize(250, 300);
* return boxLayoutDemoFrame;
* private JRadioButton buildAlignmentButton(ButtonGroup alignmentGroup, String alignmentName) {
* JRadioButton xAxisButton = new JRadioButton(alignmentName, false);
* xAxisButton.setActionCommand(alignmentName);
* xAxisButton.addActionListener(alignmentListener);
* alignmentGroup.add(xAxisButton);
* return xAxisButton;
* public static void main(String args) {
* SwingUtilities.invokeLater(new Runnable {
* public void run {
* BoxLayoutDemo demo = new BoxLayoutDemo;
* JFrame boxLayoutDemoFrame = demo.buildMainFrame;
* boxLayoutDemoFrame.setVisible(true);

## CardLayout

* Used to show one component at a time from a set of components. It is like a deck of flash cards, where you show one of the cards at a time, hence the name. You can quickly change which component is shown at any time, e.g., when the user clicks a button.

## GridLayout

* Used to arrange components in an evenly spaced grid.
* GridLayout
* import java.awt.GridLayout;
* import javax.swing.JButton;
* import javax.swing.JCheckBox;
* import javax.swing.JFrame;
* import javax.swing.JLabel;
* import javax.swing.SwingConstants;
* import javax.swing.SwingUtilities;
* public class GridLayoutDemo extends JFrame {
* private static final long serialVersionUID = 1L;
* public GridLayoutDemo {
* * Calls the constructor in superclass.
* super("GridLayout Demo");
* * Sets the close operation to DISPOSE_ON_CLOSE.
* setDefaultCloseOperation(DISPOSE_ON_CLOSE);
* * Creates a new GridLayout object. It has 2 rows and any number of
* * columns depending of the component count on container. The horizontal
* * and vertical gaps are 10 and 15, respectively.
* GridLayout layout = new GridLayout(2, 0, 10, 15);
* * The default layout manager for the JFrame's content pane is
* * BorderLayout. So, we must to change it.
* setLayout(layout);
* * Just add the new components.
* add(new JButton("Button 1"));
* add(new JButton("Button 2"));
* add(new JLabel("Label 1", SwingConstants.CENTER));
* add(new JCheckBox("CheckBox 1"));
* add(new JLabel("Label 2", SwingConstants.CENTER));
* add(new JLabel("Label 3", SwingConstants.CENTER));
* add(new JButton("Button 3"));
* * Adjusts the windows size, centers it in screen and makes it visible.
* pack;
* setLocationRelativeTo(null);
* setVisible(true);
* public static void main(String args) {
* * Creates a new instance of GridLayoutDemo. Try to resize the window
* * and see the results.
* SwingUtilities.invokeLater(new Runnable {
* @Override
* public void run {
* new GridLayoutDemo;