I'm trying to create a field which accepts doubles only. I want the value to be commited without the user having to click on enter. So I am setting a listener to the changes that are happening and setting the value each time.
Here is some of my code:
// Change the behaviour of the converter to avoid empty strings and values outside the defined bounds
valueFactory.setConverter(new StringConverter<Double>() {
private final DecimalFormat format = new DecimalFormat("#.##");
#Override
public String toString(Double value) {
if (value == null) {
return format.format(0);
}
return value.toString();
}
#Override
public Double fromString(String string) {
try {
if (string == null || string.trim().length() < 0 || string.trim().length() > MAX_LENGTH) {
return null;
} else {
Double newVal = format.parse(string).doubleValue();
return (newVal >= min && max >= newVal) ? newVal : null;
}
} catch (Exception ex) {
return 0.00;
}
}
});
// Define a formatter on the text entered into the field
TextFormatter<Object> textFormatter = new TextFormatter<>(c -> {
if (c.getText().matches("[^0-9.]+") && !c.getText().trim().isEmpty()) {
return null;
}
if(c.getControlNewText().length() <= MAX_LENGTH) {
try {
Double newVal = Double.valueOf(c.getControlNewText());
return (newVal >= min && max >= newVal) ? c : null;
} catch (Exception ex) {
if(c.getControlNewText().isEmpty()) {
c.setText("0.00");
} else if(c.getControlNewText().length() == 1) {
c.setText("0.00");
} else {
c.setText("");
}
return c;
}
} else {
c.setText("");
return c;
}
});
getEditor().setTextFormatter(textFormatter);
getEditor().textProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if(!newValue.trim().isEmpty()) {
try {
setValue(Double.parseDouble(newValue), amountToStepBy);
} catch(Exception e) {
setValue(min, amountToStepBy);
getEditor().setText(min.toString());
}
}
}
});
I want the user to only be able to add double numbers in the format #.## only. The problem is this fails when I enter a number like 0.00000001 and I get an exception:
java.lang.IllegalArgumentException: The start must be <= the end
at javafx.scene.control.TextInputControl.getText(TextInputControl.java:446)
at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:564)
at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548)
at com.sun.javafx.scene.control.skin.TextFieldSkin.replaceText(TextFieldSkin.java:576)
Also the text field gets edited with the value 1.0E-8.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Below is the code. I cannot figure out why in class Database my else if the state runs simultaneously with my if statement IF I have entered the second bird into the ArrayList. please, any help would be appreciated!
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Database d1 = new Database();
while (true) {
System.out.println("What do you want to do?");
String answer = input.nextLine();
if(answer.equalsIgnoreCase("Add")){
System.out.println("Name: ");
String name = input.nextLine();
System.out.println("Latin name: ");
String lName = input.nextLine();
d1.addBird(name, lName);
} else if (answer.equalsIgnoreCase("O")) {
System.out.println("What was observed?");
String observed = input.nextLine();
d1.Observation(observed);
} else if (answer.equalsIgnoreCase("stats")) {
d1.showBirds(); //Displays all with observations.
} else if (answer.equalsIgnoreCase("show")) {
System.out.println("What?");
String search = input.nextLine();
d1.searchBird(search);
} else if (answer.equalsIgnoreCase("quit")){
break;
}
}
}
}
public class Bird {
private final String name;
private final String latinName;
private int count;
public Bird (String name, String latinName) {
this.name = name;
this.latinName = latinName;
this.count = count;
}
public String getName () {
return this.name;
}
public String getLatin() {
return this.latinName;
}
public String add () {
return this.name + " " + "(" +this.latinName + ")"+ " " + this.count + " observation(s)";
}
public void increaseCount () {
this.count++;
}
}
import java.util.ArrayList;
public class Database {
private final ArrayList<Bird> birdList;
public Database() {
this.birdList = new ArrayList<Bird>();
}
public void addBird (String name, String lname) {
this.birdList.add(new Bird(name, lname));
}
public void Observation (String observed) {
for (Bird x : getBirds()) { // this has to be a method
if (x.getName() != null && x.getLatin() != null && x.getName().contains(observed) || x.getLatin().contains(observed)) {
System.out.println("Done");
System.out.println("");
x.increaseCount();
} else if (x.getName() != observed || x.getLatin() != observed) {
System.out.println("Not a bird");
}
}
}
public void showBirds () {
for (Bird x : this.birdList) {
System.out.println(x.add());
}
}
public ArrayList<Bird> getBirds() {
return this.birdList;
}
public void searchBird(String search) {
for (Bird x : getBirds()) {
if (x.getName().contains(search)) {
System.out.println(x.add());
}
}
}
}
I think the problem lies in this method:
public void Observation (String observed) {
for (Bird x : getBirds()) { // this has to be a method
if (x.getName() != null && x.getLatin() != null && x.getName().contains(observed) || x.getLatin().contains(observed)) {
System.out.println("Done");
System.out.println("");
x.increaseCount();
}
/* No need to print "Not a bird" for every mismatch. Use a flag instead */
else if (x.getName() != observed || x.getLatin() != observed) {
System.out.println("Not a bird");
}
}
}
Do something like this:
public void Observation (String observed) {
boolean found = false;
for (Bird x : getBirds()) { // this has to be a method
if (x.getName() != null && x.getLatin() != null && x.getName().contains(observed) || x.getLatin().contains(observed)) {
System.out.println("Done");
System.out.println("");
x.increaseCount();
found = true;
}
}
if (!found) {
System.out.println("Not a bird");
}
}
I'm completely brand new to programming (started yesterday...) and Java so excuse any stupid mistakes and really awful code (I have no clue how to order/format). I've been given a task to make an inventory of videos and I want to be able to search through the inventory to check if a particular video is there.
I know I can use contains to do this but I can't get it to work with my custom objects ArrayList (videos) and I want it to search through all the data (each InventoryRow below). I've overridden equals and HashCode but it still won't work - whenever I try to run the code it will always tell me it can't find the video even if the video is there. (FYI I use contains towards the end of my code under the rent and check functions)
I'd really appreciate any help as I've been googling all day to no avail. Also if this can't be done or another method would be better please let me know! Thanks.
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
class InventoryRow {
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((availability == null) ? 0 : availability.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((returndate == null) ? 0 : returndate.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
InventoryRow other = (InventoryRow) obj;
if (availability == null) {
if (other.availability != null)
return false;
} else if (!availability.equals(other.availability))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (returndate == null) {
if (other.returndate != null)
return false;
} else if (!returndate.equals(other.returndate))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
private String name;
private String type;
private Character availability;
private String returndate;
public InventoryRow(String name, String type, Character availability,
String returndate) {
this.name = name;
this.type = type;
this.availability = availability;
this.returndate = returndate;
}
public String getReturndate() {
return returndate;
}
public void setReturndate(String returndate) {
this.returndate = returndate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Character getAvailability() {
return availability;
}
public void setAvailability(Character availability) {
this.availability = availability;
}
public String toString() {
return name + " " + type + " " + availability + " " + returndate;
}
}
public class InventorySort {
public static void main(String[] args) {
List<InventoryRow> videos = new ArrayList<InventoryRow>();
videos.add(new InventoryRow("Casablanca", "Old", 'Y', "1 January 2015"));
videos.add(new InventoryRow("Jurassic Park", "Regular", 'N',
"1 January 2015"));
videos.add(new InventoryRow("2012", "Regular", 'Y', "1 January 2015"));
videos.add(new InventoryRow("Ant-Man", "New", 'Y', "1 January 2015"));
// Another ArrayList because I can't seem to search through the first
// one?
/*ArrayList<String> names = new ArrayList<String>();
names.add("Casablanca");
names.add("Jurassic Park");
names.add("2012");
names.add("Ant-Man");*/
Scanner input = new Scanner(System.in);
// Output the prompt
System.out.println("What do you want to do?");
// Wait for the user to enter a line of text
String line = input.nextLine();
// List, rent and check functions
// List function
if (line.equals("l")) {
// Sort function
Collections.sort(videos, new Comparator<InventoryRow>() {
public int compare(InventoryRow o1, InventoryRow o2) {
return o1.getName().compareTo(o2.getName());
}
});
for (InventoryRow inventory : videos) {
System.out.println(inventory);
}
// Rent function
} else if (line.equals("r")) {
System.out.println("Which video would you like to rent?");
String line2 = input.nextLine();
// Search through ArrayList
if (videos.contains(line2)) {
System.out.println("Video available to rent!");
} else {
System.out.println("Video unavailable to rent.");
}
// Check function
} else if (line.equals("c")) {
System.out
.println("Which video would you like to check is in the inventory?");
String line3 = input.nextLine();
// Search through ArrayList
if (videos.contains(line3)) {
System.out.println("Video found!");
} else {
System.out
.println("Video not found. Please see the inventory below.");
Collections.sort(videos, new Comparator<InventoryRow>() {
public int compare(InventoryRow o1, InventoryRow o2) {
return o1.getName().compareTo(o2.getName());
}
});
for (InventoryRow inventory : videos) {
System.out.println(inventory);
}
}
// If anything else is entered
} else {
System.out
.println("The only options are to list (l), rent (r) or check (c).");
}
}
}
You can use contains. But, for the first day of programming, it might be more understandable to simply iterate over your inventory, comparing the input string with the video name:
boolean foundIt = false;
for (InventoryRow ir : videos) {
if (line3.equals(ir.getName())) {
foundIt = true;
break;
}
}
if (foundIt) {
System.out.println("Video found!");
Alternative to #kilo answer, you could implement equals and hashcode method only on the name of video class and check it in the following way.
String line3 = input.nextLine();
// Search through ArrayList
if (videos.contains(new Video(line3, null, null, null))) {
System.out.println("Video found!");
}
This will return contains = true only if the name matches.
In another class im using the setRating to change the ratings of these songs, however I'm not sure what I need to do to this code to be able to change the rating permanently. Thanks in advance.
import java.util.*;
public class LibraryData {
static String playCount() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
static int setRating(int stars) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
private static class Item {
Item(String n, String a, int r) {
name = n;
artist = a;
rating = r;
}
// instance variables
private String name;
private String artist;
private int rating;
private int playCount;
public String toString() {
return name + " - " + artist;
}
}
// with a Map you use put to insert a key, value pair
// and get(key) to retrieve the value associated with a key
// You don't need to understand how this works!
private static Map<String, Item> library = new TreeMap<String, Item>();
static {
// if you want to have extra library items, put them in here
// use the same style - keys should be 2 digit Strings
library.put("01", new Item("How much is that doggy in the window", "Zee-J", 3));
library.put("02", new Item("Exotic", "Maradonna", 5));
library.put("03", new Item("I'm dreaming of a white Christmas", "Ludwig van Beethoven", 2));
library.put("04", new Item("Pastoral Symphony", "Cayley Minnow", 1));
library.put("05", new Item("Anarchy in the UK", "The Kings Singers", 0));
}
public static String listAll() {
String output = "";
Iterator iterator = library.keySet().iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
Item item = library.get(key);
output += key + " " + item.name + " - " + item.artist + "\n";
}
return output;
}
public static String getName(String key) {
Item item = library.get(key);
if (item == null) {
return null; // null means no such item
} else {
return item.name;
}
}
public static String getArtist(String key) {
Item item = library.get(key);
if (item == null) {
return null; // null means no such item
} else {
return item.artist;
}
}
public static int getRating(String key) {
Item item = library.get(key);
if (item == null) {
return -1; // negative quantity means no such item
} else {
return item.rating;
}
}
public static void setRating(String key, int rating) {
Item item = library.get(key);
if (item != null) {
item.rating = rating;
}
}
public static int getPlayCount(String key) {
Item item = library.get(key);
if (item == null) {
return -1; // negative quantity means no such item
} else {
return item.playCount;
}
}
public static void incrementPlayCount(String key) {
Item item = library.get(key);
if (item != null) {
item.playCount += 1;
}
}
public static void close() {
// Does nothing for this static version.
// Write a statement to close the database when you are using one
}
}
Inside Item, you should write this method:
public static void setRating(int rating0) {
rating = rating0;
}
You should also change your instance variables into static variables by calling them "public static" instead of just "public."
I can find plenty of Q&A on here about whether an arraylist can equal null, which was helpful in its own way, but I can't find an answer for throwing errors if any fields in the arraylist are null. As I'm adding objects to the arraylist, I want to throw an exception if the user tries to pass in anything that is null. Here is the code:
void addInvoiceItem(Item item, Integer quantity, double discount) throws Exception {
for (InvoiceItem thing: invoiceList) {
if (thing == null) {
throw new IllegalArgumentException("Part of the invoice item is blank (null). Please review your invoice items and ensure you have specified values for the item.");
}
else {
invoiceList.add(thing);
thing.setItemQuantity(quantity);
thing.setItemDiscount(discount);
System.out.println(invoiceList);
}
}
}
Here is the Item class:
final class Item {
String itemDescription;
double itemPrice;
Integer itemSKU;
Item (String description, double price, Integer sku) {
this.itemDescription = description;
this.itemPrice = price;
this.itemSKU = sku;
}
}
Here are the test methods that are letting me know I'm definitely omitting something. One is to test for a valid InvoiceItem, the other for an invalid one (contains nulls):
public class InvoiceTest {
//create the static values to be used
//for InvoiceItem
String goodDescription = "wheel";
double goodPrice = 500.00;
Integer goodSku = 0002;
Item goodInvoiceItem = new Item(goodDescription, goodPrice, goodSku);
String emptyDescription = null;
double emptyPrice = 0;
Integer emptySku = 0;
Item badInvoiceItem = new Item(emptyDescription, emptyPrice, emptySku);
Integer itemQuantity = 0;
double itemDiscount = 0.05;
#Test
public void invalidItemAddTest() {
Invoice badInvoice = new Invoice(null);
try {
badInvoice.addInvoiceItem(badInvoiceItem, itemQuantity, itemDiscount);
System.out.println(badInvoice);
} catch (Exception e) {
e.printStackTrace();
}
}
#Test
public void validItemAddTest() {
Invoice goodInvoice = new Invoice(null);
try {
goodInvoice.addInvoiceItem(goodInvoiceItem, itemQuantity, itemDiscount);
System.out.println(goodInvoice);
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks in advance for all your help
Edit with additions:
So Mel's answer was my starting point and I made some additions to get it working the way I needed to. My adding method now looks like this:
void addInvoiceItem(Item item, Integer quantity, double discount) {
if(item == null || quantity == 0 || discount == 0) {
throw new IllegalArgumentException("Part of the invoice item is blank (null). Please review your invoice items and ensure you have specified values for the item.");
} else {
InvoiceItem invoice = new InvoiceItem(item, quantity, discount);
invoiceList.add(invoice);
}
}
and my test methods look like this:
public class InvoiceTest {
//create the static values to be used
//for InvoiceItem
String goodDescription = "wheel";
double goodPrice = 500.00;
int goodSku = 0002;
Item goodInvoiceItem = new Item(goodDescription, goodPrice, goodSku);
String emptyDescription = null;
double emptyPrice = 0;
int emptySku = 0;
Item badInvoiceItem = new Item(emptyDescription, emptyPrice, emptySku);
int badItemQuantity = 0;
double badItemDiscount = 0;
int goodItemQuantity = 1;
double goodItemDiscount = 0.05;
/**
* #Before - initialize what we need for the test
* #throws Exception
*/
#Before
public void setUp() {
//things needed for testInvalidItemAdd()
}
/**
* #throws Exception
* #Test - confirm you cannot add an item that is null
*/
#Test
public void invalidItemAddTest() {
boolean exceptionThrown = false;
Invoice badInvoice = new Invoice(null);
try {
badInvoice.addInvoiceItem(badInvoiceItem, badItemQuantity, badItemDiscount);
System.out.println(badInvoice);
} catch (Exception e) {
e.printStackTrace();
exceptionThrown = true;
}
assertTrue(exceptionThrown);
}
#Test
public void validItemAddTest() {
boolean exceptionThrown = false;
Invoice goodInvoice = new Invoice(null);
try {
goodInvoice.addInvoiceItem(goodInvoiceItem, goodItemQuantity, goodItemDiscount);
System.out.println(goodInvoice);
} catch (Exception e) {
e.printStackTrace();
exceptionThrown = true;
}
assertFalse(exceptionThrown);
}
Your add routine is a little off. It tries to use an item that is already in the list rather than creating a new one. Try this:
void addInvoiceItem(Item item, Integer quantity, double discount) {
if(
item == null ||
quantity == null ||
item.sku == null ||
item.description == null
) {
throw new NullPointerException();
}
InvoiceItem invoice = new InvoiceItem(item, quantity, discount);
invoiceList.add(invoice);
}
Also take a look a checkNotNull( ) from the google library to reduce typing a bit.
It may be useful to check for null in the InvoiceItem constructor rather than in the adder, unless you want to allow nulls elsewhere.
How do I format a value that is fetched from a command object on front end.
Its an SSN value which comes from the DB without any "-" (Hyphens). How do I convert this?
example: Convert 123456789 into 123-45-6789. Also the in the backing bean this field is an Int.
How about creating a custom property editor?
Spring uses custom property editors to format special data, like SSN.
An IntegerPropertyEditor looks like this:
package com.pnt.common.propertyeditor;
import java.beans.PropertyEditorSupport;
import com.pnt.util.number.NumUtils;
public class IntegerPropertyEditor extends PropertyEditorSupport {
//private static final Log logger = LogFactory.getLog(IntegerPropertyEditor.class);
public void setValue(Object value) {
if (value==null) {
super.setValue(null);
}
else if (value instanceof Integer) {
super.setValue(value);
}
else if (value instanceof String) {
setValue(NumUtils.stringToInteger((String)value));
}
else {
super.setValue(NumUtils.stringToInteger(value.toString()));
}
}
public void setAsText(String text) {
setValue(NumUtils.stringToInteger(text.replaceAll(" ", "")));
}
public String getAsText() {
Integer value = (Integer)getValue();
if (value != null){
String t = value.toString();
int k = 1;
for (int i = t.length() - 1; i >= 0; i--) {
if (k % 3 == 0 && i != 0)
t = t.substring(0, i) + " " + t.substring(i);
k++;
}
return t;
}
else
return "";
}
}
And you have to register it in the controller's initBinder() method:
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder ){
try {
binder.registerCustomEditor(Integer.class, "ssnField", new IntegerPropertyEditor());
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Where "ssnField" is the name of the field.
Now all you have to do is tweak the PropertyEditor to match your format.
How about using fmt:substring