I want to be able to click a JButton from my JFrame which opens up another window and in this 2nd window, I want to be able to input something into a text field on that window and get the information from that text field.
JButton myButton = new JButton("Click Here!");
public void actionPerformed (ActionEvent event)
{
if (event.getSource() == myButton) {
// open the new window }
I know how to define the components of this new JFrame, but how will I write an actionPerformed event for that new window since nesting modules isn't allowed?
Is there a way to customize the contents of the modal dialog window? For instance if I wanted 2 text fields in the pop up window (so it can take 2 inputs)? What if I wanted to change the "OK"/"Cancel" buttons to have different labels and/or behave differently?
A modal dialog (JDialog) or a JOptionPane, like a JFrame, can hold a JPanel that has the most complex GUI that you can imagine including nesting other JPanels that use whatever layouts are necessary and that contain multiple components. For example, the following code creates JOptionPane that displays a JPanel that holds a number of JTextFields, all extractable after the JOptionPane returns:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
public class ComplexDialogPanel extends JPanel {
public static final String[] LABEL_TEXTS = { "Last Name", "First Name",
"Address", "City", "State", "Zip" };
public static final int COLS = 8;
private Map<String, JTextField> labelFieldMap = new HashMap<>();
public ComplexDialogPanel() {
setLayout(new GridBagLayout());
for (int i = 0; i < LABEL_TEXTS.length; i++) {
String labelTxt = LABEL_TEXTS[i];
add(new JLabel(labelTxt), createGbc(0, i));
JTextField textField = new JTextField(COLS);
labelFieldMap.put(labelTxt, textField);
add(textField, createGbc(1, i));
}
setBorder(BorderFactory.createTitledBorder("Enter User Information"));
}
public String getText(String labelText) {
JTextField textField = labelFieldMap.get(labelText);
if (textField != null) {
return textField.getText();
} else {
throw new IllegalArgumentException(labelText);
}
}
public static GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.weightx = 1.0;
gbc.weighty = gbc.weightx;
if (x == 0) {
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(3, 3, 3, 8);
} else {
gbc.anchor = GridBagConstraints.LINE_END;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(3, 3, 3, 3);
}
return gbc;
}
private static void createAndShowGui() {
ComplexDialogPanel mainPanel = new ComplexDialogPanel();
int optionType = JOptionPane.DEFAULT_OPTION;
int messageType = JOptionPane.PLAIN_MESSAGE;
Icon icon = null;
String[] options = { "Submit", "Cancel" };
Object initialValue = options[0];
int reply = JOptionPane.showOptionDialog(null, mainPanel,
"Get User Information", optionType, messageType, icon, options,
initialValue);
if (reply == 0) {
System.out.println("Selections:");
for (String labelText : LABEL_TEXTS) {
System.out.printf("%12s: %s%n", labelText,
mainPanel.getText(labelText));
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Related
I am unable to change the colour of my frame in Java code below. I know the code to change it would be frame.getContentPane().setBackground(Color.gray); However, this is not working for me, I am not sure what is the reason behind this, but if you are able to solve the problem do let me know, thank you.
public class UserLoginPage implements ActionListener {
//Put all JLabels,Frames and buttons here etc
JPanel panel = new JPanel();
JFrame frame = new JFrame();
JLabel userLabel = new JLabel("Username");
JLabel passwordLabel = new JLabel("Password");
JTextField userText = new JTextField();
JTextField passwordText = new JTextField();
JButton loginButton = new JButton("Login");
//Label for successful login
JLabel success = new JLabel();
//Default Constructor to add the frames and panels etc
public UserLoginPage(){
panel.setLayout(null);
userLabel.setBounds(10,20,80,25);
panel.add(userLabel);
passwordLabel.setBounds(10,50,80,25);
panel.add(passwordLabel);
userText.setBounds(100,20,165,25);
panel.add(userText);
passwordText.setBounds(100,50,165,25);
panel.add(passwordText);
loginButton.setBounds(10,80,80,25);
loginButton.addActionListener(this);
panel.add(loginButton);
success.setBounds(10,110,300,25);
panel.add(success);
//success.setText();
frame.setSize(500,500);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.gray);
frame.setVisible(true);
frame.add(panel);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new UserLoginPage();
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
String user = userText.getText();
String password = passwordText.getText();
System.out.println(user + ", " + password);
if(user.equals("Jackson") && password.equals("1234")){
JOptionPane.showMessageDialog(frame,"Login successful");
}
else{
JOptionPane.showMessageDialog(frame,"Invalid password or username");
}
}
}
You're adding panel, a JPanel to your JFrame, and since JFrame's contentPane uses a BorderLayout, this JPanel (which is opaque), will completely cover the contentPane, preventing visualization of the contentPane's background.
Solution:
Either make the panel not-opaque via panel.setOpaque(false); so that now its container's colors or images will show through
or leave it default opaque give it and not the contentPane the background color of choice.
Unrelated issue is here:
panel.setLayout(null)
You really don't want to be doing this for many reasons, including because this will make your GUI work well / look nice on only one platform. It also makes it very hard to upgrade and enhance the GUI later.
For example, and incorporating some of Andrew Thompson's suggestions, here is an example login GUI that is geared towards creating a JPanel, one that in this example is placed into a modal JDialog (similar to a JOptionPane but with more flexibility) and displayed. The code uses GridBagLayout along with GridBagConstraints when adding components to place them where I want them to be in a pleasing way that works on all platforms, and that allows ease and flexibility should I want to add more components:
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class UserLoginPanel extends JPanel {
private static final Color BACKGROUND = new Color(200, 200, 200);
private JTextField userText = new JTextField(15);
private JPasswordField passwordText = new JPasswordField(15);
LoginAction loginAction = new LoginAction(this, "Login", KeyEvent.VK_L);
JButton loginButton = new JButton(loginAction);
public UserLoginPanel() {
super(new GridBagLayout());
setBackground(BACKGROUND);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
int insetGap = 4;
gbc.insets = new Insets(insetGap, insetGap, insetGap, insetGap);
add(new JLabel("User Name:"), gbc);
gbc.gridx = 1;
add(userText, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
add(new JLabel("Password"), gbc);
gbc.gridx = 1;
add(passwordText, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 2;
add(loginButton, gbc);
insetGap = 8;
setBorder(BorderFactory.createEmptyBorder(insetGap, insetGap, insetGap, insetGap));
}
public String getUserName() {
return userText.getText();
}
public char[] getPassword() {
return passwordText.getPassword();
}
public static void main(String[] args) {
UserLoginPanel loginPanel = new UserLoginPanel();
JDialog dialog = new JDialog(null, "User Login", ModalityType.APPLICATION_MODAL);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.add(loginPanel);
dialog.pack();
dialog.setLocationByPlatform(true);
dialog.setVisible(true);
}
}
#SuppressWarnings("serial")
class LoginAction extends AbstractAction {
private UserLoginPanel loginPanel;
public LoginAction(UserLoginPanel loginPanel, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_L);
this.loginPanel = loginPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
String userName = loginPanel.getUserName();
char[] password = loginPanel.getPassword();
System.out.println("User Name: " + userName);
System.out.println("Password: " + new String(password));
Component source = (Component) e.getSource();
if (source != null) {
Window window = SwingUtilities.getWindowAncestor(source);
if (window != null) {
window.dispose();
}
}
}
}
I am working with a list of elements that I want to rank. Ideally the program would randomly choose 2 elements to compare and present them, sort the list with the new ranking, then select 2 more so the user could pick the winner over and over again until the user wanted to stop. The parts I am having trouble with are:
getting the button to interact with the object to change its rank and
getting the JFrame to close and reopen with new elements to compare
I created a class called action that is supposed to handle the clicks:
public class action extends JFrame implements ActionListener{
private JButton b1;
private JButton b2;
private JButton b3;
private JPanel jp;
public action(Bond one, Bond two){
//JFrame mf = new JFrame("My Frame");
//JPanel jp = new JPanel();
jp = new JPanel();
setSize(500,500);
setVisible(true);
setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
b1 = new JButton(one.name+"\nRating: "+one.rating);
b1.addActionListener(this);
b2 = new JButton(two.name);
b2.addActionListener(this);
b3 = new JButton("Tie");
b3.addActionListener(this);
jp.add(b1);
jp.add(b2);
jp.add(b3);
add(jp);
}
public void actionPerformed(ActionEvent e){
int clickCount = 0;
if (clickCount > 3) {
System.exit(0);
}
JOptionPane jo = new JOptionPane();
if(e.getSource() == b1){
// jo.showMessageDialog(null, "button 1");
clickCount++;
//System.exit(0);
}
if(e.getSource() == b2){
jo.showMessageDialog(null, "button 2");
clickCount++;
//System.exit(0);
}
if(e.getSource() == b3){
jo.showMessageDialog(null, "button 3");
clickCount++;
//System.exit(0);
}
}
}
And here is how I am calling the action class from my main:
while(compCount < 3){
//these generate random numbers that correspond with the index of the elements to be compared
//comp is the name of the list of objects
int r1 = r.nextInt(comp.size());
int r2 = r.nextInt(comp.size());
int t;
if(r1 == r2){
continue;
}
else{
action a = new action(comp.get(r1), comp.get(r2));
compCount++;
}
}
Currently this just creates 3 popup windows that do nothing when I click the buttons.
Any help or insight would be appreciated!
The OP wants to make a complex Swing GUI. He didn't provide a minimal, runnable, example, so I created my own.
The best way to make a complex Swing GUI is to construct it one small piece at a time. By testing each small piece in isolation, you too can construct a complex GUI.
Here's the GUI I created.
The object of this game is to choose your favorite characters from the lower case characters of the English alphabet. You can left-click on the Pass button if neither character is among your favorites.
I'd already written the JPanel to display a character for a previous Stack Overflow answer.
The first thing I did was create the main class. I named this class FavoriteCharacter.
I called the SwingUtilities invokeLater method to ensure that the Swing components were created and executed on the Event Dispatch Thread.
Next, I wrote the JFrame code. The JFrame code is nearly identical for every Swing GUI I create. The JFrame code is located in the run method of the FavoriteCharacter class.
Next, I wrote the model class, the LetterMap class. Whenever I create a complex Swing GUI, I use the model / view / controller pattern. This model is pretty simple. I have a map that contains the lower case characters of the English alphabet, along with vote counts.
Once I had the model working, I went back to creating the view. Each small part of the GUI is contained in a method of the FavoriteCharacter class. That way, I could test each small piece of the view individually. No throwing spaghetti code against the wall and seeing what sticks for me.
The actual drawing of the characters happens in a LetterPanel class. All Swing custom painting must be done in the paintComponent method of a JPanel.
After I finished the GUI, I worked on the two controller classes, PassListener and VoteListener. PassListener calls a method in the FavoriteCharacters class to select another pair of characters. VoteListener updates the LetterMap model class, displays the vote total for the selected character in a JOptionPane, and selects another pair of letters.
Here's the runnable, example code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FavoriteCharacter implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new FavoriteCharacter());
}
private char[] letterPair;
private JFrame frame;
private LetterMap letterMap;
private LetterPanel letterPanel1;
private LetterPanel letterPanel2;
public FavoriteCharacter() {
this.letterMap = new LetterMap();
this.letterPair = letterMap.pickTwo();
}
#Override
public void run() {
frame = new JFrame("Favorite Character");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTitlePanel(),
BorderLayout.BEFORE_FIRST_LINE);
frame.add(createMainPanel(letterPair),
BorderLayout.CENTER);
frame.add(createSkipPanel(),
BorderLayout.AFTER_LAST_LINE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTitlePanel() {
JPanel panel = new JPanel();
JLabel label = new JLabel("Vote for your favorite character");
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label);
return panel;
}
private JPanel createMainPanel(char[] letterPair) {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(Box.createHorizontalStrut(10));
letterPanel1 = new LetterPanel(Color.WHITE, letterPair[0]);
panel.add(createLetterPanel(letterPanel1, "0"));
panel.add(Box.createHorizontalStrut(10));
letterPanel2 = new LetterPanel(Color.WHITE, letterPair[1]);
panel.add(createLetterPanel(letterPanel2, "1"));
panel.add(Box.createHorizontalStrut(10));
return panel;
}
private void updateLetterPanels() {
letterPanel1.setLetter(letterPair[0]);
letterPanel2.setLetter(letterPair[1]);
letterPanel1.repaint();
letterPanel2.repaint();
}
private void updateLetterPair() {
letterPair = letterMap.pickTwo();
System.out.println(Arrays.toString(letterPair));
updateLetterPanels();
}
private JPanel createLetterPanel(LetterPanel letterPanel,
String actionCommand) {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(0, 10, 10, 10);
gbc.weightx = 0d;
panel.add(letterPanel, gbc);
gbc.gridy++;
gbc.weightx = 1d;
JButton button = new JButton("Vote");
button.setActionCommand(actionCommand);
button.setHorizontalAlignment(JButton.CENTER);
button.addActionListener(new VoteListener());
panel.add(button, gbc);
return panel;
}
private JPanel createSkipPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(0, 18, 10, 18);
gbc.weightx = 1d;
JButton button = new JButton("Pass");
button.setHorizontalAlignment(JButton.CENTER);
button.addActionListener(new PassListener());
panel.add(button, gbc);
return panel;
}
public class LetterPanel extends JPanel {
private static final long serialVersionUID = 1L;
private char letter;
private Color backgroundColor;
private Font font;
public LetterPanel(Color backgroundColor, char letter) {
this.backgroundColor = backgroundColor;
this.letter = letter;
this.font = getFont().deriveFont(96f)
.deriveFont(Font.BOLD);
this.setBorder(BorderFactory.createLineBorder(
Color.GREEN, 6));
this.setPreferredSize(new Dimension(120, 200));
}
public void setLetter(char letter) {
this.letter = letter;
}
public char getLetter() {
return letter;
}
public LetterPanel getLetterPanel() {
return this;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(backgroundColor);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
drawCenteredString(g2d, Character.toString(letter),
font);
}
/**
* Draw a String centered in the middle of the panel.
*
* #param g2d The Graphics2D instance.
* #param text The String to draw.
* #param font The Font to draw with.
*/
public void drawCenteredString(Graphics2D g2d,
String text, Font font) {
FontMetrics metrics = g2d.getFontMetrics(font);
int x = (getWidth() - metrics.stringWidth(text)) / 2;
int y = ((getHeight() - metrics.getHeight()) / 2) +
metrics.getAscent();
g2d.setFont(font);
g2d.drawString(text, x, y);
}
}
public class PassListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
updateLetterPair();
}
}
public class VoteListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
int index = Integer.valueOf(event.getActionCommand());
char c = letterPair[index];
letterMap.addVote(c);
int votes = letterMap.getVotes(c);
showMessageDialog(c, votes);
}
private void showMessageDialog(char c, int votes) {
String text = "The character '" + c + "' has ";
text += Integer.toString(votes);
if (votes == 1) {
text += " vote.";
} else {
text += " votes.";
}
JOptionPane.showMessageDialog(frame, text);
updateLetterPair();
}
}
public class LetterMap {
private Map<Character, Integer> letterMap;
private Random random;
public LetterMap() {
this.letterMap = createLetterMap();
this.random = new Random();
}
private Map<Character, Integer> createLetterMap() {
Map<Character, Integer> letterMap = new TreeMap<>();
for (int i = 0; i < 26; i++) {
Character c = (char) (i + 'a');
letterMap.put(c, 0);
}
return letterMap;
}
public char[] pickTwo() {
int index1 = random.nextInt(letterMap.size());
int index2 = random.nextInt(letterMap.size());
while (index2 == index1) {
index2 = random.nextInt(letterMap.size());
}
char[] output = new char[2];
Set<Character> letterSet = letterMap.keySet();
Iterator<Character> iter = letterSet.iterator();
int count = 0;
int index3 = 0;
while (iter.hasNext() && index3 < 2) {
Character key = iter.next();
if (count == index1 || count == index2) {
if (index3 < 2) {
output[index3++] = key;
}
}
count++;
}
return output;
}
public void addVote(char c) {
Integer vote = getVotes(c);
letterMap.put(c, ++vote);
}
public int getVotes(char c) {
return letterMap.get(c);
}
}
}
I need a text field on a label but when i run this code there is no text field on the screen. How can i fix it.
JFrame jf = new JFrame() ;
JPanel panel = new JPanel() ;
JLabel label = new JLabel() ;
JTextField tField = new JTextField("asd" , 10) ;
label.add( tField ) ;
panel.add( label ) ;
jf.setSize( 500,400 ) ;
jf.add( panel ) ;
jf.setVisible(true) ;
JLabel's have no default layout manager, and so while your JTextField is being added tot he JLabel, it's not showing because the label has no idea how to show it.
There can be several ways to solve this depending on what you're trying to achieve:
Give the JLabel a layout manager, and then add the JTextField to it: but then the JTextField covers the JLabel, its text (if it has any) and its icon (if it has one), not good.
Create a JPanel to hold both, and give it an appropriate layout manager: probably a good bet.
Add them both to the same JPanel, using a layout manager that can easily place them in association: another good bet. GridBagLayout works well for this.
Don't forget to also call the JLabel's setLabelFor(...) method to associate it tightly with the JTextField, as per the JLabel Tutorial
For example:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
public class GridBagEg {
private static void createAndShowGui() {
PlayerEditorPanel playerEditorPane = new PlayerEditorPanel();
int result = JOptionPane.showConfirmDialog(null, playerEditorPane, "Edit Player",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
// TODO: do something with info
for (PlayerEditorPanel.FieldTitle fieldTitle : PlayerEditorPanel.FieldTitle.values()) {
System.out.printf("%10s: %s%n", fieldTitle.getTitle(),
playerEditorPane.getFieldText(fieldTitle));
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class PlayerEditorPanel extends JPanel {
enum FieldTitle {
NAME("Name", KeyEvent.VK_N), SPEED("Speed", KeyEvent.VK_P), STRENGTH("Strength", KeyEvent.VK_T);
private String title;
private int mnemonic;
private FieldTitle(String title, int mnemonic) {
this.title = title;
this.mnemonic = mnemonic;
}
public String getTitle() {
return title;
}
public int getMnemonic() {
return mnemonic;
}
};
private static final Insets WEST_INSETS = new Insets(5, 0, 5, 5);
private static final Insets EAST_INSETS = new Insets(5, 5, 5, 0);
private Map<FieldTitle, JTextField> fieldMap = new HashMap<FieldTitle, JTextField>();
public PlayerEditorPanel() {
setLayout(new GridBagLayout());
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Player Editor"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
GridBagConstraints gbc;
for (int i = 0; i < FieldTitle.values().length; i++) {
FieldTitle fieldTitle = FieldTitle.values()[i];
JLabel label = new JLabel(fieldTitle.getTitle() + ":", JLabel.LEFT);
JTextField textField = new JTextField(10);
label.setDisplayedMnemonic(fieldTitle.getMnemonic());
label.setLabelFor(textField);
gbc = createGbc(0, i);
add(label, gbc);
gbc = createGbc(1, i);
add(textField, gbc);
fieldMap.put(fieldTitle, textField);
}
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.anchor = (x == 0) ? GridBagConstraints.WEST : GridBagConstraints.EAST;
gbc.fill = (x == 0) ? GridBagConstraints.BOTH : GridBagConstraints.HORIZONTAL;
gbc.insets = (x == 0) ? WEST_INSETS : EAST_INSETS;
gbc.weightx = (x == 0) ? 0.1 : 1.0;
gbc.weighty = 1.0;
return gbc;
}
public String getFieldText(FieldTitle fieldTitle) {
return fieldMap.get(fieldTitle).getText();
}
}
Which displays as
Note that the JLabels have underlines on mnemonic chars, chars that when pressed in alt-key combination will bring the focus to the JTextField that the JLabel was linked to via, setLabelFor(...), and is caused by this code:
FieldTitle fieldTitle = FieldTitle.values()[i]; // an enum that holds label texts
JLabel label = new JLabel(fieldTitle.getTitle() + ":", JLabel.LEFT); // create JLabel
JTextField textField = new JTextField(10); // create JTextField
// set the label's mnemonic -- brings focus to the linked text field
label.setDisplayedMnemonic(fieldTitle.getMnemonic());
// *** here we *link* the JLabel with the JTextField
label.setLabelFor(textField);
When I run this program, both text fields appear right next to each other; if possible, how can I make it to where the password field is under the username field?
public static void main(String[] args) {
JTextField username = new JTextField(10);
JPasswordField password = new JPasswordField(10);
final JPanel login = new JPanel();
login.add(new JLabel("Username:"));
login.add(username);
login.add(Box.createHorizontalStrut(50));
login.add(new JLabel("Password:"));
login.add(password);
int result = JOptionPane.showConfirmDialog(null, login,
"Login Form", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
System.out.println("Username: " + username.getText());
System.out.println("Password: " + password.getText());
}
}
Myself, I'd use a GridBagLayout since with this layout, you can specify what position in a grid you'd like to place your components, how they fill the grid cell, how they expand when the GUI expands, etc. How to use it is explained well in the GridBagLayout tutorial and in other tutorials and examples on this site.
For example:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class SimpleLogin {
public static void main(String[] args) {
SimpleLoginPanel simpleLoginPanel = new SimpleLoginPanel();
int result = JOptionPane.showConfirmDialog(null, simpleLoginPanel,
"Login Form", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
System.out.println("Username: " + simpleLoginPanel.getUserName());
// the code below is dangerous as it translates a char[] to a String
// making the password potentially discoverable by outside programs.
System.out.println("Password: " + new String(simpleLoginPanel.getPassword()));
}
}
}
// create a JPanel to hold our components
#SuppressWarnings("serial")
class SimpleLoginPanel extends JPanel {
// insets provide blank space around the gridbag layout cells
private static final Insets INSETS = new Insets(5, 5, 5, 5);
private JTextField username = new JTextField(10);
private JPasswordField password = new JPasswordField(10);
public SimpleLoginPanel() {
setLayout(new GridBagLayout());
add(new JLabel("User Name:"), createGbc(0, 0));
add(username, createGbc(1, 0));
add(new JLabel("Password:"), createGbc(0, 1));
add(password, createGbc(1, 1));
}
// so that outside classes can extract the data in the password field
public char[] getPassword() {
return password.getPassword();
}
// so that outside classes can extract the username's text
public String getUserName() {
return username.getText();
}
// the main method of this example, one that creates the GridBagConstraints
// depending on the x, y position of the component.
// this one is written for a two column grid.
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.insets = INSETS;
if (x == 0) {
// if the left column, then anchor it to the left
// and fill completely since it's a JLabel
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.LINE_START;
} else {
// if the right column, anchor to the right and
// only fill horizontally since its a JTextField.
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.LINE_END;
}
return gbc;
}
}
You can try to use BoxLayout:
login.setLayout(new BoxLayout(login, BoxLayout.PAGE_AXIS));
however it also set a Labels in a row with text fields.
I have all of the labels working correctly but the userLabel[3] is not positioning properly
No matter what I do, the label "Color:" always shows up on the frame with a x-coordinate of 0 and a y-coordinate that is half way down the frame.
JLabel[] userLabel = new JLabel[4];
for(int p = 0; p < userLabel.length; p++){
userLabel[p] = new JLabel();
userLabel[p].setSize(100,50);
frameSetUp.add(userLabel[p]);
}
userLabel[0].setText("Width of Frame:");
userLabel[1].setText("Height of Frame:");
userLabel[2].setText("# OF Balls:");
userLabel[3].setText("Color:");
userLabel[0].setLocation(10,35);
userLabel[1].setLocation(10,85);
userLabel[2].setLocation(10,135);
userLabel[3].setLocation(0,0); //no matter what coordinates I change this too, it wont reposition
Image:
[IMG]http://i41.tinypic.com/23jfo9l.png[/IMG]
http://i41.tinypic.com/23jfo9l.png
Don't use setLocation, setBounds, null layouts or absolute positioning.
Instead use the layout managers including perhaps nested JPanels, each using its own layout manager to achieve pleasing easy to maintain GUI's.
For more help, show a picture of what you're trying to achieve, what you actually are achieving, and post a minimal working example, code that is small, that compiles and runs, and shows us your problem.
e.g.,
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
#SuppressWarnings("serial")
public class InputForm extends JPanel {
private static final int COLUMNS = 10;
private static final int GAP = 3;
private static final Insets LABEL_INSETS = new Insets(GAP, GAP, GAP, 15);
private static final Insets TEXTFIELD_INSETS = new Insets(GAP, GAP, GAP, GAP);
private String[] labelTexts;
private Map<String, JTextField> fieldMap = new HashMap<String, JTextField>();
public InputForm(String[] labelTexts) {
this.labelTexts = labelTexts;
setLayout(new GridBagLayout());
for (int i = 0; i < labelTexts.length; i++) {
String text = labelTexts[i];
JTextField field = new JTextField(COLUMNS);
fieldMap.put(text, field);
addLabel(text, i);
addTextField(field, i);
}
}
public String[] getLabelTexts() {
return labelTexts;
}
private void addTextField(JTextField field, int row) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.gridx = 1;
gbc.gridy = row;
gbc.anchor = GridBagConstraints.EAST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = TEXTFIELD_INSETS;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
add(field, gbc);
}
private void addLabel(String text, int row) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.gridx = 0;
gbc.gridy = row;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = LABEL_INSETS;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
add(new JLabel(text), gbc);
}
public String getFieldText(String key) {
String text = "";
JTextField field = fieldMap.get(key);
if (field != null) {
text = field.getText();
}
return text;
}
private static void createAndShowGui() {
String[] labelTexts = new String[] { "Width of Frame:",
"Height of Frame:", "# OF Balls:", "Color:" };
InputForm inputForm = new InputForm(labelTexts);
int result = JOptionPane.showConfirmDialog(null, inputForm, "Input Form",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
for (String text : labelTexts) {
System.out.printf("%20s %s%n", text, inputForm.getFieldText(text));
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Which will display like so:
The beauty of this code, is if you wish to add another field, say a line thickness field, and want to add it so that it is second to last, then the only change needed to the code would be to change this:
String[] labelTexts = new String[] { "Width of Frame:",
"Height of Frame:", "# OF Balls:", "Color:" };
to this:
String[] labelTexts = new String[] { "Width of Frame:",
"Height of Frame:", "# OF Balls:", "Line Thickness:", "Color:" };
Which results in:
No need to have to calculate how to change the Color label or JTextField's locations as the layout manager does all the hard work for you.
Finally got the answer try increasing the size of the JLabel array by 1 and run it will work fine
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Labelss{
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setBounds(50, 50, 700, 550);
JLabel[] userLabel = new JLabel[6];
for(int p = 0; p < userLabel.length; p++){
userLabel[p] = new JLabel();
}
userLabel[0].setBounds(10,35,100,50);
userLabel[1].setBounds(10,85,100,50);
userLabel[2].setBounds(10,135,100,50);
userLabel[3].setBounds(10,185,100,50);
userLabel[4].setBounds(10,235,100,50);
userLabel[0].setText("Width of Frame:");
userLabel[1].setText("Height of Frame:");
userLabel[2].setText("# OF Balls:");
userLabel[3].setText("Color:");
userLabel[4].setText("Stack overflow:");
for(int p = 0; p < userLabel.length; p++){
frame.add(userLabel[p]);
}
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}