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.
Related
I am making authentication GUI which should contain 2 text fields, username JTextField and password JPasswordField. I want to make the password field be below the username field. my current code is as follows:
public class GuiAuthentication extends JFrame {
private static final int WIDTH = 1000;
private static final int HEIGHT = 650;
private JTextField tfUsername;
private JPasswordField tfPassword;
public GuiAuthentication() {
try {
setTitle("Metaspace Launcher");
getContentPane().setLayout(new FlowLayout());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(WIDTH, HEIGHT);
tfUsername = new JTextField("Username");
tfPassword = new JPasswordField("********");
tfUsername.setBounds(10, 10, 50, 20);
tfPassword.setBounds(10, 50, 50, 20);
getContentPane().add(tfUsername);
getContentPane().add(tfPassword);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setMinimumSize (new Dimension(WIDTH, HEIGHT));
setMaximumSize (new Dimension(WIDTH, HEIGHT));
setResizable(false);
requestFocus();
setLocationRelativeTo(null);
setVisible(true);
} catch (final Exception ex) {
ex.printStackTrace();
System.exit(ex.toString().hashCode());
}
}
#Override
public void paint(final Graphics g) {
super.paint(g);
Gui.drawBackground(this, g, WIDTH, HEIGHT);
Gui.drawRect(g, WIDTH/3, HEIGHT/3 + 20, 325, 200, 0xAA000000);
}
However, this results in the password field being located against the username field, and both of them are centered, and not located at X position 10 which I specify:
--> Screenshot (click)
Is the problem in the layout I currently use (FlowLayout)? If so, which one should I use then? If not, what else might be wrong?
Tried using GridBagLayout as well. It results in this (fields side by side, centered):
Your GridBagLayout attempt images suggest that either you're not using GridBagConstraints when adding components or that you're using the incorrectly.
If you want to center your text components in the GUI, one over the other, and say put them in their own box, then use a GridBagLayout for the container that holds them, and also pass in appropriate GridBagConstraints that will work well with your desire. This will mean giving the constraints an appropriate gridx and gridy value to match where in the grid you wish to place the component. Also you will want to anchor the component correctly, and you will usually want to set the constraints insets to give an empty space buffer around your components so that they don't crowd each other. Myself, when I do something like this, I often use a 4 x 4 grid with two rows and two columns including a column of JLabels on the left so the user knows what each text component in the right column represents. I often use a helper method to help create my constraints, something like this:
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.fill = GridBagConstraints.HORIZONTAL; // stretch components horizontally
gbc.weightx = 1.0;
gbc.weighty = 0.0; // increase if you want component location to stretch vert.
// I_GAP is a constant and is the size of the gap around
// each component
gbc.insets = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
// if the x value is odd, anchor to the left, otherwise if even to the right
gbc.anchor = x % 2 == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
return gbc;
}
And then I'd use it like this:
JPanel innerPanel = new JPanel(new GridBagLayout());
JLabel userNameLabel = new JLabel("User Name:");
userNameLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(userNameLabel, createGbc(0, 0)); // add w/ GBC
innerPanel.add(tfUsername, createGbc(1, 0)); // etc...
JLabel passwordLabel = new JLabel("Password:");
passwordLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(passwordLabel, createGbc(0, 1));
innerPanel.add(tfPassword, createGbc(1, 1));
A working example could look like so:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
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.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
#SuppressWarnings("serial")
public class MetaSpaceLauncherPanel extends JPanel {
// path to a public starry image
public static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/"
+ "commons/thumb/b/be/Milky_Way_at_Concordia_Camp%2C_Karakoram_Range%2"
+ "C_Pakistan.jpg/1280px-Milky_Way_at_Concordia_Camp%2C_Karakoram_Range"
+ "%2C_Pakistan.jpg";
private static final int I_GAP = 10;
private static final int COLS = 15;
private JTextField tfUsername = new JTextField(COLS);
private JPasswordField tfPassword = new JPasswordField(COLS);
private BufferedImage background = null;
public MetaSpaceLauncherPanel(BufferedImage background) {
this.background = background;
// close window if enter pressed and data within fields
ActionListener listener = e -> {
String userName = tfUsername.getText().trim();
char[] password = tfPassword.getPassword();
Window window = SwingUtilities.getWindowAncestor(MetaSpaceLauncherPanel.this);
if (userName.isEmpty() || password.length == 0) {
// both fields need to be filled!
String message = "Both user name and password fields must contain data";
String title = "Invalid Data Entry";
JOptionPane.showMessageDialog(window, message, title, JOptionPane.ERROR_MESSAGE);
} else {
// simply close the dialog
window.dispose();
}
};
tfUsername.addActionListener(listener);
tfPassword.addActionListener(listener);
JPanel innerPanel = new JPanel(new GridBagLayout());
innerPanel.setOpaque(false);
Border outerBorder = BorderFactory.createEtchedBorder();
Border innerBorder = BorderFactory.createEmptyBorder(I_GAP, I_GAP, I_GAP, I_GAP);
Border border = BorderFactory.createCompoundBorder(outerBorder, innerBorder);
innerPanel.setBorder(border);
JLabel userNameLabel = new JLabel("User Name:");
userNameLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(userNameLabel, createGbc(0, 0));
innerPanel.add(tfUsername, createGbc(1, 0));
JLabel passwordLabel = new JLabel("Password:");
passwordLabel.setForeground(Color.LIGHT_GRAY);
innerPanel.add(passwordLabel, createGbc(0, 1));
innerPanel.add(tfPassword, createGbc(1, 1));
setLayout(new GridBagLayout());
add(innerPanel); // add without constraints to center it
}
public String getUserName() {
return tfUsername.getText();
}
public char[] getPassword() {
return tfPassword.getPassword();
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.fill = GridBagConstraints.HORIZONTAL; // stretch components horizontally
gbc.weightx = 1.0;
gbc.weighty = 0.0; // increase if you want component location to stretch vert.
// I_GAP is a constant and is the size of the gap around
// each component
gbc.insets = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
// if the x value is odd, anchor to the left, otherwise if even to the right
gbc.anchor = x % 2 == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
return gbc;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
g.drawImage(background, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || background == null) {
return super.getPreferredSize();
}
int w = background.getWidth();
int h = background.getHeight();
return new Dimension(w, h);
}
private static void createAndShowGui() {
BufferedImage img = null;
try {
// just using this as an example image, one available to all
// you would probably use your own image
URL imgUrl = new URL(IMG_PATH); // online path to starry image
img = ImageIO.read(imgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1); // no image available -- exit!
}
MetaSpaceLauncherPanel launcherPanel = new MetaSpaceLauncherPanel(img);
JDialog dialog = new JDialog(null, "MetaSpace Launcher", ModalityType.APPLICATION_MODAL);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.getContentPane().add(launcherPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
// test to see if we can get the data
String userName = launcherPanel.getUserName();
char[] password = launcherPanel.getPassword();
// don't convert password into String as I'm doing below as it is now
// not secure
String message = String.format("<html>User Name: %s<br/>Password: %s</html>", userName,
new String(password));
JOptionPane.showMessageDialog(null, message);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
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);
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();
}
});
}
}
I have an ItemListener that looks like this:
private class Listener implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
calculate();
}
}
At the bottom of my calculate() method, I set these labels like this:
subtotalLbl.setText("\t\t\t\t\t\t\t\tSubtotal:\t\t\t\t\t\t\t\t\t " + String.valueOf(determinedSubTotal + priceIncrease) + "\t\t\t\t\t\t\t\t\t");
taxLbl.setText("\t\t\t\t\t\t\t\tTax:\t\t\t\t\t\t\t\t\t " + String.valueOf(determinedTax + priceIncrease) + "\t\t\t\t\t\t\t\t\t");
totalLbl.setText("\t\t\t\t\t\t\tTotal:\t\t\t\t\t\t\t\t\t " + String.valueOf(determinedTotal + priceIncrease) + "\t\t\t\t\t\t\t\t\t");
Then I have an ActionListener that uses the text from the totalLbl for parseDouble
private class BtnClicked implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String input = totalLbl.getText().trim();
Double parsedString = Double.parseDouble(input) * 0.20;
Object src = e.getSource();
if(src == submit)
{
JOptionPane.showMessageDialog(null,"Thank you for your order - the tip will be " + fmt.format(parsedString), "Thank you" , JOptionPane.INFORMATION_MESSAGE);
}
else if(src == cancel)
{
JOptionPane.showMessageDialog(null,"Order was canceled" ,"Order Canceled" , JOptionPane.INFORMATION_MESSAGE);
}
}
Obviously the program is crashing at the line inside of the BtnClicked's actionPerformed method where parseDouble(input) is at, because the totalLbl JLabel has "Total:" in it.. where else would I set this or how would I work around this? The "Total:" is required. (can't use split() )
Here's a screenshot of what the entire JFrame looks like, program crashes when clicking the submit button:
Create two JLables, one which says Total: the other which actually holds the total value.
So your total calculation would look more like...
totalLblText.setText("Total:");
totalLbl.setText(String.valueOf(determinedTotal + priceIncrease));
Then you won't need to care.
You should make better use of your layout managers in order to support the formatting your trying to achieve rather than using formatting characters like \t, these will always end up in a mess
Updated with layout example
This simple example demonstrates how you might use a layout managers (and a technique known as compound layouts) and relieve the need to try and use a single label for displaying more information then it should...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
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) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextField numberOfPizzas;
private JCheckBox pepperoni;
private JCheckBox sausage;
private JCheckBox peppers;
private JCheckBox onions;
private JCheckBox mushrooms;
private JCheckBox extracheese;
private JLabel lblSubTotal;
private JLabel lblTax;
private JLabel lblTotal;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
JPanel header = new JPanel();
JPanel extras = new JPanel(new GridBagLayout());
JPanel totals = new JPanel(new GridBagLayout());
add(header, gbc);
gbc.gridy++;
add(extras, gbc);
gbc.gridy++;
add(totals, gbc);
numberOfPizzas = new JTextField(5);
header.add(new JLabel("Number of pizzas"));
header.add(numberOfPizzas);
gbc = new GridBagConstraints();
pepperoni = new JCheckBox("Pepperoni");
sausage = new JCheckBox("Sausage");
peppers = new JCheckBox("Peppers");
onions = new JCheckBox("Onions");
mushrooms = new JCheckBox("mushrooms");
extracheese = new JCheckBox("Extra Cheeses");
JCheckBox left[] = new JCheckBox[] {pepperoni, peppers, mushrooms};
JCheckBox right[] = new JCheckBox[] {sausage, onions, extracheese};
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 0;
gbc.gridy = 0;
add(left, extras, 0, 1, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
add(right, extras, 0, 1, gbc);
gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
gbc.insets = new Insets(2, 12, 2, 12);
totals.add(new JLabel("Subtotal:"), gbc);
gbc.gridy++;
totals.add(new JLabel("Tax:"), gbc);
gbc.gridy++;
totals.add(new JLabel("Total:"), gbc);
gbc.weightx = 0;
gbc.gridx = 1;
gbc.gridy = 0;
lblSubTotal = new JLabel("8.0");
lblTax = new JLabel("0.78");
lblTotal = new JLabel("8.78");
totals.add(lblSubTotal, gbc);
gbc.gridy++;
totals.add(lblTax, gbc);
gbc.gridy++;
totals.add(lblTotal, gbc);
}
protected void add(JComponent[] comps, JComponent parent, int deltaX, int deltaY, GridBagConstraints gbc) {
for (JComponent comp : comps) {
parent.add(comp, gbc);
gbc.gridy += deltaY;
gbc.gridx += deltaX;
}
}
}
}
Lots of different ways to do this, the easiest is probably:
String[] parts = totalLbl.getText().split(":");
String input = parts[1].trim();
Double parsedString = Double.parseDouble(input) * 0.20;
you can do this
str = str.replaceAll("\\D+","");
this will delete non digits from the string
so you would want it to be like this
Double parsedString = Double.parseDouble(input.replaceAll("\\D+","")*0.20);
You can use separate widgets for the label and the value. E.g. The total label, create a JLabel object and set the text with static value "Total:", then for the total value, create a JTextField object and set the text with the actual value. When submitting, get the value from the textfield instead of from the label. Don't forget to call setEditable(false) to the textfield because the textfield is meant to display the value only, not to accept input.
I have a form with lots of text fields and some of those text fields may contain very long strings. To make it work I made those text fields scrollable using this code:
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension((int)textField.getPreferredSize().getWidth(), (int)textField.getPreferredSize().getHeight() * 2));
Then I put scroll into my form using GridBagLayout.
Second line in my example is required for scroller to show up. But it has downside. When I resize window to fit whole text in text field, then scroll disapears leaving me with just two times higher then others text field, which looks ridiculous.
How can I make this all work and show me normal size of text field after scroller is hidden?
EDIT:
You may use following as a demo code to reproduce the issue:
import javax.swing.*;
import java.awt.*;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension(70, 40) );
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("abc");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
For this , in the absence of a good SSCCE, I think you hadn't provided any constraint that goes for fill, which is used for
Used when the component's display area is larger than the component's requested size to determine whether and how to resize the component. Valid values (defined as GridBagConstraints constants) include NONE (the default), HORIZONTAL (make the component wide enough to fill its display area horizontally, but do not change its height), VERTICAL (make the component tall enough to fill its display area vertically, but do not change its width), and BOTH (make the component fill its display area entirely).
So you must add something like this to your GridBagConstraints
constraintsGridBag.fill = GridBagConstraints.HORIZONTAL;
This will only allow it to expand HORIZONTALLY not both ways.
** EDIT : As for the added code **
Never specify setPreferredSize(...) for any component in Swing. Let the Layout Manager you are using, take care for that. Remove all setPreferredSize(...) thingies, will let it remain in normal size upon resizing.
*EDIT 2 : *
Code to tell you what I am saying :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class GridBagTest extends JFrame
{
private JPanel topPanel;
private JPanel bottomPanel;
public GridBagTest()
{
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
//gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 0.8;
// Setting TOP PANEL.
topPanel = new JPanel();
topPanel.setLayout(new GridBagLayout());
GridBagConstraints constraintsTopPanel = new GridBagConstraints();
constraintsTopPanel.gridwidth = 2; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
/*
* fill with HORIZONTAL, means the component upon resize, will
* only expand along the X-Axis.
*/
constraintsTopPanel.fill = GridBagConstraints.NONE;
constraintsTopPanel.insets = new Insets(5, 5, 5, 5);
constraintsTopPanel.ipadx = 2;
constraintsTopPanel.ipady = 2;
constraintsTopPanel.weightx = 0.3;
constraintsTopPanel.weighty = 0.2;
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 0;
JTextField tfield1 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield1, constraintsTopPanel);
constraintsTopPanel.gridx = 2;
constraintsTopPanel.gridy = 0;
final JTextField tfield2 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield2, constraintsTopPanel);
constraintsTopPanel.gridx = 4;
constraintsTopPanel.gridy = 0;
JTextField tfield3 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield3, constraintsTopPanel);
topPanel.setBackground(Color.WHITE);
add(topPanel, gbc);
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 2;
constraintsTopPanel.gridwidth = 6; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
JButton button = new JButton("REMOVE");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
topPanel.remove(tfield2);
topPanel.revalidate();
topPanel.repaint();
}
});
topPanel.add(button, constraintsTopPanel);
//Setting BOTTOM PANEL.
bottomPanel = new JPanel();
bottomPanel.setLayout(new BorderLayout());
bottomPanel.setBackground(Color.DARK_GRAY);
JLabel label3 = new JLabel("I am a new JLABEL for the bottom JPanel", JLabel.CENTER);
label3.setForeground(Color.WHITE);
bottomPanel.add(label3, BorderLayout.CENTER);
gbc.weighty = 0.2;
add(bottomPanel, gbc);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
public static void main(String... args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GridBagTest();
}
});
}
}
Well the best I've got is looking ugly in code, but does exactly what I need to the textField. Below is changed sample code from initial question. I'd be thankfull for any ideas how to make it better:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
//gbc.ipady = 20;//gives some room for scroll to appear and don't hide text area under the scroll.
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("bbbbbbbb");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
scroll.addComponentListener( new ScrollTextComponentListener(scroll, textField2));
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
class ScrollTextComponentListener implements ComponentListener {
private boolean scrollVisible;
private JScrollPane scroll;
private JComponent compareComponent;
public ScrollTextComponentListener(JScrollPane scroll, JComponent compareComponent) {
this.scroll = scroll;
this.compareComponent = compareComponent;
}
private boolean isScrollVisible() {
return scroll.getHorizontalScrollBar().getModel().getExtent() != scroll.getHorizontalScrollBar().getModel().getMaximum();
}
private void setScrollSize(){
boolean scrollVisible = isScrollVisible();
if (scrollVisible){
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
//also had to set both min and max sizes, because only preffered size didn't always work
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
}
else {
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
}
this.scrollVisible = scrollVisible;
}
#Override
public void componentResized(ComponentEvent e) {
if (isScrollVisible() != scrollVisible) setScrollSize();
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentShown(ComponentEvent e) {
setScrollSize();
}
#Override
public void componentHidden(ComponentEvent e) {
}
}