A JFormattedTextField to accept a currency format without decimals - java

How do I code a JFormattedTextField to accept a currency format without decimals?
I have tried looking for my answer everywhere. Here, Oracle, Google, and Code Ranch to be specific.
My question: How do I code a formatted text field to accept a currency format without decimals. The text field can accept a value anywhere from $5 to $10,000,000. I would like it to include the "," when need. This field will not be used for mathematical expressions so there is no need to convert it from a string.
Here is the code that I am trying to use. This format is not allowing me to enter any digits at all in the formatted text field.
buildInfo method
//The buildInfo method will build the info panel
private void buildInfo()
{
info = new JPanel();
GridLayout gl = new GridLayout (3,1);
info.setLayout (gl);
//Create panel, label, and text area for pledgers name
p1 = new JPanel();
p1.setLayout(new FlowLayout(FlowLayout.LEFT));
label1 = new JLabel ("Pledger's Name: ");
p1.add (label1);
text1 = new JTextField (20);
p1.add (text1);
//Create panel, label, and text area for pledge amount
p2 = new JPanel();
p2.setLayout(new FlowLayout(FlowLayout.LEFT));
label2 = new JLabel ("Pledged Amount: ");
p2.add (label2);
NumberFormat amount = NumberFormat.getCurrencyInstance(Locale.US);
amount.setMaximumFractionDigits(0);
NumberFormatter pAmount = new NumberFormatter(amount);
pAmount.setMinimum(5.0);
pAmount.setMaximum(10000000.0);
pAmount.setAllowsInvalid(false);
text2 = new JFormattedTextField (pAmount);
text2.setColumns(12);
p2.add (text2);
//Create panel, label, and text area for charity being pledged
p3 = new JPanel();
p3.setLayout(new FlowLayout(FlowLayout.LEFT));
label3 = new JLabel ("Charity Pledged To:");
p3.add (label3);
text3 = new JTextField (20);
p3.add (text3);
//Add panels to main panel
add(p1);
add(p2);
add(p3);
}

Use
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.US);
format.setMaximumFractionDigits(0);
NumberFormatter formatter = new NumberFormatter(format);
formatter.setMinimum(5.0);
formatter.setMaximum(10000000.0);
formatter.setAllowsInvalid(false);
formatter.setOverwriteMode(true);
JFormattedTextField field = new JFormattedTextField(formatter);
field.setValue(5.0);

Related

What can I modify in my JavaFX GUI that will display the output correctly? It displays the tips for integers only

I am a beginner currently learning JavaFX in my college programming class. I am designing a tip calculator, but I cannot get it to display the tip and check information if the starting check amount is a double. How can I modify my code to display the correct outputs? Would it be an issue with my Lambda expression?
// declare interface controls
Label titleLabel, checkAmtLabel, tipPercentLabel, splitLabel, tipAmtLabel;
Label totalLabel, amtPerPersonLabel;
TextField checkAmtText, tipAmtText, totalText, amtPerPersonText;
Slider tipPercentSlider;
ChoiceBox splitChoiceBox;
Button calcTipButton;
// declare a grid pane (8 rows and 2 columns)
GridPane grid;
#Override
public void start(Stage primaryStage) {
// instantiate labels and their properties
titleLabel = new Label("Tip Calculator");
titleLabel.setMaxWidth(Double.MAX_VALUE);
titleLabel.setAlignment(Pos.CENTER);
checkAmtLabel = new Label("Check Amount");
checkAmtLabel.setMaxWidth(Double.MAX_VALUE);
checkAmtLabel.setAlignment(Pos.CENTER_RIGHT);
tipPercentLabel = new Label("Tip Percent: ");
tipPercentLabel.setMaxWidth(Double.MAX_VALUE);
tipPercentLabel.setAlignment(Pos.CENTER_RIGHT);
splitLabel = new Label("Split");
splitLabel.setMaxWidth(Double.MAX_VALUE);
splitLabel.setAlignment(Pos.CENTER_RIGHT);
tipAmtLabel = new Label("Tip Amount");
tipAmtLabel.setMaxWidth(Double.MAX_VALUE);
tipAmtLabel.setAlignment(Pos.CENTER_RIGHT);
totalLabel = new Label("Total");
totalLabel.setMaxWidth(Double.MAX_VALUE);
totalLabel.setAlignment(Pos.CENTER_RIGHT);
amtPerPersonLabel = new Label("Amount Per Person");
amtPerPersonLabel.setMaxWidth(Double.MAX_VALUE);
amtPerPersonLabel.setAlignment(Pos.CENTER_RIGHT);
// instantiate text fileds and their properties
checkAmtText = new TextField();
tipAmtText = new TextField();
tipAmtText.setEditable(false);
totalText = new TextField();
totalText.setEditable(false);
amtPerPersonText = new TextField();
amtPerPersonText.setEditable(false);
//checkAmtText.setOnMouseClick(e -> clearClick());
// instantiate a slider and its properties
tipPercentSlider = new Slider();
tipPercentSlider.setPrefWidth(300);
tipPercentSlider.setMin(0);
tipPercentSlider.setMax(25);
tipPercentSlider.setMajorTickUnit(5);
tipPercentSlider.setMinorTickCount(0);
tipPercentSlider.setBlockIncrement(5);
tipPercentSlider.setShowTickLabels(true);
tipPercentSlider.setShowTickMarks(true);
tipPercentSlider.setSnapToTicks(true);
tipPercentSlider.setOrientation(Orientation.HORIZONTAL);
tipPercentSlider.valueProperty().addListener(
(observable, oldvalue, newvalue) ->
{
// show integer values only
tipPercentLabel.setText(String.format("Tip Percent: %2d%s",newvalue.intValue(),"%"));
} );
// instantiate a choice box and its properties
splitChoiceBox = new ChoiceBox();
splitChoiceBox.getItems().addAll("1", "2", "3", "4", "5");
splitChoiceBox.setValue("1");
// instantiate a button and its properties
calcTipButton = new Button("Calculate Tip");
calcTipButton.setMaxWidth(Double.MAX_VALUE);
calcTipButton.setOnAction(e -> calcTipClick());
// instantiate a grid pane and its properties
grid = new GridPane();
grid.setHgap(15);
grid.setVgap(15);
grid.setPadding(new Insets(10));
grid.add(titleLabel, 0, 0, 2, 1);
grid.addRow(1, checkAmtLabel, checkAmtText);
grid.addRow(2, tipPercentLabel, tipPercentSlider);
grid.addRow(3, splitLabel, splitChoiceBox);
grid.add(calcTipButton, 0, 4, 2, 1);
grid.addRow(5, tipAmtLabel, tipAmtText);
grid.addRow(6, totalLabel, totalText);
grid.addRow(7, amtPerPersonLabel, amtPerPersonText);
// instantiate the grid pane and put items in in grid
Scene scene = new Scene(grid);
scene.getRoot().setStyle("-fx-font: 15 'Comic Sans MS'");
primaryStage.setTitle("Tip Calculator");
primaryStage.setScene(scene);
primaryStage.show();
}
private void calcTipClick() {
//Gather choiceBox
String choiceInput = splitChoiceBox.getValue().toString();
int choiceSelection = Integer.parseInt(choiceInput.substring(0, 1));
//Gather Slider information
Number sliderInput = tipPercentSlider.getValue();
//Gather textField amount
String val = checkAmtText.getText();
//I Used a string converter in this part
NumberStringConverter nsc = new NumberStringConverter();
Number amount = 0;
Number tipAmount = amount.doubleValue() * sliderInput.doubleValue()/100;
tipAmtText.setText(tipAmount.toString());
Number totalAmount = tipAmount.doubleValue() + amount.doubleValue();
totalText.setText(totalAmount.toString());
Number perPerson = totalAmount.doubleValue() / choiceSelection;
amtPerPersonText.setText(perPerson.toString());
}
Start by using generics with the ChoiceBox:
ChoiceBox<Integer> = new ChoiceBox<>();
// ...
splitChoiceBox.getItems().addAll(1, 2, 3, 4, 5);
splitChoiceBox.setValue(1);
This ensures type safety and takes care of retrieving the value as an int:
//Gather choiceBox
int choiceSelection = splitChoiceBox.getValue();
Now to your calcTipClick method. Why convert doubles to Number and then back to double? Just use double in first place:
//Gather Slider information
double sliderInput = tipPercentSlider.getValue();
//...
double tipAmount = amount * sliderInput / 100;
double totalAmount = tipAmount + amount;
double perPerson = totalAmount / choiceSelection;
To convert double to String Google that and after you found the answer look at the bottom of this one.
To convert String to double do the same as above.
As to why nothing is displayed in your fields, look again at your code for this method and use a debugger to find out where what you think should be happening isn't happening. It's trivial.
Note: Don't use fields when local variables will do (e.g., your labels).
double to String:
tipAmtText.setText(String.valueOf(tipAmount));
totalText.setText(totalAmount + "");
amtPerPersonText.setText(Double.toString(perPerson));
String to double:
Double.parseDouble(val)
fromString(val) of your NumberStringConverter if you really need to

creating JFrame with variable amount of JLabels

I am currently trying to make a JFrame which should contain one String followed by a text entry field for each entry in a HashMap (longToShortNamesMap). Currently I am displaying the entries as follws in a JOptionPane:
String paneMessage = "";
List keys = new ArrayList(longToShortNameMap.keySet());
for(int i = 0 ; i < keys.size();i++){
paneMessage += "Field name " + keys.get(i) + " has been shortened to " + longToShortNameMap.get(keys.get(i)) + "\n";
}
JOptionPane.showMessageDialog (null, paneMessage, "Data Changed", JOptionPane.INFORMATION_MESSAGE);
Instead, I would like a frame to appear which will have the same message appear but will have the "longToShortNameMap.get(keys.get(i))" part appear in an editable text field. I'm not quite sure how ot go about this but this is what I have so far which is popping one JFrame with one label (which is not an editable text field).
private static void showFrames(Map<String,String> longToShortNameMap) {
JFrame frame = new JFrame("Data Changed");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 500);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
JPanel panel = new JPanel(new BorderLayout());
List<String> keys = new ArrayList(longToShortNameMap.keySet());
for (String key : keys) {
JLabel label = new JLabel(longToShortNameMap.get(key));
panel.add(label);
}
frame.add(panel);
}
EDIT: As a contextual side note, I am doing this because field names are limited to 10 characters in a place in my application so I am forced to trim the field names down to 10 characters. When I do this, I want to notify the user what each trimmed field has been trimmed to and additionally give them the option to change the trimmed named
Your main issue is your choice of layout manager. BorderLayout allows one component in each of its 5 areas. When you're adding your labels to the center area (the default), you keep replacing the last one instead of appending it. I recommend adding each label and JTextField (your editable field) to a GridLayout panel.
private static void showFrames(Map<String,String> longToShortNameMap) {
JFrame frame = new JFrame("Data Changed");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 500);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
JPanel panel = new JPanel(new GridLayout(0, 2)); //use gridlayout
List<String> keys = new ArrayList(longToShortNameMap.keySet());
for (String key : keys) {
JLabel label = new JLabel(key); // your label is the key itself
JTextField textField = new JTextField(longToShortNameMap.get(key));
panel.add(label); // Populate textfield with the key's value
panel.add(textField);
}
frame.add(panel);
}

NumberFormatter not behaving as expected

I didn't find any java question that helped me solve my problem, so here I come.
I'm currently trying to use a NumberFormatter with a JFormattedTextField to format a price in a GUI as the user types it in.
But I'm getting strange results after typing 2 digits in the textfield.
Here the code I use to test (Netbeans 8.0 + JDK 1.7.0_51):
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator('.');
symbols.setGroupingSeparator(' ');
symbols.setCurrencySymbol("EUR");
DecimalFormat format = new DecimalFormat("¤ #,##0.00", symbols);
format.setMaximumFractionDigits(2);
format.setGroupingUsed(true);
NumberFormatter formatter = new NumberFormatter(format);
formatter.setMinimum( 0.00);
formatter.setMaximum(9_999.99);
formatter.setAllowsInvalid(false);
formatter.setOverwriteMode(true);
JFormattedTextField field = new JFormattedTextField(formatter);
field.setColumns(10);
field.setValue(0.33);
frame.add(field);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
What I expect :
// Step Text in TextField
// 1: GUI started EUR <caret>0.33
// 2: '1' pressed EUR 1<caret>.33
// 3: '2' pressed EUR 12<caret>.33
What I get :
// Step Text in TextField
// 1: start GUI EUR <caret>0.33 [OK]
// 2: press '1' EUR 1<caret>.33 [OK]
// 3: press '2' EUR 1 2<caret>33.00 [NOK, see expected result above]
To me it looks like the Formatter does (for step 3) :
insert '2' at the caret position -> EUR 12.33
remove all 'formatting characters' -> 1233
Formats the result of the "removal" again -> EUR 1 233.00
Is this the default behavior for the NumberFormatter?
If yes, am I missing something in the setup of the formatter or do I need to write a custom one?
If not, what am I doing wrong?
Regards,
Xan.
seems like as I'm haven't a.m., described issue, to test the setting for InputVerifier as is described in API ,
I'd suggest to use plain JTextField with DocumentFilter and the ISO name for currency to wrap by using NavigationFilter, e.g. excelent code example by camickr
.
import java.awt.*;
import java.math.*;
import java.text.*;
import javax.swing.*;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.text.InternationalFormatter;
public class DocumentListenerAdapter {
public DocumentListenerAdapter() {
JFrame frame = new JFrame("AbstractTextField Test");
final JFormattedTextField textField1 = new JFormattedTextField(new Float(10.01));
textField1.setFormatterFactory(new AbstractFormatterFactory() {
#Override
public AbstractFormatter getFormatter(JFormattedTextField tf) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator('.');
symbols.setGroupingSeparator(' ');
symbols.setCurrencySymbol("EUR");
DecimalFormat format = new DecimalFormat("¤ #,##0.00", symbols);
format.setMaximumFractionDigits(2);
format.setGroupingUsed(true);
//NumberFormat format = DecimalFormat.getInstance();
format.setMinimumFractionDigits(2);
format.setMaximumFractionDigits(2);
format.setRoundingMode(RoundingMode.HALF_UP);
InternationalFormatter formatter = new InternationalFormatter(format);
formatter.setAllowsInvalid(false);
formatter.setMinimum(0.0);
formatter.setMaximum(9000.00);
return formatter;
}
});
NumberFormat numberFormat = NumberFormat.getNumberInstance();
numberFormat.setMaximumFractionDigits(2);
numberFormat.setMaximumFractionDigits(2);
numberFormat.setRoundingMode(RoundingMode.HALF_UP);
final JFormattedTextField textField2 = new JFormattedTextField(numberFormat);
textField2.setValue(new Float(10.01));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(textField1, BorderLayout.NORTH);
frame.add(textField2, BorderLayout.SOUTH);
frame.setVisible(true);
frame.pack();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new DocumentListenerAdapter();
}
});
}
}

GUI java text and textfields opposite displayed

I am new to gui in java, i spent 3
hours trying to figure out what i have done wrong or misunderstood, i should get this:
but the text in my code is displayed after textfields
textPanel = new JPanel();
textPanel.setLayout(new GridLayout(3,0));
fName = new JTextField( 15 ) ;
textPanel.add(fName);
jlbName = new JLabel ( "Firstname" );
jlbName.setHorizontalAlignment(JLabel.RIGHT);
textPanel.add(jlbName);
lName = new JTextField( 15 ) ;
textPanel.add(lName);
jlbName = new JLabel ( "LastName" );
jlbName.setHorizontalAlignment(JLabel.RIGHT);
textPanel.add(jlbName);
libNo = new JTextField( 15 ) ;
textPanel.add(libNo);
libNo.setEditable(false);
jlbName = new JLabel ( "Library Number" );
jlbName.setHorizontalAlignment(JLabel.RIGHT);
textPanel.add(jlbName);
add(textPanel,BorderLayout.EAST);
JButton jbtN = new JButton("Add borrower");
add(jbtN ,BorderLayout.SOUTH);
You are inserting the components into the panel in the wrong order. You first insert the text fields and later the labels. Do the opposite, i.e. instead of:
textPanel.add(fName);
...
textPanel.add(jlbName);
...
do:
textPanel.add(jlbName);
...
textPanel.add(fName);
...

"Unexpected type" error

I'm having a problem compiling my Java program:
\Desktop\Java Programming\JFrameWithPanel.java:79: unexpected type
required: variable
found : value
if(serviceTerms.isSelected() = false)
^
1 error
What is causing this error?
public class JFrameWithPanel extends JFrame implements ActionListener, ItemListener
{
int packageIndex;
double price;
double[] prices = {49.99, 39.99, 34.99, 99.99};
DecimalFormat money = new DecimalFormat("$0.00");
JLabel priceLabel = new JLabel("Total Price: "+price);
JButton button = new JButton("Check Price");
JComboBox packageChoice = new JComboBox();
JPanel pane = new JPanel();
TextField text = new TextField(5);
JButton accept = new JButton("Accept");
JButton decline = new JButton("Decline");
JCheckBox serviceTerms = new JCheckBox("I Agree to the Terms of Service.", false);
JTextArea termsOfService = new JTextArea("This is a text area", 5, 10);
public JFrameWithPanel()
{
super("JFrame with Panel");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pane.add(packageChoice);
setContentPane(pane);
setSize(250,250);
setVisible(true);
packageChoice.addItem("A+ Certification");
packageChoice.addItem("Network+ Certification ");
packageChoice.addItem("Security+ Certifictation");
packageChoice.addItem("CIT Full Test Package");
pane.add(button);
button.addActionListener(this);
pane.add(text);
text.setEditable(false);
text.setBackground(Color.WHITE);
text.addActionListener(this);
pane.add(termsOfService);
termsOfService.setEditable(false);
termsOfService.setBackground(Color.lightGray);
pane.add(serviceTerms);
serviceTerms.addItemListener(this);
pane.add(accept);
accept.addActionListener(this);
pane.add(decline);
decline.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
packageIndex = packageChoice.getSelectedIndex();
price = prices[packageIndex];
text.setText("$"+price);
Object source = e.getSource();
if(source == accept)
{
if(serviceTerms.isSelected() = false) // line 79
{
JOptionPane.showMessageDialog(null,"Please accept the terms of service.");
}
else
{
JOptionPane.showMessageDialog(null,"Thanks.");
}
}
}
You have an (illegal) assignment instead of a comparison. Surely you mean:
if (serviceTerms.isSelected() == false)
Of course the preferential, and more readable, way to write this condition is:
if (!serviceTerms.isSelected())
The problem is that you are using the assignment operator =. What you should be using is the equality operator == like the following:
if(serviceTerms.isSelected() == false) // line 79
{
JOptionPane.showMessageDialog(null,"Please accept the terms of service.");
}
Or, to totally bypass this mistake, you should skip comparing to false and use the ! (not) operator like so.
if(!serviceTerms.isSelected()) // line 79
{
JOptionPane.showMessageDialog(null,"Please accept the terms of service.");
}
I feel this way reads better.
If not, service terms is selected
That reads more like a sentence than:
If service terms is selected equals false

Categories