Using ArrayList in a JPanel - java

Class SampleFiveA extends JPanel. This contains textfields, one below the other, each of which has a label on the left. All textfields will be of the same width and positioned against the right border of the panel. SampleFiveA has only one constructor that accepts the following three parameters:
ArrayList names,
ArrayList values,
int cols
I so far created the sample username password screen in GUI but now I have a problem implementing an ArrayList in JPanel one for User Name and the other for password. Kind of stuck there for hours now cant find a proper example to do it. Below is the code I commented what I need to be done using ArrayList.
public class SampleFiveA extends JPanel {
ArrayList<String> names = new ArrayList<String>(); //the text for the labels
ArrayList<String> values = new ArrayList<String>(); // the initial contents of the text fields
int col ; //the number of columns used to set the width of each textfield
public SampleFiveA()
{
JPanel p = new JPanel();
p.setLayout(new GridLayout(2,2));
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
p.add(lab1 = new JLabel("User Name"));
JTextField txt1 = new JTextField("User Name", JTextField.RIGHT);
p.add(txt1= new JTextField());
JLabel lab2 = new JLabel("Password ", JLabel.LEFT);
p.add(lab2 = new JLabel("Password"));
JPasswordField txt2 = new JPasswordField("*****",JPasswordField.RIGHT );
p.add(txt2 = new JPasswordField());
// names.add(lab1,lab2);// Not right but I want to put the label text to this arrayList
// values.add(txt1,txt2);//
add(p);
};
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.getContentPane().add(new SampleFiveA());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);
frame.setVisible(true);
};
};

you can use
names.add(txt1.getText());
values.add(txt2.getText());
but maybe you should think about a better data structure, e.g. a HashMap and
hashmap.put(txt1.getText(),txt2.getText())
(and you should do this based on some event,e.g. user presses a button, not in the constructor, as otherwise the value will be the one you set before)

Here's a start for you.
It adds a FocusListener to the text fields and makes sure that the content of the ArrayList is updated with the current value when the text field looses focus.
import java.awt.GridLayout;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class Main extends JPanel {
ArrayList<String> names = new ArrayList<String>(); // the text for the
// labels
ArrayList<String> values = new ArrayList<String>(); // the initial contents
// of the text fields
int col; // the number of columns used to set the width of each textfield
public Main() {
JPanel p = new JPanel();
p.setLayout(new GridLayout(2, 2));
names = new ArrayList<String>();
values = new ArrayList<String>();
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
p.add(lab1);
JTextField txt1 = new JTextField("User Name", JTextField.RIGHT);
p.add(txt1);
names.add(lab1.getText());
values.add(txt1.getText());
JLabel lab2 = new JLabel("Password ", JLabel.LEFT);
p.add(lab2);
JPasswordField txt2 = new JPasswordField("*****", JPasswordField.RIGHT);
p.add(txt2);
names.add(lab2.getText());
values.add(txt2.getText());
// names.add(lab1,lab2);// Not right but I want to put the label text to
// this arrayList
// values.add(txt1,txt2);//
txt1.addFocusListener(new ArrayListFocusListener(txt1, values, 0));
txt2.addFocusListener(new ArrayListFocusListener(txt2, values, 1));
add(p);
// Start a thread to print the content of the list for 10 seconds
new Thread() {
public void run() {
for (int i = 0; i < 10; i++) {
try {
sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(values);
}
}
}.start();
};
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new Main());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
};
class ArrayListFocusListener implements FocusListener {
JTextField textField;
ArrayList<String> backingList;
int myIndex;
public ArrayListFocusListener(JTextField textField,
ArrayList<String> backingList, int myIndex) {
this.textField = textField;
this.backingList = backingList;
this.myIndex = myIndex;
}
public void focusGained(FocusEvent e) {
}
#Override
public void focusLost(FocusEvent e) {
backingList.set(myIndex, textField.getText());
}
}
};

I'm sure what you are trying to do. You either want to put the JLabel in an ArrayList or the text of that label.
If you want to put the whole JLabel in an ArrayList, you should make a ArrayList<JLabel>. But I take it you want to get the text from the JLabel, so you should write names.add(lab1.getText());.
The constructor you have made doesn't take any parameters. The parameters you have wrote are the instance variable, meaning those are the variables any instance of that class will have. If you want to pass parameters in your constructor you should do what thasc told you.
You write:
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
p.add(lab1 = new JLabel("User Name"));
But since you are already creating the lab1 JLabel you could just write p.add(lab1).
And a final note I think SampleFiveA should better extend JFrame unless you want it to extend JPanel to use it somewhere else. If you need it to be standalone you should change that.
cheers

Related

textField.getText() not working when textField is in a different panel (compare to the button.addActionListener)

I'm new to Java Swing and encountered an issue when using JTextField.getText(). Basically .getText() is not picking up whatever string I put into the text field and returns an empty string.
I think the reason I got an empty string is that the JTextField is in a different panel than the button, but don't know how to get it working... Any help will be highly appreciated!
Here is my logic
(1) Create a JFrame, call it frame
(2) Create several JPanels and frame.add(JPanel)
(3) Fill in the panels with JButton and JTextField. Note that the text field is in a different panel than the button.
(4) Call button.addActionListener(...) and use JTextField.getText()
Here is my code:
package GUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class aaaaa {
// Class attributes
// Overall class attributes
private JFrame frame = new JFrame("Simulation App");
// Class attributes for method setTextFieldPar
private JPanel panelThetaCh = new JPanel();
private JPanel panelSetButton = new JPanel();
private JTextField textFieldThetaCh = new JTextField();
private String StringThetaCh;
// Class attributes for method setButton
private JButton buttonSetPar;
// ========================================================================================================================
// Class methods
// Text field of all simulation parameters
public void setTextFieldPar(JPanel panel, JTextField textField, String latexString){
// Panel layout - FlowLayout
panel.setLayout(new FlowLayout());
panel.setMinimumSize(new Dimension(300, 100));
frame.add(panel);
panel.setAlignmentX(Component.CENTER_ALIGNMENT);
JLabel labelText = new JLabel("text");
panel.add(labelText);
// Create text field
textField = new JTextField(13);
panel.add(textField);
}
// Button "Set Parameters"
public void setButton (JPanel panel){
panel.setLayout(new GridLayout(4, 0));
panel.setMaximumSize(new Dimension(200, 100));
frame.add(panel);
panel.setAlignmentX(Component.CENTER_ALIGNMENT);
buttonSetPar = new JButton("Set Parameters");
panel.add(buttonSetPar);
}
// Monitor input in text field
public void monitorTextField() {
buttonSetPar.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
// Extract numbers entered in text field for the parameters
StringThetaCh = textFieldThetaCh.getText();
if (StringThetaCh.equals("")) {
JFrame errorWindow = new JFrame("Error");
errorWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
errorWindow.setLocationRelativeTo(null);
JOptionPane.showMessageDialog(errorWindow, "At least one text field is empty, please enter numerical values");
}
}
});
}
// Constructor
public aaaaa(){
frame.setSize(350, 800);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
// Text field for parameters
setTextFieldPar(panelThetaCh, textFieldThetaCh, "\\theta_{CH}");
// Button for set parameter
setButton(panelSetButton);
// Monitoring input in text field
monitorTextField();
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
aaaaa window2 = new aaaaa();
window2.frame.setVisible(true);
}
});
}
}
You are already creating the text field in the class declaration:
private JTextField textFieldThetaCh = new JTextField();
then you pass it to the method setTextFieldPar and in there you are creating another text field that is added to the panel:
textField = new JTextField(13);
panel.add(textField);
So, the class variable textFieldThetaCh is not the one added to the panel and therefore is inaccessible to the user.
Simply remove the creation of the new text field in setTextFieldPar and it will work.
Here is a visual representation of what is happening:
in the class declaration:
inside the setTextFieldPar method (remember that the parameters are passed by value, so a copy of the object reference is made):
after textField = new JTextField(13);, the copy of the reference now points to a new object:
after panel.add(textField);, the new object is added to the panel, which is not what textFieldThetaCh is pointing to:
i just use textFieldThetaCh directly without send it as pram
you was taking the text from textFieldThetaCh when you are typing the text on textField
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class aaaaa {
// Class attributes
// Overall class attributes
private JFrame frame = new JFrame("Simulation App");
// Class attributes for method setTextFieldPar
private JPanel panelThetaCh = new JPanel();
private JPanel panelSetButton = new JPanel();
private JTextField textFieldThetaCh = new JTextField(13);
private String StringThetaCh;
// Class attributes for method setButton
private JButton buttonSetPar;
// Text field of all simulation parameters
public void setTextFieldPar(JPanel panel, JTextField textField, String
latexString){
// Panel layout - FlowLayout
panel.setLayout(new FlowLayout());
panel.setMinimumSize(new Dimension(300, 100));
frame.add(panel);
panel.setAlignmentX(Component.CENTER_ALIGNMENT);
JLabel labelText = new JLabel("text");
panel.add(labelText);
// Create text field
// textField = new JTextField(13);
panel.add(textFieldThetaCh);
}
// Button "Set Parameters"
public void setButton (JPanel panel){
panel.setLayout(new GridLayout(4, 0));
panel.setMaximumSize(new Dimension(200, 100));
frame.add(panel);
panel.setAlignmentX(Component.CENTER_ALIGNMENT);
buttonSetPar = new JButton("Set Parameters");
panel.add(buttonSetPar);
}
// Monitor input in text field
public void monitorTextField() {
buttonSetPar.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
// Extract numbers entered in text field for the parameters
StringThetaCh = textFieldThetaCh.getText();
if (StringThetaCh.equals("")) {
JFrame errorWindow = new JFrame("Error");
errorWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
errorWindow.setLocationRelativeTo(null);
JOptionPane.showMessageDialog(errorWindow, "At least one text
field is empty, please enter numerical values");
}
else
JOptionPane.showMessageDialog(null,
StringThetaCh);
}
});
}
// Constructor
public aaaaa(){
frame.setSize(350, 800);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
// Text field for parameters
setTextFieldPar(panelThetaCh, textFieldThetaCh, "\\theta_{CH}");
// Button for set parameter
setButton(panelSetButton);
// Monitoring input in text field
monitorTextField();
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
aaaaa window2 = new aaaaa();
window2.frame.setVisible(true);
}
});
}
}
Your button actionPerformed is within monitorTextField() which is in the constructor. This gets fired up at the beginning but never called upon afterwards (referring to monitorTextField()).
Put the actionPerformed somewhere outside of a function so it can function anytime the button is pressed and it should work.

Adding elements from JTextField to ArrayList

so I have an assignment that include GUI that contain:
JTextField that lets user enter an input into the text field
AddButton adds the input into an ArrayList
ListButton displays the content of ArrayList in the JTextArea
The problem is: When I enter [1,2,3] the output only show me the last element [3], how to fix this?
public class Example extends JFrame {
private final int WINDOW_WIDTH = 300;
private final int WINDOW_HEIGHT = 300;
private JPanel panel1, panel2;
private JLabel messageLabel;
private JTextField input;
private JTextArea output;
private JButton addButton, listButton;
String userInput;
ArrayList<String> list = new ArrayList<>();
public Example() {
setTitle("Array Exercise");
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
panel1 = new JPanel();
panel1.setLayout(new GridLayout(6,1));
messageLabel = new JLabel("Input");
input = new JTextField(5);
addButton = new JButton("Add");
listButton = new JButton("List");
panel1.add(messageLabel);
panel1.add(input);
panel1.add(addButton);
panel1.add(listButton);
add (panel1, BorderLayout.WEST);
output = new JTextArea(12, 10);
panel2 = new JPanel();
panel2.add(output);
add(panel2, BorderLayout.EAST);
setVisible(true);
input.requestFocus();
ButtonListener bh = new ButtonListener();
addButton.addActionListener(bh);
listButton.addActionListener(bh);
}
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
userInput = input.getText();
if (e.getSource() == addButton) {
list.add(userInput);
output.setText(userInput + " added.");
input.setText("");
input.requestFocus();
}
else if (e.getSource() == listButton) {
list.stream().forEach(x-> output.setText(x));
}
}
}
The JTextField its text to a new text for each element in your list. What you have to do is something like this instead:
for(String s : list){
outPut.append(s + "\n");
}
//Use "\n" if you want each string on a new line. Otherwise, skip it
(I used this type of for-loop for clarity)
Now it "adds" (appends) each new String in your list. In your code, it sets the text to the first String. The sets the text to the second String (and so on). So remember to clear the area with perhaps setText(""); every time you want to print out, for example, a new list of Strings.
complementing Oskar's answer:
setTest() sets the whole text of the text area, overwriting the previous content. So the last value set is the (only) one that will be saved at the end.
Since already using Streams, you could use:
output.setText(list.stream().collect(Collectors.joining("\n")));

Text boxes squished in Swing layout

I have a frame that opens when you click file>new user, but the text fields are all squished together.
I'm trying to have them all stacked vertically so I use new GridLayout(3, 2) as my LayoutManager. However, the stuff for the new window is all the way at the bottom.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class App extends JFrame implements ActionListener
{
private final int WIDTH = 300;
private final int HEIGHT = 550;
private int control = 0;
String[] username = new String[10];
String[] pass = new String[10];
private String tempName;
private String tempPass;
Container con = getContentPane();
JPanel panel = new JPanel();
private JTextField name = new JTextField();
private JPasswordField password = new JPasswordField();
JMenuBar mainBar = new JMenuBar();
JMenu menu1 = new JMenu("File");
JMenu menu2 = new JMenu("Edit");
JMenuItem newUser = new JMenuItem("New User");
JButton but1 = new JButton("Log In");
JButton but2 = new JButton("test");
JLabel error = new JLabel("Login info not corret\n Or user not registered.");
JLabel success = new JLabel("Success!");
/////////////stuff for dialog///////////////////
JPanel panel2 = new JPanel();
JTextField newModalUser = new JTextField();
JPasswordField newModalPass = new JPasswordField();
JPasswordField newModalPassCon = new JPasswordField();
JButton register = new JButton("Register");
////////////////////////////////////////////////
public static void main(String[] args)
{
App frame = new App();
}
public App()
{
//just settin some stuff up
super("For The Bold");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
//setResizable(false);
setVisible(true);
//add menubar
setJMenuBar(mainBar);
mainBar.add(menu1);
menu1.add(newUser);
//background of main JFrame
setContentPane(new JLabel(new ImageIcon("//Users//ryanchampin//Desktop//GUI app//image.png")));
//test names in the arrays
username[0] = "ryan";
pass[0] = "test";
//main stuff in the middle
//panel.setBackground(Color.RED);
panel.setSize(300,300);
panel.add(name);
panel.add(password);
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS ));
panel.add(but1);
panel.add(but2);
add(panel,new GridBagConstraints());
setLayout(new GridBagLayout());
//assign action listener
but1.addActionListener(this);
newUser.addActionListener(this);
register.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
tempName = name.getText();
tempPass = password.getText();
if(source == but1)
{
for(int x = 0; x < username.length; x++)
{
if(tempName.equalsIgnoreCase(username[x]) && tempPass.equals(pass[x]))
{
//display success JLabel
add(success);
System.out.println("success");
break;
}
else
{
success.setText(null);
add(error);
name.setText(null);
password.setText(null);
}
}
}
else
if(source == newUser)
{
panel.setVisible(false);
setLayout(new GridLayout(3,2));
add(panel2);
panel2.add(newModalUser);
panel2.add(newModalPass);
panel2.add(newModalPassCon);
panel2.add(register);
}
else if(source == register)
System.out.println("yay it worked");
}
}
Avoid using setSize(...) or setPreferredSize(...) if possible.
Instead let the components and their layout managers set their own sizes.
Use a CardLayout to swap views instead of what you're doing. If you do this, the CardLayout will size its container to fit all the "cards" that it has been given.
Don't forget to call pack() on the GUI after adding all components
Don't forget to call setVisible(true) after adding all components and after calling pack.
When creating new JTextFields and JPasswordFields, pass in an int for the number of columns into the constructors.
Edit
You ask:
whats pack() used for?
The pack() method tells the GUI to have all the layout managers of its constituent containers to lay out their components, and then to set the best size of the GUI after every component has been properly placed.
If you want spacing in a GridLayout, you can use the setHgap(int) and setVgap(int) methods to set the number of pixels of space that will appear between each element in the grid.
In your code, there are two ways you could do this: construct a GridLayout and call the two setter methods on it, then pass it into the setLayout(LayoutManager) method:
GridLayout layout = new GridLayout(3, 2);
layout.setHgap(5); // or whatever number of pixels you want
layout.setVgap(5); // same
setLayout(layout);
Alternatively, you could cast the LayoutManager you would get from calling getLayout() and call the two methods on it:
setLayout(new GridLayout(3, 2));
((GridLayout) getLayout()).setHgap(5);
((GridLayout) getLayout()).setVgap(5);
if you want them stacked vertically, wouldn't it be easier to keep using BoxLayout?

Java adding components to JOptionPane

I'm trying create a custom panel for a simple data entry dialog. I've created a custom panel which I add my labels and text fields. I'm trying to add it to a JOptionPane for display.
When I call it, my components do not display but the JOptionPane buttons do. What is the correct way of doing this?
Here is where I create my custom panel and call JOptionPane:
public class ListenCustEdit implements ActionListener {
#Override
#SuppressWarnings("empty-statement")
public void actionPerformed(ActionEvent e) {
TestPanel panel = new TestPanel();
int input = JOptionPane.showConfirmDialog(frame, panel, "Edit Customer:"
,JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (input == 0) {
// OK
JOptionPane.showMessageDialog(frame,"Changes savewd");
} else {
// Cancel
JOptionPane.showMessageDialog(frame, "No changes were saved");
}
}
}
Here is my custom panel class:
public class TestPanel extends JPanel {
JTextField custIdTextField;
JTextField companyTextField;
JTextField firstNameTextField;
JTextField lastNameTextField;
public TestPanel() {
initUI();
}
public final void initUI() {
// create the panel and set the layout
JPanel main = new JPanel();
main.setLayout(new GridLayout(4,4));
// create the labels
JLabel custIdLabel = new JLabel("Cust Id: ");
JLabel companyLabel = new JLabel("Company: ");
JLabel firstNameLabel = new JLabel("First Name: ");
JLabel lastNameLabel = new JLabel("Last Name: ");
// create the text fields
custIdTextField = new JTextField();
companyTextField = new JTextField();
firstNameTextField = new JTextField();
lastNameTextField = new JTextField();
// add componets to panel
main.add(custIdLabel);
main.add(custIdTextField);
main.add(companyLabel);
main.add(companyTextField);
main.add(firstNameLabel);
main.add(firstNameTextField);
main.add(lastNameLabel);
main.add(lastNameTextField);
}
You need to add the main panel to your TestPanel.
public final void initUI() {
// ...
add(main);
}
In initUI, you create a JPanel (called "main") and stuff it full of components, but don't do anything with it. You need to either add "main" to the actual instance of TestPanel, or just skip the step of creating the "main" panel altogether.
The first way:
public final void initUI() {
// ... everything as before, then
this.add(main);
}
The second way:
public final void initUI() {
this.setLayout(new GridLayout(4,4));
// create the labels
JLabel custIdLabel = new JLabel("Cust Id: ");
JLabel companyLabel = new JLabel("Company: ");
JLabel firstNameLabel = new JLabel("First Name: ");
JLabel lastNameLabel = new JLabel("Last Name: ");
// create the text fields
custIdTextField = new JTextField();
companyTextField = new JTextField();
firstNameTextField = new JTextField();
lastNameTextField = new JTextField();
// add componets to panel
this.add(custIdLabel);
this.add(custIdTextField);
this.add(companyLabel);
this.add(companyTextField);
this.add(firstNameLabel);
this.add(firstNameTextField);
this.add(lastNameLabel);
this.add(lastNameTextField);
}
(The "this."'s aren't strictly necessary, but I added them for illustration.)
Hope this helps!
You didn't add main Panel to your TestPanel instance in the constructor.

Java: Roller program - debug - variables not updating from JTextField and NumberFormatException thrown regardless of valid information

Problems:
I am unable to get the values of the JTextFields or the rollResultTotal to update.
Even if the data in the JTextFields are valid, a NumberFormatException is still thrown.
Questions: Why don't the variables stay? Is this due to declaration in the class itself? Is it possible to update a JLabel panel to show an updated result? (tried this, epic failure)
Thanks in advance for any input and examples.
/*
ITP-120: Final Project
Programmer: S. Schnoor
Date: November 7th, 2009
Filename: SchnoorProject.java
Purpose: To generate "dice rolls" - a tally of random values as defined by the user,
including a final calculation modifier.
*/
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.lang.*;
import java.math.*;
public class SchnoorProject extends JFrame implements ActionListener, EventListener
{
// Declare Class Variables
int sidesToRoll, diceToRoll, diceLeft, modifier, rollResult, rollResultTotal;
String getSides, getDice, getModifier;
JTextField inputSides = new JTextField();
JTextField inputDice = new JTextField();
JTextField inputModifier = new JTextField();
Random roll;
// Panels and Buttons
JPanel rollPanel;
JButton newRollButton, helpButton, exitButton;
// Create Colors
Color darkPurple = new Color ( 80, 0, 80);
Color darkGold = new Color (255, 215, 0);
Color darkCoal = new Color ( 24, 24, 24);
Color crimson = new Color (127, 12, 12);
Color ltSilver = new Color (140, 140, 180);
public static void main(String args[])
{
JFrame frame = new SchnoorProject();
WindowListener l = new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
frame.addWindowListener(l);
frame.pack();
frame.setVisible(true);
}
public SchnoorProject()
{
// Construction of Components
rollPanel = new JPanel();
getContentPane().add(rollPanel);
JLabel sidesLabel = new JLabel ("Enter the number of sides on each die below. (1 to 99)");
sidesLabel.setForeground(darkGold);
sidesLabel.setHorizontalAlignment(sidesLabel.CENTER);
JTextField inputSides = new JTextField("6");
inputSides.setBackground(darkCoal);
inputSides.setForeground(darkGold);
inputSides.setHorizontalAlignment(inputSides.CENTER);
JLabel diceLabel = new JLabel ("Enter the number of dice to roll below. (1 to 99)");
diceLabel.setForeground(darkGold);
diceLabel.setHorizontalAlignment(diceLabel.CENTER);
JTextField inputDice = new JTextField("3");
inputDice.setBackground(darkCoal);
inputDice.setForeground(darkGold);
inputDice.setHorizontalAlignment(inputDice.CENTER);
JLabel modifierLabel = new JLabel ("Enter the final modifier below. (-99 to 99)");
modifierLabel.setForeground(darkGold);
modifierLabel.setHorizontalAlignment(modifierLabel.CENTER);
JTextField inputModifier = new JTextField("2");
inputModifier.setBackground(darkCoal);
inputModifier.setForeground(darkGold);
inputModifier.setHorizontalAlignment(inputModifier.CENTER);
JButton newRollButton = new JButton("ROLL");
newRollButton.setBackground(darkCoal);
newRollButton.setForeground(darkGold);
newRollButton.addActionListener(this);
JButton helpButton = new JButton("Help/About");
helpButton.setBackground(darkCoal);
helpButton.setForeground(ltSilver);
helpButton.addActionListener(this);
JButton exitButton = new JButton("Exit");
exitButton.setBackground(darkCoal);
exitButton.setForeground(crimson);
exitButton.addActionListener(this);
//Conversions
getSides = inputSides.getText();
getDice = inputDice.getText();
getModifier = inputModifier.getText();
sidesToRoll = Integer.parseInt(getSides);
diceToRoll = Integer.parseInt(getDice);
modifier = Integer.parseInt(getModifier);
diceLeft = diceToRoll;
//rollResultTotal = rollResultTotal;
// Paneling
rollPanel.setLayout(new GridLayout (3,3));
rollPanel.setBackground(darkPurple);
rollPanel.setForeground(darkGold);
rollPanel.add(sidesLabel);
rollPanel.add(diceLabel);
rollPanel.add(modifierLabel);
rollPanel.add(inputSides);
rollPanel.add(inputDice);
rollPanel.add(inputModifier);
rollPanel.add(newRollButton);
rollPanel.add(helpButton);
rollPanel.add(exitButton);
}
// Implement ActionListener for multiple JButtons
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
if ("Help/About".equals(arg))
{
JOptionPane.showMessageDialog(null,"This application generates random values, based on the parameters input by the user.\nPlease choose number of dice, sides on each die, and a +/- roll modifier.\nIf no roll modifier is needed, enter 0 (numeric zero) in the modifier field.\n(The starting numbers tell the program to roll 3 six-sided dice and add 2 or '3d6+2'.)","Help/About",JOptionPane.INFORMATION_MESSAGE);
}
if ("Exit".equals(arg))
{
System.exit(0);
}
if ("ROLL".equals(arg))
{
try
{
while (diceLeft>0)
{
getSides = inputSides.getText();
sidesToRoll = Integer.parseInt(getSides);
if(sidesToRoll<1 || sidesToRoll>99) throw new NumberFormatException();
else
getDice = inputDice.getText();
diceToRoll = Integer.parseInt(getDice);
if(diceToRoll<1 || diceToRoll>99) throw new NumberFormatException();
else
getModifier = inputModifier.getText();
modifier = Integer.parseInt(getModifier);
if(modifier<-99 || modifier>99) throw new NumberFormatException();
else
rollResult = roll.nextInt(sidesToRoll)+1;
rollResultTotal = rollResultTotal + rollResult;
diceLeft--;
}
}
catch(NumberFormatException ex)
{
JOptionPane.showMessageDialog(null,"You must enter an integer within the given range of each field.","ROLL",JOptionPane.INFORMATION_MESSAGE);
diceLeft = 0;
}
{ //Display the Roll Formula and Result
JOptionPane.showMessageDialog(null,"You entered a roll of " + (diceToRoll) + "d" + (sidesToRoll) + "+(" + (modifier) + ").\nYou rolled " + (rollResultTotal) + "!");
}
;}
;}
}
You initialize this member variable, but you never add this field to the UI:
JTextField inputSides = new JTextField(" ");
Here you read from this text field that still contains the String " ", which is not an integer.
getSides = inputSides.getText();
sidesToRoll = Integer.parseInt(getSides);
When you build your UI in the constructor, you declare another, local variable with the same name, pointing to a new object:
JTextField inputSides = new JTextField("6");
This is the object that appears in the UI. The local variable inputSides hides the member variable of the same name.
As an aside, this is not the right way to compare strings:
arg == "ROLL"
This only works because arg is pointing to the same, interned object instance. The correct way to compare these values would be:
"ROLL".equals(arg)
EDIT:
The trick you are missing is in thinking about the objects you are creating and which ones your reference variables are pointing at.
Consider this simplified version of your code:
public class ObjectReferences {
private final JLabel label = new JLabel("I am FOO"); // label 1
public ObjectReferences() {
JLabel label = new JLabel("I am BAR"); // label 2
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
onclick();
}
});
// will display "I am BAR"
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setLayout(new FlowLayout());
frame.add(label); // label 2
frame.add(button);
frame.setVisible(true);
}
public void onclick() {
// will display "I am FOO"
JOptionPane.showMessageDialog(null, label.getText()); // label 1
}
public static void main(String[] args) {
new ObjectReferences();
}
}
Two label objects are created, but only one is added to the frame. label 1 is referenced by the member variable and this is the one visible to the onclick() method. Within the constructor, label 2 is referenced by a local variable called label that hides the member variable called label.
Your intent is to write something like this instead:
public class ObjectReferences {
private final JLabel label = new JLabel("I am FOO");
public ObjectReferences() {
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
onclick();
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setLayout(new FlowLayout());
frame.add(label);
frame.add(button);
frame.setVisible(true);
}
public void onclick() {
JOptionPane.showMessageDialog(null, label.getText());
}
public static void main(String[] args) {
new ObjectReferences();
}
}

Categories