Which Layout Manager to use? [closed] - java

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.

Related

How to update Jpanel using JComboBox

i'm new in java language, and i'm trying to create a GUI which it has JComboBox to allow the user to select one of the choices and based on the selected option the panel is updated by adding more text fields.
currently i'm facing an issue which is the panel doesn't updated if I choosed (choice 1) it should appear 5 text fields with their labels.
My question is: how can I update the panel to add more text fields based on the selected option from JComboBox by the user?
Also, I'm facing another issue which i couldn't find a way to setting the size of JFrame
Here is my code:
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class RTSS extends JFrame implements ActionListener {
private JComboBox cb;
JPanel main;
JPanel panel3;
JPanel panel2;
JPanel panel1;
GridBagConstraints gbc;
String[] choices;
JLabel Label1;
JLabel Label2;
JLabel Label3;
JLabel Label4;
JLabel Label5;
JTextField tf1;
JTextField tf2;
JTextField tf3;
JTextField tf4;
JTextField tf5;
public RTSS() {
Border blackline = BorderFactory.createLineBorder(Color.black);
EmptyBorder b1 = new EmptyBorder(5, 0, 0, 0);
main = new JPanel(new FlowLayout(FlowLayout.LEFT));
panel3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
panel3.setAlignmentX(1);
panel3.setPreferredSize(new Dimension(800, 35));
panel3.setBorder(b1);
main.add(panel3);
panel2 = new JPanel();
panel1 = new JPanel();
panel1.setPreferredSize(new Dimension(700, 500));
panel1.setBorder(blackline);
panel1.setLayout(new GridBagLayout());
gbc = new GridBagConstraints();
choices = new String[]{ "","Choice 1", "Choice 2", "Choice 3 "};
cb = new JComboBox(choices);
//Main inputs (labels)
Label1 = new JLabel("Label 1 ");
Label2 = new JLabel("Label 2 ");
Label3 = new JLabel("Label 3");
Label4 = new JLabel("Label 4 ");
Label5 = new JLabel("Label 5 ");
//TextFields
tf1 = new JTextField(10);
tf2 = new JTextField(10);
tf3 = new JTextField(10);
tf4 = new JTextField(10);
tf5 = new JTextField(10);
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.insets = new Insets(10, 3, 5, 0);
panel3.add(cb);
panel2.add(panel1);
gbc.gridx = 0;
gbc.gridy = 0;
panel1.add(Label1, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
panel1.add(Label2, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
panel1.add(Label3, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
panel1.add(tf1, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
panel1.add(tf2, gbc);
gbc.weightx = 0.5;
gbc.weighty = 0.5;
gbc.gridx = 1;
gbc.gridy = 2;
panel1.add(tf3, gbc);
main.add(panel2);
add(main);
}
#Override
public void actionPerformed(ActionEvent e) {
String Choice = cb.getSelectedItem().toString();
if ("Choice 1".equals(Choice)) {
gbc.gridx = 0;
gbc.gridy = 3;
panel1.add(Label4, gbc);
gbc.gridx = 1;
gbc.gridy = 3;
panel1.add(tf4, gbc);
gbc.gridx = 0;
gbc.gridy = 4;
panel1.add(Label5, gbc);
gbc.weightx = 6;
gbc.weighty = 1;
gbc.gridx = 1;
gbc.gridy = 4;
panel1.add(tf5, gbc);
}
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
ex.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new RTSS().setVisible(true);
}
});
}
}
Add the following lines to the end of the RTSS constructor:
public RTSS() {
//your code
//this lines
pack();
setLocationRelativeTo(null);
cb.addActionListener(this);
}
These 3 lines will 1.set the layout, 2. center the frame and 3. activate the ActionListener.
If you now make a selection in the ComboBox, your code will be executed in the ActionListener.
After a selection in the ComboBox that changes the layout, call pack() again.
#Override
public void actionPerformed(ActionEvent e) {
String Choice = cb.getSelectedItem().toString();
if ("Choice 1".equals(Choice)) {
// your code
pack();
}
}

How to add and remove components from particular coordinates in GridBagLayout?

I am new to swing, am trying to make a form in which you can navigate to different panels by the click of buttons on the left-hand side, to fill out forms(panels) appearing on the right-hand side, and I am using the GridBagLayout for the purpose. I am trying to remove the current panel on the click of the JButton and then add the corresponding panels I created by extending JPanel to classes. For ex., if I click on the accountDetailsButton, I wish to open up the accountDetails Panel, somewhat like switching tabs. I want to replace whichever panel is open on that position with the accountDetails Panel, and since any tab may be open, I need to exchange the panel on the basis of coordinates instead of the component name. I don't know how to go about it as I want to remove and add components on the basis of coordinates on the frame, and the name of the components may not be known. Here's the code.
Thanks a lot in advance!
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class FormWindow {
private CustomerProfile customerProfile;
private AccountDetails accountDetails;
private LoanDetails loanDetails;
private DocumentUpload documentUpload;
private JPanel mainPanel;
private JLabel logo;
private JButton customerProfileButton;
private JButton accountDetailsButton;
private JButton loanDetailsButton;
private JButton documentUploadButton;
private JPanel bufferPanel;
public static void main(String[] args) {
JFrame frame = new JFrame("FormWindow");
frame.setContentPane(new FormWindow().mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
FormWindow() {
mainPanel = new JPanel();
bufferPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
customerProfile = new CustomerProfile();
accountDetails = new AccountDetails();
loanDetails = new LoanDetails();
documentUpload = new DocumentUpload();
// fieldForm.setLayout(new GridBagLayout());
GridBagConstraints gbc;
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gbc.gridheight = 5;
gbc.fill = GridBagConstraints.BOTH;
bufferPanel.add(customerProfile);
mainPanel.add(bufferPanel, gbc);
final GridBagConstraints gbcForms = gbc;
logo = new JLabel();
logo.setText("LOGO");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(5, 5, 10, 5);
mainPanel.add(logo, gbc);
customerProfileButton = new JButton();
customerProfileButton.setText("Customer Profile");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
mainPanel.add(customerProfileButton, gbc);
accountDetailsButton = new JButton();
accountDetailsButton.setText("Account Details");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
mainPanel.add(accountDetailsButton, gbc);
loanDetailsButton = new JButton();
loanDetailsButton.setText("Loan Details");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
mainPanel.add(loanDetailsButton, gbc);
documentUploadButton = new JButton();
documentUploadButton.setText("Document Upload");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 4;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
mainPanel.add(documentUploadButton, gbc);
//adding action listeners to buttons
customerProfileButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
}
});
accountDetailsButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
}
});
loanDetailsButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
}
});
documentUploadButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
}
});
}
}
I wish to display the corresponding panel on the right-hand side of the frame when the corresponding button is clicked. For ex., if I click the accountDetailsButton, I want to replace the previously visible panel with the accountDetails panel (the code for accountDetails has the accountDetails class extending JPanel). This is done to get the feel of switching between tabs in a way.

How to get JButton to fill BoxLayout vertically?

It's easiest to explain with a picture, so here it goes. This is how it looks right now:
I am trying to get all JButtons to to be same size, i.e to fill out the BoxLayout completely vertically.
Here is my code:
public class TestarBara extends JFrame implements ActionListener{
JButton heyy;
public static void main(String[] args){
new TestarBara();
}
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
public TestarBara(){
super("knapparnshit");
panel.setLayout(new GridLayout(3,3,2,2));
for(int x=1; x < 10; x++){
String y = Integer.toString(x);
JButton button = new JButton(y);
button.addActionListener(this);
panel.add(button);
}
add(panel, BorderLayout.CENTER);
JButton b1 = new JButton("this");
JButton b2 = new JButton("does");
JButton b3 = new JButton("not");
JButton b4 = new JButton("work");
panel2.setLayout(new BoxLayout(panel2, BoxLayout.PAGE_AXIS));
panel2.add(b1);
panel2.add(Box.createRigidArea(new Dimension(0,4)));
panel2.add(b2);
panel2.add(Box.createRigidArea(new Dimension(0,4)));
panel2.add(b3);
panel2.add(Box.createRigidArea(new Dimension(0,4)));
panel2.add(b4);
panel2.setBorder(BorderFactory.createBevelBorder(1));
add(panel2, BorderLayout.WEST);
Dimension dim = panel2.getPreferredSize();
b1.setPreferredSize(dim);
b2.setPreferredSize(dim);
b3.setPreferredSize(dim);
b4.setPreferredSize(dim);
setResizable(true);
setSize(300,300);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
#Override
public void actionPerformed(ActionEvent e) {
Object button = e.getSource();
if(button instanceof JButton){
((JButton) button).setEnabled(false);
((JButton) button).setText("dead");
Toolkit.getDefaultToolkit().beep();
}
}
}
What do I need to do so the JButtons all are the same size, and all of them going all the way to the left?
The problem is BoxLayout will honour the preferredSize of the individual components, you'd be better off with a layout manager that provided you with more control, like GridBagLayout, for example...
panel2.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(0, 0, 4, 0);
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
panel2.add(b1, gbc);
panel2.add(b2, gbc);
panel2.add(b3, gbc);
gbc.insets = new Insets(0, 0, 0, 0);
panel2.add(b4, gbc);
Or GridLayout...
panel2.setLayout(new GridLayout(0, 1, 0, 4));
panel2.add(b1);
panel2.add(b2);
panel2.add(b3);
panel2.add(b4);

how to add a TiltledBorder in a GridBagLayout?

I am trying to make an UI with Swing using only one Container with the GridBagLayout !
My problem is that I want to regroup some JtextFields and Jlabels under one title (TitledBorder) in my interface, is there a way to add the border directly in my container, or should I create another JPanel to regroup my components and then add the hole Panel to my GridBagLayout ?
Based on the pic you provided, the typical solution would be to have 2 separate panels, each with their own TitledBorder, and then place both of these panels on a third outer panel.
However, you could create a similar effect on a single panel by replacing the TitledBorders with a combination of a JLabel followed by a JSeparator.
The difference is that the logical "group" of fields is now only defined by title that isn't surrounding the whole group. Some people prefer this, others do not.
Here's a sample of your pic to give you the idea:
import java.awt.*;
import javax.swing.*;
public class Test implements Runnable
{
private JTextField firstName;
private JTextField lastName;
private JTextField title;
private JTextField nickname;
private JComboBox format;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Test());
}
public Test()
{
firstName = new JTextField(20);
lastName = new JTextField(20);
title = new JTextField(20);
nickname = new JTextField(20);
format = new JComboBox();
}
public void run()
{
JFrame frame = new JFrame();
frame.getContentPane().add(createPanel());
frame.pack();
frame.setVisible(true);
}
private JPanel createPanel()
{
JPanel p = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(4,4,4,4);
gbc.ipadx = 1;
gbc.ipady = 1;
gbc.anchor = GridBagConstraints.WEST;
JLabel nameHeader = new JLabel("Name:");
nameHeader.setForeground(Color.RED.darker());
p.add(nameHeader, gbc);
gbc.gridx = 1;
gbc.gridwidth = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
p.add(new JSeparator(JSeparator.HORIZONTAL), gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.NONE;
p.add(new JLabel("First Name"), gbc);
gbc.gridx = 1;
p.add(firstName, gbc);
gbc.gridx = 2;
p.add(new JLabel("Last Name"), gbc);
gbc.gridx = 3;
p.add(lastName, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
p.add(new JLabel("Title"), gbc);
gbc.gridx = 1;
p.add(title, gbc);
gbc.gridx = 2;
p.add(new JLabel("Nickname"), gbc);
gbc.gridx = 3;
p.add(nickname, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
p.add(new JLabel("Format"), gbc);
gbc.gridx = 1;
gbc.gridwidth = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
p.add(format, gbc);
return p;
}
}
You could play with the constraints to polish this up a bit, but you get the idea.
An upside to this approach is that when adding more fields for the Email section, you can get them to line up with the fields in the Name section. With separate panels, this would be more difficult (you could use a bunch of Box.createHorizontalStrut(...) for this).
The downside to this approach is that you now have a large panel with many fields, and it could get a bit unwieldy to maintain if you need to add more fields.
Try This :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
class SwingLayoutDemo {
private JFrame mainFrame;
private JLabel headerLabel;
private JLabel statusLabel;
private JPanel controlPanel;
private JLabel msglabel;
public SwingLayoutDemo(){
prepareGUI();
}
public static void main(String[] args){
SwingLayoutDemo swingLayoutDemo = new SwingLayoutDemo();
swingLayoutDemo.showGridBagLayoutDemo();
}
private void prepareGUI(){
mainFrame = new JFrame("Java SWING Examples");
mainFrame.setSize(400,400);
mainFrame.setLayout(new GridLayout(3, 1));
headerLabel = new JLabel("",JLabel.CENTER );
statusLabel = new JLabel("",JLabel.CENTER);
statusLabel.setSize(350,100);
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
controlPanel = new JPanel();
controlPanel.setBorder(new TitledBorder (
new LineBorder (Color.black, 5),
"Title String"));
controlPanel.add(new JLabel("TitledBorder using LineBorder"));
controlPanel.setLayout(new FlowLayout());
mainFrame.add(headerLabel);
mainFrame.add(controlPanel);
mainFrame.add(statusLabel);
mainFrame.setVisible(true);
}
private void showGridBagLayoutDemo(){
headerLabel.setText("Layout in action: GridBagLayout");
JPanel panel = new JPanel();
panel.setBackground(Color.darkGray);
panel.setSize(300,300);
GridBagLayout layout = new GridBagLayout();
panel.setLayout(layout);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
panel.add(new JButton("Button 1"),gbc);
gbc.gridx = 1;
gbc.gridy = 0;
panel.add(new JButton("Button 2"),gbc);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.ipady = 20;
gbc.gridx = 0;
gbc.gridy = 1;
panel.add(new JButton("Button 3"),gbc);
gbc.gridx = 1;
gbc.gridy = 1;
panel.add(new JButton("Button 4"),gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = 2;
panel.add(new JButton("Button 5"),gbc);
controlPanel.add(panel);
mainFrame.setVisible(true);
}
}

Multiple Panels Below Each Other

Is it possible i can have a top panel for a login. Then a middle and bottom panel underneath.
I'm using gridbaglayout and i have assigned 2 panels. One panel has components linked to it for login details and the other panel has other components linked to it. However, it's not going occurring to plan.
Ive tried using Box/Borderlayout to do this, but then i'm not able to create the spacing i want.
Here is a sketch of what i want.
public class GUI extends JFrame{
private JPanel myTopPL, myTopPL2;
private JTextField myUsernameTF;
private JTextField myPasswordTF;
private JTextField myMessageTF;
private JLabel myUsernameLBL;
private JLabel myPasswordLBL;
private JLabel myItemsLBL;
private JTextArea myMainTA;
private JButton myLoginBN;
private JButton myConnectBN;
private JButton mySendBN;
private JComboBox myItemsCB;
public GUI () {
super("GUI ");
setLayout(new GridBagLayout());
myTopPL = new JPanel();
myTopPL2 = new JPanel();
myTopPL.setLayout(new GridBagLayout());
myTopPL2.setLayout(new GridBagLayout());
GridBagConstraints myTopPLGBC = new GridBagConstraints();
myTopPLGBC.weightx = 1;
myTopPLGBC.weighty = 1;
GridBagConstraints myTopPLGBC2 = new GridBagConstraints();
myTopPLGBC.weightx = 2;
myTopPLGBC.weighty = 2;
myUsernameLBL = new JLabel("Username: ");
myUsernameLBL.setFont(new Font("Arial", Font.BOLD, 13));
myTopPLGBC.gridx = 1;
myTopPLGBC.gridy = 1;
myTopPLGBC.insets = new Insets(5,5,5,5);
myTopPL.add(myUsernameLBL, myTopPLGBC);
myUsernameTF = new JTextField(10);
myTopPLGBC.gridx = 2;
myTopPLGBC.gridy = 1;
myTopPLGBC.insets = new Insets(5,5,5,5);
myTopPL.add(myUsernameTF,myTopPLGBC);
myPasswordLBL = new JLabel("Password: ");
myPasswordLBL.setFont(new Font("Arial", Font.BOLD, 13));
myTopPLGBC.gridx = 3;
myTopPLGBC.gridy = 1;
myTopPLGBC.insets = new Insets(5,5,5,5);
myTopPL.add(myPasswordLBL, myTopPLGBC);
myPasswordTF = new JTextField(10);
myTopPLGBC.gridx = 4;
myTopPLGBC.gridy = 1;
myTopPLGBC.insets = new Insets(5,5,5,5);
myTopPL.add(myPasswordTF,myTopPLGBC);
myLoginBN = new JButton("Login");
myTopPLGBC.gridx = 5;
myTopPLGBC.gridy = 1;
myTopPLGBC.insets = new Insets(5,5,5,5);
myTopPL.add(myLoginBN,myTopPLGBC);
myItemsLBL = new JLabel("Items: ");
myItemsLBL.setFont(new Font("Arial", Font.BOLD, 13));
myTopPLGBC2.gridx = 1;
myTopPLGBC2.gridy = 3;
myTopPLGBC2.insets = new Insets(5,5,5,5);
myTopPL2.add(myItemsLBL, myTopPLGBC2);
myItemsCB = new JComboBox();
myItemsCB.addItem(" Select an Item ");
myTopPLGBC2.gridx = 1;
myTopPLGBC2.gridy = 4;
myTopPLGBC2.insets = new Insets(5,5,5,5);
myTopPL2.add(myItemsCB, myTopPLGBC2);
myConnectBN = new JButton("Connect");
myTopPLGBC2.gridx = 2;
myTopPLGBC2.gridy = 4;
myTopPLGBC2.insets = new Insets (5,5,5,5);
myTopPL2.add(myConnectBN, myTopPLGBC2);
GridBagConstraints GBC = new GridBagConstraints();
GBC.anchor = GridBagConstraints.NORTHWEST;
GBC.weightx = 1;
GBC.weighty = 1;
this.add(myTopPL,GBC);
GridBagConstraints GBC2 = new GridBagConstraints();
GBC2.anchor = GridBagConstraints.NORTHWEST;
GBC2.weightx = 2;
GBC2.weighty = 2;
this.add(myTopPL2,GBC2);
}
public static void main(String[] args) {
GUI GUI = new GUI ();
GUI .setDefaultCloseOperation(RMIAuctionHouse.EXIT_ON_CLOSE);
GUI .setSize(750,500);
GUI .setVisible(true);
}
}
I'd break down the application into it's individual areas of responsibilities and focus on creating the UI elements to support it. This will allow you to focus on the needs of each section of your application, it also allows you the opportunity to change around the layout as you need
public class TestLayout15 {
public static void main(String[] args) {
new TestLayout15();
}
public TestLayout15() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
private JTextField messageField;
private JButton sendButton;
public MainPane() {
setBorder(new EmptyBorder(4, 4, 4, 4));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new LoginPane(), gbc);
gbc.gridy++;
add(new ConnectPane(), gbc);
gbc.gridy++;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(new JScrollPane(new JTextArea(5, 20)), gbc);
gbc.gridwidth = 1;
messageField = new JTextField(10);
sendButton = new JButton("Send");
gbc.gridy++;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(messageField, gbc);
gbc.gridx++;
gbc.weightx = 0;
add(sendButton, gbc);
}
}
public class ConnectPane extends JPanel {
private JComboBox comboBox;
private JButton connectButton;
public ConnectPane() {
comboBox = new JComboBox();
connectButton = new JButton("Connect");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
add(comboBox, gbc);
gbc.gridx++;
gbc.weightx = 1;
add(connectButton, gbc);
}
}
public class LoginPane extends JPanel {
private JTextField userNameField;
private JPasswordField passwordField;
private JButton loginButton;
public LoginPane() {
userNameField = new JTextField(10);
passwordField = new JPasswordField(10);
loginButton = new JButton("Login");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
add(new JLabel("User name:"), gbc);
gbc.gridx++;
add(userNameField, gbc);
gbc.gridx++;
add(new JLabel("Password:"), gbc);
gbc.gridx++;
add(passwordField, gbc);
gbc.gridx++;
gbc.weightx = 1;
add(loginButton, gbc);
}
}
}
To start with, replace the call to GUI.setSize(750,500) with GUI.pack(). That will size the window to fit your content. After doing that you'll see the second panel is appearing to the right of the first. This is because you did not set gridx/gridy on GBC2 so it defaults to putting myTopPL2 to the right of myTopPL1, not below it.
I rarely explicitly set the gridx/gridy when using GridBagLayout. For your first row of the display, I would use default values for all but myLoginBN where I would set gridwidth to GridBagConstraints.REMAINDER. That tells GridBagLayout that nothing else goes on this row. The next item added with a default gbc will be placed at the start of the second row.
Minor nits:
Use standard Java capitalization:
Class name are camelcase with a leading uppercase character. So, "Gui", not "GUI".
Instance names are camelcase with a leading lowercase character. So, "gbc1" not "GBC1"
Use SwingUtilities.InvokeLater to start the Gui on the EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI GUI = new GUI ();
GUI .setDefaultCloseOperation(RMIAuctionHouse.EXIT_ON_CLOSE);
GUI .setSize(750,500);
GUI .setVisible(true);
}});
Seems you are not familiar with Java layouts, so i recomend you to try null(absolute) Layout:
setLayout(null);
...
component.setBounds( x, y, width, heigh );
add(component);
Here example
package gui;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GUI extends JFrame{
private JTextField myUsernameTF;
private JLabel myUsernameLBL;
public GUI() {
super("GUI ");
setLayout(null);
myUsernameLBL = new JLabel("Username: ");
myUsernameLBL.setFont(new Font("Arial", Font.BOLD, 13));
myUsernameLBL.setBounds(50,30,80,20);
add(myUsernameLBL);
myUsernameTF = new JTextField(10);
myUsernameTF.setBounds(190,30,80,20);
add(myUsernameTF);
// and so on ...
}
public static void main(String[] args) {
GUI frame = new GUI();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(750,500);
frame.setVisible(true);
}
}
Good luck on thorny way to handle java swing =)

Categories

Resources