How to position components with GridBagLayout? - java

I am kind of new to Java Programming and I am trying to make a window that contains two buttons and a text area, as seen in the image below.
The problem I encountered though was positioning the components. I tried using GridLayout and separating the window into 9 rows and 16 cells, but then found I couldn't make components occupy more than a cell. I know I should be using GridBagLayout but I don't know how exactly. Help would be appreciated. :)

You have a number of choices. Instead of trying to layout the whole component in one, try using a compound layout, where by you layout sections of the UI in separate panes and focus on the individual requirements of each section...
public class TestLayout11 {
public static void main(String[] args) {
new TestLayout11();
}
public TestLayout11() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ExamplePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class ExamplePane extends JPanel {
public ExamplePane() {
setLayout(new GridBagLayout());
JPanel buttonPane = new JPanel(new GridBagLayout());
JButton btnOkay = new JButton("Ok");
JButton btnCancel = new JButton("Cancel");
JTextArea textArea = new JTextArea(5, 20);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.CENTER;
buttonPane.add(btnOkay, gbc);
gbc.gridy++;
gbc.insets = new Insets(50, 0, 0, 0);
buttonPane.add(btnCancel, gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(100, 100, 100, 100);
add(buttonPane, gbc);
gbc.insets = new Insets(150, 100, 150, 100);
gbc.gridx++;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
add(new JScrollPane(textArea), gbc);
}
}
}

Related

Java Swing - position panel in top left of a JTabbedframe

I am having to migrate from Python TKinter to Java Swing due to a change of jobs.
The problem I have is:
How do I position a panel containing objects such as labels and text fields in the top left hand corner of JTabbedFrame.
If the frame itself is bigger than the panel , the JPanel is centering by default on the page.
Here is my code so far:
public class GUI {
//Constructor
GUI(){
//Craete a new frame
//borderlayout
JFrame jfrm = new JFrame("Tabbed Demo");
//Intialize size
jfrm.setSize(500, 250);
//Terminate program
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create Tabbed Frame
JTabbedPane jtp = new JTabbedPane(JTabbedPane.TOP);
//Create a panel to place on tabbed page
JPanel jpnl = new JPanel();
jpnl.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5,5,5,5);
jpnl.setOpaque(true);
jpnl.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
//create a 3 labels horizontally
gbc.gridx=1;
gbc.gridy=0;
JLabel title= new JLabel(" Tracking System ");
title.setFont(new Font("Serif", Font.PLAIN, 40));
jpnl.add(title,gbc);
gbc.gridx=0;
gbc.gridy=1;
JLabel subtitle= new JLabel("First");
subtitle.setFont(new Font("Serif", Font.PLAIN, 18));
jpnl.add(subtitle,gbc);
gbc.gridx=1;
gbc.gridy=1;
JTextArea firstText = new JTextArea("Type Here!");
firstText.setFont(new Font("Serif", Font.PLAIN, 18));
jpnl.add(firstText,gbc);
gbc.gridx=0;
gbc.gridy=2;
JLabel subtitle2= new JLabel("Last");
jpnl.add(subtitle2,gbc);
subtitle2.setFont(new Font("Serif", Font.PLAIN, 18));
//add to Tab
jtp.addTab("Demo", jpnl);
//make visible
jfrm.getContentPane().add(jtp);
jfrm.setVisible(true);
}
public static void main(String[] args) {
// launch app
//create the frame on the event dispaytching thread
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new GUI();
}
});
}
}
The result is shown below
What I want to do is move the location of the JPanel to the top left no matter how big the frame is, eg location 0,0 of the tabbed page.Override the centring of the JPanel.
I am using the GridBaglayout manager.
Not to discount the power of something like MigLayout, but if you're stuck on a project which limits third party libraries, then knowing how to manipulate the default layout managers is one of the most important skills you can develop
You could simply add a "filler" component into you layout, setting it's weightx and weighty properties to fill the available space
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestLayout {
public static void main(String[] args) {
new TestLayout();
}
public TestLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2; //GridBagConstraints.REMAINDER;
gbc.insets = new Insets(4, 4, 4, 4);
JLabel title = new JLabel("Tracking System");
title.setFont(title.getFont().deriveFont(40f));
add(title, gbc);
gbc.gridy++;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.WEST;
add(new JLabel("First: "), gbc);
gbc.gridy++;
add(new JLabel("First: "), gbc);
gbc.gridx++;
gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JTextField(10), gbc);
gbc.gridy++;
add(new JTextField(10), gbc);
gbc.gridx++;
gbc.gridy++;
gbc.weightx = 1;
gbc.weighty = 1;
// Blank/filler component
add(new JLabel(), gbc);
}
}
}
By changing
gbc.gridwidth = 2; //GridBagConstraints.REMAINDER;
to
gbc.gridwidth = GridBagConstraints.REMAINDER;
I can effect the position of the title as well
But you can also effect it by using the anchor property. Which you use will come down to your needs
Have a look at How to Use GridBagLayout for more details

Resize and placement of elements

public class InputURL {
public InputURL() {
input();
}
private static JFrame mainFrame = Launcher.returnFrame();
private static JPanel mainPanel;
private void input(){
//Defining a Panel on which everything will be set
mainPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
//To put the GridBagLayout Constraints
GridBagConstraints c = new GridBagConstraints();
//Set Panel Size
mainPanel.setSize(Constants.windowWidth,Constants.windowHeight);
//Setting the Input Box
JTextField inputURL = new JTextField();
c.fill = GridBagConstraints.CENTER;
c.ipady = 50;
c.weightx = 0.0;
c.gridwidth = 3;
c.gridx = 0;
c.gridy = 1;
mainPanel.add(inputURL, c);
//Adding the start button
JButton submitURL = new JButton(Constants.SUBMIT_URL_BUTTON);
submitURL.addActionListener(new ActionListener() {
//The action performed by the start button
public void actionPerformed(ActionEvent e)
{
//Execute when button is pressed
}
});
//The placement of the button
c.fill = GridBagConstraints.VERTICAL;
c.ipady = 50;
c.weightx = 0.0;
c.gridwidth = 3;
c.gridx = 0;
c.gridy = 2;
mainPanel.add(submitURL, c);
//Adding the components on Panel to Frame
mainFrame.add(mainPanel);
}
}
The ouput and expected output can be viewed here. Need help regarding the Output. E.G.:
I've tried using GridBagConstraints and for some reason I cannot play much with the UI.
A lot will come down to you final needs, for example, this just makes use of some of the basic properties of GridBagConstraints
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestLayout {
public static void main(String[] args) {
new TestLayout();
}
public TestLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextField inputURL;
private JButton submitURL ;
public TestPane() {
inputURL = new JTextField(20);
submitURL = new JButton("Submit the URL");
submitURL.setMargin(new Insets(10, 10, 10, 10));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(10, 10, 10, 10);
add(new JLabel("Header"), gbc);
gbc.gridy++;
gbc.insets = new Insets(0, 10, 20, 10);
add(inputURL, gbc);
gbc.gridy++;
gbc.insets = new Insets(0, 0, 0, 0);
gbc.weighty = 1.0;
add(submitURL, gbc);
}
}
}
A more complex solution might make use of compound layouts, using a mixture of BorderLayout, GridLayout and GridBagLayout
For example...
public class TestPane extends JPanel {
private JTextField inputURL;
private JButton submitURL ;
public TestPane() {
setLayout(new BorderLayout());
JLabel header = new JLabel("Header");
header.setHorizontalAlignment(JLabel.CENTER);
header.setBorder(new EmptyBorder(10, 10, 10, 10));
add(header, BorderLayout.NORTH);
inputURL = new JTextField(20);
submitURL = new JButton("Submit the URL");
submitURL.setMargin(new Insets(10, 10, 10, 10));
JPanel content = new JPanel(new GridLayout(2, 1));
JPanel field = new JPanel(new GridBagLayout());
field.add(inputURL);
content.add(field);
JPanel actions = new JPanel(new GridBagLayout());
actions.add(submitURL);
content.add(actions);
add(content);
}
}
While it might sound stupid, spend more time focusing on the actual workflow of the user, this will lead you to the best layout decisions, rather then focus on the physical layout itself

Layout Manager for background images and text

I'm trying to think of the best layout manager to achieve the picture below. I know absolute positioning is what I am used to, but I can't get the background image using this. GridBagLayout is excellent, but horrifically hard when ever I try I get a separate image for each grid.
Does anyone know an easy way out of this, or easy code to achieve the following?
There are several ways to do it. These are what I can think of at the moment:
Create a subclass of JComponent.
Override the paintComponent(Graphics g) method to paint the image that you want to display.
Set the content pane of the JFrame to be this subclass.
Some sample code:
class ImagePanel extends JComponent {
private Image image;
public ImagePanel(Image image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
}
}
// elsewhere
BufferedImage myImage = ImageIO.read(...);
JFrame myJFrame = new JFrame("Image pane");
myJFrame.setContentPane(new ImagePanel(myImage));
Note that this code does not handle re-sizing the image to fit the JFrame, if that's what you wanted.
There are a number of ways you can achieve this.
The simplest might be to just use what's already available...
If you don't need the background to be scaled at run-time (ie you can get away with a non-resizable window), simply using a JLabel as the primary container could make your life significantly easier.
public class LabelBackground {
public static void main(String[] args) {
new LabelBackground();
}
public LabelBackground() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new LoginPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class LoginPane extends JLabel {
public LoginPane() {
try {
setIcon(new ImageIcon(ImageIO.read(getClass().getResource("/background.jpg"))));
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.EAST;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel nameLabel = new JLabel("Name: ");
nameLabel.setForeground(Color.WHITE);
JLabel passwordLabel = new JLabel("Password: ");
passwordLabel.setForeground(Color.WHITE);
add(nameLabel, gbc);
gbc.gridy++;
add(passwordLabel, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx++;
gbc.gridy = 0;
add(new JTextField(20), gbc);
gbc.gridy++;
add(new JTextField(20), gbc);
gbc.gridy++;
gbc.insets = new Insets(10, 2, 2, 2);
gbc.anchor = GridBagConstraints.EAST;
add(new JButton("Submit"), gbc);
}
}
}
Updated with example of left alignment
At the end of the constructor, add...
JPanel filler = new JPanel();
filler.setOpaque(false);
gbc.gridx++;
gbc.weightx = 1;
add(filler, gbc);
You might like to take a look at How to use GridBagLayout for more details

Line up swing components by edges

Is it possible to line up swing components?
The components are in separate panels which both use flow layout. These two panels are in another panel which is using a grid layout.
As you can see there is a subtle difference and I find it annoying. I know that all of the jlabels [the rectangles in blue/purple all have the same size, so i think it might be because of the '+' and '*', but I'm not sure because the left sides of the first two boxes aren't lined up.
the panels
JPanel panel2 = new JPanel(new GridLayout(4, 1));
JPanel panel2a = new JPanel(new FlowLayout());
JPanel panel2b = new JPanel(new FlowLayout());
the first two rectangles (purple)
add1 = new JLabel("", JLabel.CENTER);
add1.setTransferHandler(new TransferHandler("text"));
add1.setBorder(b2);
add2 = new JLabel("", JLabel.CENTER);
add2.setTransferHandler(new TransferHandler("text"));
add2.setBorder(b2);
the two blue rectangles
textFieldA = new JTextField();
textFieldA.setHorizontalAlignment(JTextField.CENTER);
textFieldA.setEditable(false);
textFieldA.setBorder(new LineBorder(Color.blue));
textFieldM = new JTextField();
textFieldM.setHorizontalAlignment(JTextField.CENTER);
textFieldM.setEditable(false);
textFieldM.setBorder(new LineBorder(Color.blue));
the + and *
opA = new JLabel("+", JLabel.CENTER);
opS = new JLabel("*", JLabel.CENTER);
Showing that the rectangles are the same size
Dimension d = card1.getPreferredSize();
int width = d.width + 100;
int height = d.height + 50;
add1.setPreferredSize(new Dimension(width, height));
add2.setPreferredSize(new Dimension(width, height));
mult1.setPreferredSize(new Dimension(width, height));
mult2.setPreferredSize(new Dimension(width, height));
textFieldA.setPreferredSize(new Dimension(width, height));
textFieldM.setPreferredSize(new Dimension(width, height));
Adding to the panels
panel2a.add(add1);
panel2a.add(opA);
panel2a.add(add2);
panel2a.add(enterA);
panel2a.add(textFieldA);
panel2c.add(mult1);
panel2c.add(opM);
panel2c.add(mult2);
panel2c.add(enterM);
panel2c.add(textFieldM);
panel2.add(panel2a);
panel2.add(panel2c);
AFAIU this could be achieved using GroupLayout. This layout would require 5 horizontal groups and 2 vertical groups.
See How to Use GroupLayout for examples (including discussion of that image).
See also this answer for an MCVE.
Cross container layout management isn't really possible (or at least I've never seen a layout manager that does it).
You can, however, think carefully about your layout requirements and produce some interesting effects using compound components and layout managers...
public class TestLayout {
public static void main(String[] args) {
new TestLayout();
}
public TestLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(2, 0));
frame.add(new CalculatePane("+"));
frame.add(new CalculatePane("x"));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CalculatePane extends JPanel {
public CalculatePane(String operator) {
setLayout(new GridBagLayout());
Font font = UIManager.getFont("TextField.font").deriveFont(Font.BOLD, 24);
JTextField field1 = new JTextField(2);
JTextField field2 = new JTextField(2);
JTextField field3 = new JTextField(2);
field1.setFont(font);
field2.setFont(font);
field3.setFont(font);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.fill = GridBagConstraints.BOTH;
add(field1, gbc);
gbc.gridx++;
add(new JLabel(operator), gbc);
gbc.gridx++;
add(field2, gbc);
gbc.gridx++;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JButton("="), gbc);
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx++;
add(field3, gbc);
}
}
}

Which Layout Manager to use? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
So basically I want to create this sort of a GUI, but because of my inexperience with Java GUIs, I cannot figure out which Layout Manager to use. I've tried Flow, Border, Grid, but none of them allow me to create this sort of a GUI without messing up the alignments somewhere.
Any suggestions? How should I decide on a layout manager in the future, or is it something which will come with experience?
I'd prefer to use a simple to use layout, as this is a very basic GUI and I don't think something like MiGLayout should be necessary.
I'd use a combination of compound panels and layouts. Apart from making easier to get the layout to work, you could also isolate areas of responsibility within their own class.
public class TestLayout13 {
public static void main(String[] args) {
new TestLayout13();
}
public TestLayout13() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new FormPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class FormPane extends JPanel {
public FormPane() {
setBorder(new EmptyBorder(8, 8, 8, 8));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
NamePane namePane = new NamePane();
namePane.setBorder(new CompoundBorder(new TitledBorder("Name"), new EmptyBorder(4, 4, 4, 4)));
add(namePane, gbc);
gbc.gridy++;
EMailPane emailPane = new EMailPane();
emailPane.setBorder(new CompoundBorder(new TitledBorder("E-Mail"), new EmptyBorder(4, 4, 4, 4)));
add(emailPane, gbc);
}
}
public class NamePane extends JPanel {
public NamePane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("First Name:"), gbc);
gbc.gridx += 2;
add(new JLabel("Last Name:"), gbc);
gbc.gridy++;
gbc.gridx = 0;
add(new JLabel("Title:"), gbc);
gbc.gridx += 2;
add(new JLabel("Nickname:"), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 0.5;
add(new JTextField(10), gbc);
gbc.gridx += 2;
add(new JTextField(10), gbc);
gbc.gridy++;
gbc.gridx = 1;
add(new JTextField(10), gbc);
gbc.gridx += 2;
add(new JTextField(10), gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 0;
gbc.fill = GridBagConstraints.NONE;
add(new JLabel("Format:"), gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx++;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JComboBox(), gbc);
}
}
protected class EMailPane extends JPanel {
public EMailPane() {
JPanel detailsPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
detailsPane.add(new JLabel("E-Mail Address:"), gbc);
gbc.gridx++;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
detailsPane.add(new JTextField(10), gbc);
gbc.gridy++;
gbc.gridx = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.weighty = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;
detailsPane.add(new JScrollPane(new JList()), gbc);
JPanel buttonsPane = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
buttonsPane.add(new JButton("Add"), gbc);
gbc.gridy++;
buttonsPane.add(new JButton("Edit"), gbc);
gbc.gridy++;
buttonsPane.add(new JButton("Delete"), gbc);
gbc.gridy++;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.NORTH;
buttonsPane.add(new JButton("As Default"), gbc);
JPanel formatPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
formatPane.setBorder(new TitledBorder(new EmptyBorder(1, 1, 1, 1), "Mail Format:"));
formatPane.add(new JRadioButton("HTML"));
formatPane.add(new JRadioButton("Plain"));
formatPane.add(new JRadioButton("Custom"));
setLayout(new BorderLayout());
add(detailsPane);
add(buttonsPane, BorderLayout.LINE_END);
add(formatPane, BorderLayout.PAGE_END);
}
}
}
My preference is MigLayout because it is the most complete and well documented layout manager for Swing. In addition to Swing, it also supports SWT and JavaFX, so the time you spend learning it may pay back more than once. It supports maven, refer to http://www.miglayout.com for details, which is a big plus. Also it has a very useful debug feature. You can add "debug 1" in the constructor, and you will se how the layout was created. Example:
emailButtonPanel.setLayout(new MigLayout("wrap, fill, insets 20 10 0 10, debug 1"));
Another feature that I find very useful from time to time, is the hidemode, which allows you that a component does not take part in the layout if not visible (or several other strategies).
Here is one possible approach for the image you posted, using MigLayout:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import net.miginfocom.layout.CC;
import net.miginfocom.swing.MigLayout;
/**
*/
public class LayoutApproach {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Contact information");
frame.getContentPane().add(new ContactPanel());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(800, 450));
frame.setLocationRelativeTo(null); // Center
frame.pack();
frame.setVisible(true);
}
});
}
static class ContactPanel extends JPanel {
private JPanel namePanel;
private TitledBorder nameTitledBorder;
private JLabel firstNameLabel;
private JTextField firstNameTextField;
private JLabel lastNameLabel;
private JTextField lastNameTextField;
private JLabel titleLabel;
private JTextField titleTextField;
private JLabel nicknameLabel;
private JTextField nickNameTextField;
private JLabel formatLabel;
private JComboBox<String> formatComboBox;
private JPanel emailPanel;
private TitledBorder emailTitledBorder;
private JLabel emailLabel;
private JTextField emailTextField;
private JList<String> emailItemsList;
private JLabel mailFormatLabel;
private JPanel emailButtonPanel;
private JButton addButton;
private JButton editButton;
private JButton removeButton;
private JButton asDefaultButton;
private JRadioButton htmlRadioButton;
private JRadioButton plainTextRadioButton;
private JRadioButton customTextRadioButton;
private JPanel buttonPanel;
private JButton okButton;
private JButton cancelButton;
public ContactPanel() {
createComponents();
makeLayout();
createHandlers();
registerHandlers();
initComponent();
i18n();
}
/**
* Create GUI components, but contains no layout.
*/
public void createComponents() {
namePanel = new JPanel();
nameTitledBorder = new TitledBorder("");
firstNameLabel = new JLabel();
firstNameTextField = new JTextField();
lastNameLabel = new JLabel();
lastNameTextField = new JTextField();
titleLabel = new JLabel();
titleTextField = new JTextField();
nicknameLabel = new JLabel();
nickNameTextField = new JTextField();
formatLabel = new JLabel();
formatComboBox = new JComboBox<>();
emailPanel = new JPanel();
emailTitledBorder = new TitledBorder("");
emailLabel = new JLabel();
emailTextField = new JTextField();
emailItemsList = new JList<>();
mailFormatLabel = new JLabel();
emailButtonPanel = new JPanel();
addButton = new JButton();
editButton = new JButton();
removeButton = new JButton();
asDefaultButton = new JButton();
htmlRadioButton = new JRadioButton();
plainTextRadioButton = new JRadioButton();
customTextRadioButton = new JRadioButton();
buttonPanel = new JPanel();
okButton = new JButton();
cancelButton = new JButton("Cancel");
}
/**
* Create listeners/handlers
*/
public void createHandlers() {
}
/**
* Registers/adds listeners/handlers.
*/
public void registerHandlers() {
}
public void makeLayout() {
layoutNamePanel();
layoutEmailPanel();
layoutButtonPanel();
MigLayout migLayout = new MigLayout("fill, insets 20");
setLayout(migLayout);
add(namePanel, "dock north");
add(emailPanel, "dock north");
add(buttonPanel, "dock south");
}
private void layoutButtonPanel() {
buttonPanel.setLayout(new MigLayout("alignX right"));
buttonPanel.add(okButton, "tag ok");
buttonPanel.add(cancelButton, "tag cancel");
}
private void layoutNamePanel() {
MigLayout nameLayout = new MigLayout("fill, wrap 4", // Layout Constraints
"15[]15[grow]15[]15[grow]", // Column constraints
""); // Row constraints
// -- Layout all components with name
namePanel.setLayout(nameLayout);
// Create this border here since I use it for layout
Border nameBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 6, 10, 6), nameTitledBorder);
namePanel.setBorder(nameBorder);
namePanel.add(firstNameLabel, "alignX right");
namePanel.add(firstNameTextField, "grow");
namePanel.add(lastNameLabel, "alignX right");
namePanel.add(lastNameTextField, "grow");
namePanel.add(titleLabel, "alignX right");
namePanel.add(titleTextField, "grow");
namePanel.add(nicknameLabel, "alignX right");
namePanel.add(nickNameTextField, "grow");
namePanel.add(formatLabel, "alignX right");
namePanel.add(formatComboBox, new CC().grow().span(3)); // Alternative to using plain text'
}
private void layoutEmailPanel() {
MigLayout emailLayout = new MigLayout("fill",// Layout Constraints
"", // Column constraints
""); // Row constraints
// -- Layout all components with name
emailPanel.setLayout(emailLayout);
// Create this border here since I use it for layout
Border emailBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 6, 10, 6), emailTitledBorder);
emailPanel.setBorder(emailBorder);
emailButtonPanel.setLayout(new MigLayout("wrap, fill, insets 20 10 0 10"));
emailButtonPanel.add(addButton, "growx");
emailButtonPanel.add(editButton, "growx");
emailButtonPanel.add(removeButton, "growx");
emailButtonPanel.add(asDefaultButton, "growx");
JPanel emailAndItems = new JPanel(new MigLayout("fill"));
emailAndItems.add(emailLabel, "split 2");
emailAndItems.add(emailTextField, "span, growx, wrap");
emailAndItems.add(emailItemsList, "span, grow");
JPanel radioButtons = new JPanel(new MigLayout());
radioButtons.add(htmlRadioButton);
radioButtons.add(plainTextRadioButton);
radioButtons.add(customTextRadioButton);
emailPanel.add(radioButtons, "dock south");
emailPanel.add(mailFormatLabel, "dock south, gapleft 15");
emailPanel.add(emailAndItems, "dock west, growx, push");
emailPanel.add(emailButtonPanel, "dock east, shrink");
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(htmlRadioButton);
buttonGroup.add(plainTextRadioButton);
buttonGroup.add(customTextRadioButton);
}
/**
* Sets initial values for component.
*/
public void initComponent() {
formatComboBox.addItem("Item 1");
formatComboBox.addItem("Item 2");
formatComboBox.addItem("Item 3");
formatComboBox.addItem("Item 4");
DefaultListModel<String> model = new DefaultListModel<>();
emailItemsList.setModel(model);
model.insertElementAt("Item 1", 0);
model.insertElementAt("Item 2", 1);
model.insertElementAt("Item 3", 2);
model.insertElementAt("Item 4", 3);
customTextRadioButton.setSelected(true);
}
public void i18n() {
nameTitledBorder.setTitle("Name:");
firstNameLabel.setText("First Name:");
lastNameLabel.setText("Last Name:");
titleLabel.setText("Title:");
nicknameLabel.setText("Nickname:");
formatLabel.setText("Format:");
emailTitledBorder.setTitle("E-mail");
emailLabel.setText("E-mail address:");
mailFormatLabel.setText("Mail Format:");
addButton.setText("Add");
editButton.setText("Edit");
removeButton.setText("Remove");
asDefaultButton.setText("As Default");
htmlRadioButton.setText("HTML");
plainTextRadioButton.setText("Plain Text");
customTextRadioButton.setText("Custom");
okButton.setText("OK");
cancelButton.setText("Cancel");
}
}
}
The code was written in Java 7. A maven pom.xml file to go with it could be something like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>stackoverflow</groupId>
<artifactId>stackoverflow</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.miglayout</groupId>
<artifactId>miglayout-core</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>com.miglayout</groupId>
<artifactId>miglayout-swing</artifactId>
<version>4.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
I'd say border layout will work alright for you if you are looking for Java library layout managers. A more advanced one would be MiG Layout. You can google it for the info.
You do know that you can nest layout managers right? As in, one JPanel has one layoutmanager and another has a different one. So one could have border layout and another flow layout.
You can try NetBeans if you want a simple Swing designer, but IMHO Miglayout is the shortest way to get your UI's done as you intended. After the initial learning curve of course...
Try to visualize your screen in grids, and then you can use both gridbag and miglayout.

Categories

Resources