I have been think for somedays how to fix this but i need someone’s help.
I have a 2 tableviews and one is fill up with data. and if customer clicked on a row it gets it to other tableview. but the problem is with total price which supposed to dynamical add any item pick by a user.
I got this code and is perfect but I can’t seem to get the total to label and not in a row.
model
private final ReadOnlyObjectWrapper<Double> total = new ReadOnlyObjectWrapper<>();
public LineItemProperty(String name, Integer quantity, Double unitPrice) {
setName(name);
setQuantity(quantity);
setUnitPrice(unitPrice);
// Obvious binding for the total of this line item:
// total = quantity * unit price
total.bind(Bindings.createObjectBinding(new Callable<Double>() {
#Override
public Double call() throws Exception {
if (quantityProperty().get() == null || unitPriceProperty().get() == null) {
return 0.0;
}else{
return quantityProperty().get() * unitPriceProperty().get();
}
}
}, quantityProperty(), unitPriceProperty()));
}
in view
table.getColumns().add(column("Total Price", LineItemProperty::totalProperty, false, null));
final Label selected = new Label("Total");
another class for total
public class LineItemListWithTotal extends TransformationList<LineItemProperty, LineItemProperty>{
private final TotalLine totalLine;
public LineItemListWithTotal(
ObservableList<? extends LineItemProperty> source) {
super(source);
totalLine = new TotalLine(source);
}
#Override
protected void sourceChanged(ListChangeListener.Change<? extends LineItemProperty> c) {
// no need to modify change:
// indexes generated by the source list will match indexes in this
// list
fireChange(c);
}
Thanx a lot. any idea will help and appreciated
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
So I am very new to Java... been at it for about 4 weeks... be gentle.
I am trying to get my takeItem method (below) to pass the itemName variable back to my Player Class so I can add an item from my current room to my player. I get the compiler error: Constructor Item in class Item cannot be applied to given types..
my end goal is to get the player class to hold the object after removing it from the room.
takeItem Method:
private void takeItem(Command command)
{
if(!command.hasSecondWord()) {
// if there is no second word, we don't know where to go...
System.out.println("Take what?");
System.out.println();
return;
}
String itemName = command.getSecondWord();
Item theItem;
// Try to take an item.
theItem = new Item(player.getCurrentRoom().removeItem(itemName));
if (theItem == null)
{
System.out.println("There is no item!");
}
else
{
player.addItem(theItem);
player.getItemsCarried();//print item info
}
Player Class:
//above code omitted//
public void setCurrentRoom(Room room)
{
currentRoom = room;
}
public Room getCurrentRoom()
{
return currentRoom;
}
//code below omitted//
public void addItem (Item thingy)
{
items.put(thingy.getName(), thingy);
}
//code below omitted//
Item Class:
public class Item
{
// instance variables - replace the example below with your own
private String name;
private String description;
private int weight;
/**
* Constructor for objects of class Item
*/
public Item(String n, String d, int w)
{
name = n;
description = d;
weight = w;
}
//code below omitted//
Room Class:
public class Room
{
private String description;
private HashMap <String, Room> exits;
private HashMap <String, Item> items;
//some code below omitted//
public Room (String description)
{
this.description = description;
exits = new HashMap<>();
items = new HashMap<>();
}
public void addItem (Item thingy)
{
items.put(thingy.getName(), thingy);
}
public String removeItem(String thingy)
{
items.remove(thingy);
return thingy;
}
//code below omitted
Your constructor in the Item class takes two String parameters and one int, but you are trying to create a new Item by passing in only one String (whatever is returned by the removeItem() method). You can either change the removeItem() method so that it returns the Item that is removed, in which case you should change
theItem = new Item(player.getCurrentRoom().removeItem(itemName));
to
theItem = player.getCurrentRoom().removeItem(itemName);
or you can create a new Item with the necessary parameters.
In one of our applications we use the lazy query container to browse a potentially very large dataset. This works great. However, it is possible to select an arbitrary number of rows when using a multi-select table.
In our case, this can lead to selecting up to 500.000 rows (Vaadin limit) and then crash the VM.
Is there a way to limit the number of selected rows?
Here is a sample that shows the problem:
public class UIImpl extends UI {
private int SIZE = 500000;
#Override
protected void init(VaadinRequest request) {
// add a large table
LazyQueryContainer lqc = new LazyQueryContainer(
new QueryFactory() {
public Query constructQuery(QueryDefinition qd) {
return new Query() {
#Override
public int size() {
return SIZE;
}
#Override
public void saveItems(List<Item> addedItems, List<Item> modifiedItems, List<Item> removedItems) { }
#Override
public List<Item> loadItems(int startIndex, int count) {
List<Item> r = new ArrayList<>(count);
for (int i = startIndex; i<startIndex+count;i++) {
PropertysetItem item = new PropertysetItem();
item.addItemProperty("name", new ObjectProperty(i));
r.add(item);
}
return r;
}
#Override
public boolean deleteAllItems() {
return false;
}
#Override
public Item constructItem() {
return null;
}
};
}
},
null,
20,
false
);
lqc.addContainerProperty("name", Integer.class, null);
Table table = new Table();
table.setContainerDataSource(lqc);
table.setMultiSelect(true);
table.setSelectable(true);
table.setImmediate(true);
table.setVisibleColumns("name");
table.setSizeFull();
table.addValueChangeListener(new Property.ValueChangeListener() {
public void valueChange(Property.ValueChangeEvent event) {
System.err.println(event.getProperty().getValue());
}
});
setContent(table);
}
}
If you want to limit the number of rows a user is able to select you can use something similar to the following code:
public class TableWithSelectionLimit extends Table {
private final int maxSelections= -1;
private String[] lastSelected;
public TableWithSelectionLimit(int maxSelections) {
this.maxSelections = maxSelections;
}
#Override
public void changeVariables(Object source, Map<String, Object> variables) {
String[] selected = (String[]) variables.get("selected");
if (selected != null && selected.length > maxSelections) {
if (lastSelected != null) {
variables.put("selected", lastSelected);
} else {
variables.remove("selected");
}
markAsDirty();
} else {
lastSelected = selected;
}
super.changeVariables(source, variables);
}
}
This is of course optimizable, but it gives you an idea on how you could do it.
Update
For handling also selections produced using "Shift"+Click one has to handle/update these selection ranges additionally inside the method mentioned above.
Those can be retrieved using variables.get("selectedRanges") that will return a String[] containing items like "8-10" whereas the
first number is: the start index of the selection range
second number is: the amount of items selected starting at this index
Using this information it should be possible to update those values as wished and put them back into the variables using variables.put("selectedRanges", updatedRanges).
Attention: do not forget to call markAsDirty() if the values are changed, as otherwise the changes won't be propagated to the client side.
i have the following problem: I read out database items in an observable list. Now I want to display some items from the selected line in a few textfields on the right side of my tableview.
I got the observable-line-index with the following code, but I want to select an other column of the line.
AnalysemethodenTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
public void changed(ObservableValue<?> observable, Object oldvalue, Object newValue) {
index.set(analysemethodendata.indexOf(newValue));
databaseIndex = (analysemethodendata.indexOf(newValue) + 1);
System.out.println("Index:\t" + databaseIndex);
}
});
I found the following code: Click
But i don't understand this. It's something like to write a new list and place a copy of the items of the observable list in this new list.
I think, if I have the index of the line with my code, I can select the other items in the line of the observable list, too (I thought like "x,y" like an array)
If i cast it to String, the output is only machine code.
Hope I can understand the solution with your help!
EDIT: I inserted the following code:
System.out.println(analysemethodendata.get(databaseIndex).toString());
But I only get machine code in my Output:
table.analysemethoden_table#63c0d5b7
EDIT 2:
Table-Controller-Code:
package table;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleStringProperty;
public class analysemethoden_table {
private final SimpleStringProperty rAmnorm;
private final SimpleStringProperty rMethverantw;
private final SimpleFloatProperty rBestimmungsgrenze;
private final SimpleFloatProperty rNachweisgrenze;
public analysemethoden_table (String sAmnorm, String sMethoverantw, Float sBestimmungsgrenze, Float sNachweisgrenze) {
this.rAmnorm = new SimpleStringProperty(sAmnorm);
this.rMethverantw = new SimpleStringProperty(sMethoverantw);
this.rBestimmungsgrenze = new SimpleFloatProperty(sBestimmungsgrenze);
this.rNachweisgrenze = new SimpleFloatProperty(sNachweisgrenze);
}
// Getter- und Setter-Methoden
/** rAmnorm **/
public String getRAmnorm() {
return rAmnorm.get();
}
public void setRAmnorm(String set) {
rAmnorm.set(set);
}
/** rMethverantw **/
public String getRMethverantw() {
return rMethverantw.get();
}
public void setRMethverantw(String set) {
rMethverantw.set(set);
}
/** rBestimmungsgrenze **/
public Float getRBestimmungsgrenze() {
return rBestimmungsgrenze.get();
}
public void setRBestimmungsgrenze(Float set) {
rBestimmungsgrenze.set(set);
}
/** rNachweisgrenze **/
public Float getRNachweisgrenze() {
return rNachweisgrenze.get();
}
public void setRNachweisgrenze(Float set) {
rNachweisgrenze.set(set);
}
}
You need to use
analysemethodendata.get(databaseIndex).getRAmnorm();
or any other getter method in place of getRAmnorm() to get the required output.
databaseIndex -> row number
I'm just starting my first real project in Java so I'm still understanding the basics so apologies for this.
I'm working out the price * quantity then giving the total amount to each individual product, this will then have to be repeated for all my products as part of the order process. So i want to find the best way so i can repeat it.
Here is the working code I have:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
double priceA = 20.00;/*fixed price*/
String strA = txtbxCaseA.getText();/*gets amount from textbox*/
int numA = Integer.parseInt(strA);/*parse to int */
double casetotalA = (priceA * numA);/*sum*/
String caseAtotal = String.valueOf(casetotalA);/*to string */
double priceB = 25.00;
String strB = txtbxCaseB.getText();
int numB= Integer.parseInt(strB);
double casetotalB = (priceB * numB);
String caseBtotal = String.valueOf(casetotalB);
double priceC = 30.00;
String strC = txtbxCaseC.getText();
int numC = Integer.parseInt(strC);
double casetotalC = (priceC * numC);
String caseCtotal = String.valueOf(casetotalC);
ArrayList caselist = new ArrayList();
caselist.add("Case A Total - £" + caseAtotal);
caselist.add("Case B Total - £" + caseBtotal);
caselist.add("Case C Total - £" + caseCtotal);
DefaultListModel myModel = new DefaultListModel ();
for(int i = 0; i < caselist.size(); i++){
jTextArea3.append((String)caselist.get(i) + ('\n'));
myModel.addElement(caselist.get(i) + ",");
/*
- save arraylist to a gobal varible for cart processing
- move to next panel (page) along
*/
}
}
My question is, is this method good practice, and also is their a better method (maybe shorter) that i can repeat for each of my 50 products as this seems a little inefficient but it works.
Any suggestions or comments would be greatly appreciated.
is their a better method (maybe shorter) that i can repeat for each
of my 50 products
Why not store your products in a collection (a List) such that you can iterate through each one and total as you go ? If you have a Product object you can then assign a price to each as a member and iterate through totalling as you go.
for (Product p : listOfProducts) {
sum = sum + p.price * quantity;
}
Note that I would pull the above out into a price calculator or similar such that you can run and test (via a unit test framework such as JUnit) separately from the GUI Swing code.
One thing that can be done is that you can use an array of TextBox and create a function that calculates the value and inserts in the Arraylist and this function is called in a loop inside the button event handler method. Also try to use ArrayList<String> instead of ArrayList. That ensures stronger type checking.
Some tips for improving your overall project, making it easier for yourself. Some of these tips have been posted already in other answers.
The basic principle is (like Ceiling Gecko commented): If you see yourself repeating code, make a generic way to code it once and reuse that code for each of the repetitions.
Use a Product class
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
This you will populate, for every product you have, at the very start of your program and store it either in an array or a List
List<Product> productList = new ArrayList<Product>();
productList.add(new Product("Milk", 10.00));
productList.add(new Product("Bread", 20.00));
The products here is hard coded for example, but you may want to read it from a file or DB. More on this later.
Use generics for your Collections
Why Use Generics?
Dynamically generate your 'TextBoxes'
If you code a JPanel with 50 JTextFields for the purpose of inputting amount, what will happen when you add another product?
You will then have to go and change your code.
If you use the List of Products mentioned earlier you can dynamically generate your JTextFields
If you populated your list from a file or DB you will never have to change your code if you update your product list and/or prices. You can then just update your file or DB and the changes will reflect in your code.
List<JTextField> textFields = new ArrayList<JTextField>();
for (Product p : productList) {
textFields.add(new JTextField());
}
Then use that list along with your product list to place your Components on your JPanel
JPanel panel = new JPanel();
for (int i = 0; i < textFields.size(); i++) {
panel.add(new JLabel(productList.get(i).getName()));
panel.add(textFields.get(i));
}
Put your calculation code in a separate reusable method
private double calculateTotal(String amount, double cost) {
int amnt = Integer.parseInt(amount);
return cost * amnt;
}
Now loop through your generated 'TextBoxes' to calculate the totals
Handle the NumberFormatException that may be thrown by Integer.parseInt
private void jButton2ActionPerformed(ActionEvent evt) {
caselist = new ArrayList<String>();
for (int i = 0; i < textFields.size(); i++) {
try {
double total = calculateTotal(textFields.get(i).getText(), productList.get(i).getPrice());
caselist.add(productList.get(i).getName() +" Total - £" + total);
} catch (NumberFormatException e) {
caselist.add(productList.get(i).getName() +" invalid amount");
}
}
}
Here is everything rolled into one
so you can copy and run it to see how it all fits together.
It was put together quickly, so it is not the best way to structure your program
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ProductCalc extends JFrame {
public static void main(String[] args) {
new ProductCalc();
}
private List<Product> productList;
private List<JTextField> textFields;
private List<String> caselist;
public ProductCalc() {
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
productList = new ArrayList<Product>();
productList.add(new Product("Milk", 10.00));
productList.add(new Product("Bread", 20.00));
productList.add(new Product("Eggs", 5.00));
textFields = new ArrayList<JTextField>();
for (Product p : productList) {
textFields.add(new JTextField(10));
}
JPanel panel = new JPanel();
for (int i = 0; i < textFields.size(); i++) {
panel.add(new JLabel(productList.get(i).getName()));
panel.add(textFields.get(i));
}
JButton button = new JButton("click");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
panel.add(button);
this.setSize(500, 500);
this.add(panel);
this.setVisible(true);
}
private void jButton2ActionPerformed(ActionEvent evt) {
caselist = new ArrayList<String>();
for (int i = 0; i < textFields.size(); i++) {
try {
double total = calculateTotal(textFields.get(i).getText(), productList.get(i).getPrice());
caselist.add(productList.get(i).getName() + " Total - £" + total);
} catch (NumberFormatException e) {
caselist.add(productList.get(i).getName() + " invalid amount");
}
}
for (String s : caselist) {
System.out.println(s);
}
}
private double calculateTotal(String amount, double cost) {
int amnt = Integer.parseInt(amount);
return cost * amnt;
}
}
class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
Some tips for you on best practices since you mentioned it:
double priceA = 20.00;
First of all double isn't exactly precise, you should watch out if you plan to use floating point variables to make any calculations that have to be 100% accurate (such as money calculations), use java.math.BigDecimal class instead.
Secondly you should store all constant (fixed) values at the top of your class where you define your variables, so you don't have any "magic numbers" roaming about.
Example: private static final double priceA = 20.00
This way you don't have to re-define the variables each time you access the method.
Thirdly you should always be suspicious of user input and handle it.
What would happen here Integer.parseInt(strA) if I for example would leave one of the text boxes empty?
Or even worse what if I would write some text there instead of numbers?
You should always be aware that users will not always use your program as intended and will even try to break it.
Finally you could define a calculating method outside of this method that would simplify your current method.
From your example it could look something like this:
private String calculcateTotal(double price, String amount) {
int actualAmount = Integer.parseInt(amount);
double totalAmount = (price * actualAmount);
return String.valueOf(totalAmount);
}
Which would reduce your original method down to:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
double priceA = 20.00;
double priceB = 25.00;
double priceC = 30.00;
ArrayList caselist = new ArrayList();
caselist.add("Case A Total - £" + calculateTotal(priceA, txtbxCaseA.getText()));
caselist.add("Case B Total - £" + calculateTotal(priceB, txtbxCaseB.getText()));
caselist.add("Case C Total - £" + calculateTotal(priceC, txtbxCaseC.getText()));
DefaultListModel myModel = new DefaultListModel ();
for(int i = 0; i < caselist.size(); i++){
jTextArea3.append((String)caselist.get(i) + ('\n'));
myModel.addElement(caselist.get(i) + ",");
/*
- save arraylist to a gobal varible for cart processing
- move to next panel (page) along
*/
}
}
See how it looks neater now?
And you could even omit the
double priceA = 20.00;
double priceB = 25.00;
double priceC = 30.00;
if you had defined them at the top of your class like I mentioned before.
My advice would be to separate the business logic from the presentation logic and you'll end up with something like this:
/**
* Represents the concept of getting a `Integer` quantity from some source.
*/
public inteface Quantity
{
public Integer getValue();
}
/**
* Represents the combination of a price and quantity to produce a total.
*/
public class Total
{
private double price;
private Quantity quantity;
public Total(double price, Quantity quantity)
{
this.price = price;
this.quantity = quantity;
}
public Double getValue()
{
Integer quantity = quantity.getValue();
return quantity != null ? quantity * price : null;
}
}
Then you can use this inteface and class in your Swing code like this (which is only intended to show the interaction with Swing, not how to layout the controls):
public class MyFrame extends JFrame
{
private static final List<Double> PRICES = Arrays.asList(20.0, 25.0, 30.0);
public MyFrame()
{
List<Total> totals = new ArrayList<Total>();
JList totalsList = new JList(new TotalListModel(totals));
addComponent(totalsList);
for (Double price : PRICES)
{
JTextField quantityTextField = new JTextField();
quantityTextField.addActionListener(new RepaintComponentActionListener(totalsList));
addComponent(quantityTextField);
totals.add(new Total(price, new TextFieldQuantity(quantityTextField)));
}
}
private class TotalListModel extends AbstractListModel
{
private List<Total> totals;
public TotalListModel(List<Total> totals)
{
this.totals = totals;
}
public Object getElementAt(int index)
{
Double value = totals.get(index).getValue();
return value != null ? value.toString() : "NO VALUE";
}
public int getSize()
{
return totals.size();
}
}
private class TextFieldQuantity implements Quantity
{
private JTextField textField;
public TextFieldQuantitySource(JTextField textField)
{
this.textField = textField;
}
public Integer getQuantity()
{
try
{
return Integer.parseInt(textField.getText());
}
catch (NumberFormatException e)
{
return null;
}
}
}
private class RepaintComponentActionListener implements ActionListener
{
private Component component;
public RefreshControlActionListener(Component component)
{
this.component = component;
}
public void actionPerformed(ActionEvent actionEvent)
{
component.repaint();
}
}
}
In case it's not immediately clear how this code is working, it uses:
a custom ListModel to wrap the totals meaning that the JList simply needs repainting and the current totals will be displayed.
a loop over the PRICES to dynamically create the JTextField controls (I'll leave it for you to work out the layout).
a custom ActionListener that repaints the JList when any of the JTextFields change.
a custom Quantity that reads the value from the JTextField.
Please I need help.
I am trying to finish 2 different java methods.
1- the first method is called getOrder() which is supposed to get an order of different items that have already been added to an ArrayList named order but I just did not include the code for it as I think it is not necessary. I need to return all the contents of order ArrayList as long as it does not contain null.
The getItem method (which is working perfectly) Loads the contents of the items in the order using the class A4Q1Util.
The problem that I have is with this line of code:
return toBeReturned.add(A4Q1Util.getItem());
it gives the following error:
Type mismatch: cannot convert from boolean to java.util.ArrayList
2- In the second method (printOrderCos), I am supossed to print out the totalCost of items from the ArrayList order. I defined the variable totalCost and count. Count is defined so that it works as an index that goes through each element(item) of the order ArrayList and then adds up the cost of each item to totalCost.
The problem that I encounter with the second method is with this line of code:
totalCost+=order.get(count);
it gives an error:
error: The operator += is undefined for the argument type(s) double, Item
public static ArrayList<Item> getOrder()
{
ArrayList<Item> toBeReturned;
toBeReturned = new ArrayList<Item>();
while (A4Q1Util.getItem()!=null)
{
return toBeReturned.add(A4Q1Util.getItem());
}
}
public static void printOrderCost(ArrayList<Item> order)//prints the total cost of the order
{
double totalCost;
int count;
totalCost=0;
for (count=0;count<order.size();count++)
{
totalCost+=order.get(count);//intValue();
}
System.out.println("The total cost of your order is:");
}
class Item
{
protected String description;
protected int quantity;
public Item (String description, int quantity)
{
this.description = description;
this.quantity = quantity;
}
}
class Coffee extends Item
{
protected double unitCost;
public Coffee (String description, int quantity)
{
super(description, quantity);//cost?,and price extraction
unitCost=4;
}
}
class Muffin extends Item
{
protected double unitCost1, unitCost2, unitCost3;
public Muffin (String description, int quantity)
{
super(description,quantity);
unitCost1=1;
unitCost2=0.75;
unitCost3=0.50;
}
}
class TimBits extends Item
{
protected double unitCost;
public TimBits (String description, int quantity)
{
super(description, quantity);
unitCost=0.25;
}
}
class A4Q1Util
{
private static ArrayList<Item> order;
private static int count = 0;
public static Item getItem()
{
Item item;
if (order==null)
{
order = new ArrayList<Item>();
order.add(new Muffin("Bran", 3));
order.add(new Coffee("Latte", 1));
order.add(new TimBits("Assorted", 24));
order.add(new Muffin("Chocolate", 1));
order.add(new Coffee("Decaf", 2));
order.add(new TimBits("Chocolate", 12));
order.add(new Muffin("PeanutButter", 2));
order.add(new Muffin("Blueberry", 5));
}
item = null;
if (count<order.size())
{
item = order.get(count);
count++;
}
{
return item;
}
}
}
The error message is telling you exactly what is wrong:
You're trying to add an Item to a number, which obviously is not going to work. Instead perhaps you want to call a method on the item returned from the list, perhaps a getCost() method or something similar. We don't have the Item class code to look at, and so cannot tell you which method to call, but hopefully your Item class has an appropriate method which returns a number.
Your method get() seems that is returning an Item instance, so you may want to create a method (if it's not already created) to return a number that you can use to add to totalCost, maybe something like:
totalCost += order.get(count).getCost(...); // getCost(...) is the method you should create
For your 2nd problem , problem is "order.get(count)" returns Item object . and You cannot added "Item object" with double.
For problem 1 :
public static ArrayList<Item> getOrder()
{
ArrayList<Item> toBeReturned;
toBeReturned = new ArrayList<Item>();
Item item;
item=A4Q1Util.getItem();
while (item!=null)
{
toBeReturned.add(item);// it will all the items from A4Q1Util class to list
item=A4Q1Util.getItem();
}
return toBeReturned;
}