JComboBox populetd with my object - java

I have a class called persone (peoples), it's just an arraylist of object persona (person).
I want to use this the object persone for populate a JComboBox.
I've read many post, and I've understood that I've to use DefaultComboBoxModel(E[] items), but, of course, I've missed something. I made some mistake. Can I have an example ? And how to set or get the selected item?
This is my class:
public class Persone {
private ArrayList<Persona> el = new ArrayList<Persona>();
public Persone() {
}
public ArrayList<Persona> getEl() {
return el;
}
public void setEl(ArrayList<Persona> el) {
this.el = el;
}
public boolean delPersonaFromPersone(Persona persona) {
return this.el.remove(persona);
}
public boolean addPersonaToPersone(Persona persona) {
return this.el.add(persona);
}
public boolean substPersonaInPersone(Persona persona, Persona withPersona ) {
if ( !this.el.remove(persona))
return false;
return this.el.add(persona);
}
#Override
public String toString() {
return "Persone [el=" + el + "]";
}
}

You can't add an Object containing an ArrayList to a combo box.
Instead you need to add individual Persona object to the combo box.
Then you would need to provide a custom renderer to display the Persona object.
Check out Combo Box With Custom Renderer for more information and examples on how to do this.

I've found my mistake (some bad assignment).
For use in JComboBox, I've made a new array from ArrayList.
Here my code:
JComboBox<Persona> cbResponsabile = new JComboBox<Persona>();
Persona[] array = persone.getEl().toArray(new Persona[persone.getEl().size()]);
cbResponsabile.setModel(new DefaultComboBoxModel(array));
contentPanel.add(cbResponsabile);
// .....
// assignment
// persona is an element of array
cbResponsabile.setSelectedItem(persona);

Related

JavaFX TableView ComboBox String Converter

I am trying to add a ComboBox into the TableView but for some reason I cannot make the conversion. Behind the scenes, I want to make the conversation if the value is
0 then it should display 'free' if the value is 1 then it will say 'taken' in the ComboBox, and once the user changes the value in the ComboBox
it will save its integer value.
I am not sure how to add the converter and it gives the following error at event.getNewValue():
cant convert int to string.
Any help where I am doing wrong?
private final IntegerProperty mode;
public int getMode() {
return mode.get();
}
public void setMode(int mode) {
this.mode.set(mode);
}
public IntegerProperty modeProperty() {
return mode;
}
Set<String> modeList = new HashSet<>();
modeList.add("Free");
modeList.add("Taken");
var converter=modeConverter();
TableColumn<Review, String> modeCombo = new TableColumn("Mode");
modeCombo.setCellValueFactory(new PropertyValueFactory("mode"));
modeCombo.setCellFactory(ComboBoxTableCell.forTableColumn(converter); //How to apply the converter.
modeCombo.setCellFactory(ComboBoxTableCell.forTableColumn(FXCollections.observableList(modeList))));
modeCombo.setOnEditCommit(event -> {
mode.setOperationMode(event.getNewValue()); //Method cannot be applied java.lang.String. But I already make the conversatin via modeConverter
});
...
private StringConverter modeConverter() {
return new StringConverter<Integer>() {
#Override
public String toString(Integer object) {
if (object == 0) {
return "FREE";
} else {
return "Taken";
}
}
#Override
public Integer fromString(String string) {
if (string.equalsIgnoreCase("free")) {
return 0;
} else {
return 1;
}
}
};
}
You need to use the overloaded method:
forTableColumn​(StringConverter converter,
ObservableList items)
Please note that ComboBox backing list should contain 0, 1 instead of Free, Taken. The converter is responsible for displaying 0 as Free and 1 as Taken.
Also, the TableColumn should be of type <Review, Integer> instead of <Review, String>.
In your code, you can do something as follows:
ObservableList<Integer> modeList = FXCollections.observableList(0, 1);
TableColumn<Review, Integer> modeCombo = new TableColumn("Mode");
modeCombo.setCellValueFactory(new PropertyValueFactory("mode"));
modeCombo.setCellFactory(ComboBoxTableCell.forTableColumn(converter, modeList)));
Once your basic type is fixed, the following should work:
modeCombo.setOnEditCommit(event -> {
mode.setOperationMode(event.getNewValue());
});

Unable to set Object instance as selected item of JComboBox with Renderer

I have a DAOImplementation class with the method definition below.
#Override
public Registration getRegistrationInfoById(int aRegistrationId) {
String SQL = "{CALL getRegistrationInfoById(?)}";
Registration aRegistration = new Registration();
try (Connection con = DBUtil.getConnection(DBType.MYSQL);
CallableStatement cs = con.prepareCall(SQL);) {
cs.setInt(1, aRegistrationId);
try (ResultSet rs = cs.executeQuery();) {
while (rs.next()) {
int gradeLevel = Integer.parseInt(rs.getString(RegistrationTable.GRADELEVEL));
aRegistration.setGradeLevel(gradeLevel);
}
}
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e.getErrorCode() + "\n" + e.getMessage());
}
return aRegistration;
}//end of method
This returns an integer value of Grade Level (1,2,3,4,5,6,7...so on...) which I've verified because I tried printing the output returned by aRegistration.getGradeLevel();
Now my problem is with my JComboBox. I have set a ListCellRenderer for my JComboBox which holds all the GradeLevel values
public class JComboBoxRenderer_GradeLevel extends JLabel implements ListCellRenderer<Object> {
public JComboBoxRenderer_GradeLevel() {
this.setOpaque(true);
}
#Override
public Component getListCellRendererComponent(JList<? extends Object> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof GradeLevel) {
this.setText("" + ((GradeLevel) value).getGradelevel());
} else {
this.setText("--");
}
if (isSelected) {
this.setBackground(Color.YELLOW);
this.setForeground(list.getSelectionForeground());
} else {
this.setBackground(list.getBackground());
this.setForeground(list.getForeground());
}
return this;
}
}
And looks like this JComboBox as expected. (GradeLevel model is renderered to simply show an int value of gradelevel), ((GradeLevel) value).getGradelevel());returns an integer value.
I understand that even when JComboBox has its renderer that displays an integer value of GradeLevel by using ((GradeLevel)value).getGradeLevel(), the actual value on the JComboBox is still treated as instance of GradeLevel or object. But not a String or int.
So my problem is when I try to set the selected value to an int value, it won't change the selected value of the JComboBox. Nothing happens when I use setSelectedItem();
This is what I tried to do for the GUI.
//Grade Level
GradeLevelDaoImpl gldi = new GradeLevelDaoImpl();
List<GradeLevel> gradeLevels = gldi.getAllGradeLevelsInfo();
DefaultComboBoxModel gradeLevelModel = new DefaultComboBoxModel(gradeLevels.toArray());
jcmbGradeLevel.setModel(gradeLevelModel);
jcmbGradeLevel.setRenderer(new JComboBoxRenderer_GradeLevel());
jcmbGradeLevel.setSelectedIndex(-1);
GradeLevel gradeLevel = new GradeLevel();
gradeLevel.setGradelevel(registration.getGradeLevel());
jcmbGradeLevel.setSelectedItem(gradeLevel); //PROBLEM HERE, it doesn't change
JOptionPane displays this.
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel);
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel.getGradeLevel());
It doesn't seem to be able to compare the object I'm trying to set it to(gradeLevel) with the objects JComboBox has(gradeLevels). Notice the singular and plural.
How do I manipulate the types so that setSelectedItem() will match with what the JComboBox have?
Thanks.
If you want to do this by using different instances of the object, but with the same properties, then you need to override the class's equals and hashcode methods, so that the combination of properties are unique. This is very important, this is a relationship expectation that any object which is equal to another will have the same hashcode
This is a really quick example and I used by IDE's auto generation process (because I'm lazy), but, if your Registration class has other properties which should be considered when comparing to instances of the class, you will need to modify it to support them (again, any good IDE should be able to do this)
public class Registration {
private int gradeLevel;
public Registration(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
public int getGradeLevel() {
return gradeLevel;
}
public void setGradeLevel(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
#Override
public int hashCode() {
int hash = 7;
hash = 73 * hash + this.gradeLevel;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Registration other = (Registration) obj;
if (this.gradeLevel != other.gradeLevel) {
return false;
}
return true;
}
}
Then using something like...
Registration a = new Registration(1);
Registration b = new Registration(1);
Registration c = new Registration(2);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
will print...
true
false
false
which shows us that the code is working.
Once you get this setup, you should then be able to change the selected item by creating an instance of Registration, seeding it with the required properties and passing it to the JComboBox.
This is very important and very common concept used a lot within Java, well worth taking the time to learn and understand

Shopping Cart page displays only one item

I'm developing a Java EE e-commerce application that will sell car parts. I can add items to the shopping cart implemented using CopyOnWriteArrayList. I then use a managed bean (session scoped) to display its contents.
I then use a to display the data in ViewCode.xhtml. The probelsm is: It will only show the first item in the arraylist. Please can someone help?
The Managed Bean:
#ManagedBean(name="ViewCartManagedBean")
#SessionScoped
public class ViewCartManagedBean {
List<Orderitem> cartItemsList = new ArrayList<>();
#EJB
com.shop.cart.CartFacade cartFacade;
public ViewCartManagedBean(){}
#PostConstruct
public void initialize(){
setCartItemsList();
}
public List<Orderitem> getCartItemsList() {
return cartItemsList;
}
public void setCartItemsList() {
cartItemsList = cartFacade.viewItemsIntheCart();
}
}
The cart facade
#Stateless(name="ShoppingCartLocal")
public class CartFacade {
#PersistenceContext(unitName ="Shop")
EntityManager cartEntityManager;
#EJB
ShoppingCart cartBean;
public CartFacade(){}
public void assignCustomerToCart(CustomerEntity customer){
cartBean.setCustomer(customer);
}
public boolean addItemToCart(ProductEntity product, int quantityPurchased){
boolean result = false;
result=cartBean.addCartItem(product, quantityPurchased);
return result;
}
public List<Orderitem> viewItemsIntheCart(){
return cartBean.getCartItems();
}
the ShoppingCartBean
#Stateful(name="ShoppingCart")
#StatefulTimeout(value = 200)
public class ShoppingCartBean implements ShoppingCart,ShoppingCartLocal {
#PersistenceContext(unitName ="Shop", type=PersistenceContextType.EXTENDED)
private EntityManager cartEntityManager;
private CustomerManager customerManagerBean;
private CopyOnWriteArrayList<Orderitem> cartItems= new CopyOnWriteArrayList<Orderitem>();
private CustomerEntity customer=null;
public CustomerEntity getCustomer() {
return customer;
}
public void setCustomer(CustomerEntity customer) {
this.customer = customer;
System.out.println("hey Im linked to the cart " + customer.getName());
}
private com.shop.entity.Orderitem basketItem=new Orderitem();
public ShoppingCartBean(){}
#PostConstruct
public void initialise(){
//cartItems = new CopyOnWriteArrayList<Orderitem>();
}
public void removeCartItem(int itemCode){
System.out.println("hello");
}
#Override
public boolean addCartItem(ProductEntity product, int quantityPurchased){
double subTotal;
boolean result=false;
if (cartItems.size()==0){
basketItem.setItemcode(product.getItemcode());
basketItem.setItemdescription(product.getItemdescription());
basketItem.setUnitprice(product.getUnitprice());
basketItem.setQuantitypurchased(quantityPurchased);
subTotal=quantityPurchased*basketItem.getUnitprice();
basketItem.setSubtotal(subTotal);
cartItems.add(basketItem);
result=true;
}else{
Iterator<Orderitem> basketIterator = cartItems.iterator();
while (basketIterator.hasNext()){
Orderitem cartItem = basketIterator.next();
System.out.println("cart item item code: " + cartItem.getItemcode());
System.out.println("product item code: " + product.getItemcode());
if(cartItems.size()!=0 && !(cartItem.getItemcode().equals((product.getItemcode())))){
basketItem.setItemcode(product.getItemcode());
basketItem.setItemdescription(product.getItemdescription());
basketItem.setUnitprice(product.getUnitprice());
basketItem.setQuantitypurchased(quantityPurchased);
subTotal=quantityPurchased*basketItem.getUnitprice();
basketItem.setSubtotal(subTotal);
cartItems.add(basketItem);
result=true;
}
}
}
System.out.println("cart size " + cartItems.size());
return result;
}
Finally the view (ViewCart.xhtml)
<h:form name="ViewCartManagedBean">
<h:dataTable var="cartList" value="#{ViewCartManagedBean.cartItemsList}"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row" >
<h:column>
<f:facet name="header"><h:outputText value="Item Code" style="font-family: Verdana, Helvetica, sans-serif;font-size: 16px;"/></f:facet>
<h:outputText value="#{cartList.itemcode}" style="font-family: Verdana, Helvetica, sans-serif;font-size: 14px;"/>
</h:column>
Datatable looks like a valid way to display your list data, pretty much a copy of the tutorial
However the way you add your data is wrong. (which is why I suggested using a debugger in comments.)
at the time of printing you should notice only 1 element in your list (I expect) or many times the same item.
Your instance variable:
private com.shop.entity.Orderitem basketItem=new Orderitem();
is reused over and over. this should be a method variable not an instance variable. You add the same instance to the list over and over, while updating it's properties. This will update the properties of a single instance and not create new ones. This means that if you do:
List list = new SomeList();
SomeObject object = new SomeObject();
list.add(object);
list.add(object);
object.setName("name");
the list will contain 2 references to the same object, both with name "name"
So again: this is what you are doing when you use the instance variable
basketItem rather than make it a variable that only lives in the method addCartItem
when adding items to your cart you should use something like:
public boolean addCartItem(ProductEntity product, int quantityPurchased){
for (Orderitem current : cartItems) {
if (current.getItemCode().equals(product.getItemCode())) {
// adding duplicate entry.
return false; // or handle adding differently
}
}
// now that we're sure that the item doesn't already exist in the basket
Orderitem basketItem=new Orderitem();
basketItem.setItemcode(product.getItemcode());
basketItem.setItemdescription(product.getItemdescription());
basketItem.setUnitprice(product.getUnitprice());
basketItem.setQuantitypurchased(quantityPurchased);
basketItem.setSubtotal(quantityPurchased*basketItem.getUnitprice());
cartItems.add(basketItem);
return true;
}
Next time, run your debugger and check (after adding several items to your list) what the actual contents of the list items are. That way you can probably spot that something is going wrong.

JList toArray method - display different information about a single class in seperate JList

I have two JLists and an ArrayList of Items in my Main Class and my Player class
private ArrayList<Item> allItems= new ArrayList<Item>();
listItemsShop= new JList(allItems.toArray());
listItemsInv= new JList(currentPlayer.getAllItems().toArray());
As most are probably aware, the toArray method returns the contents of my collection 'allItems" as an array. This enables it to be used in the JList component.
The JList component then calls on my Items class toString method and returns whatevers in that. e.g.
#Override
public String toString() {
return name + "," + "$"+price;
}
This is fine for my first JList 'listItemsShop' but for my second JList I dont want to display the price. The second JList is an inventory so the Item has been purchased.. I would like to only display the Items name and maybe some other details such as damage amount or condition..
Does anyone know of a way to do to this? I have read of someone creating a duplicate class and overwriting the second classes toString method that way, this seems like a large redundancy though. If anyone knows of another way around this I'd love to hear from you.
Cheers
Don't use a JList. Instead use a JTable. Then you can control what columns you want to display. See How to Use Tables for more information.
EDIT: Sorry, I misread you question. As trashgod suggest, it's better to use cell renderers:
public class ItemCellRenderer extends DefaultListCellRenderer {
public static enum Type {SHOP, INVENTORY;}
private Type type;
public ItemCellRenderer(Type t) {
super();
this.type = t;
}
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
Item item = (Item) value;
if (type == Type.SHOP) {
label.setText(item.getPrice());
} else if (type == Type.INVENTORY) {
label.setText(item.getData());
} else {
label.setText(null);
}
return label;
}
}
You can use it in this way:
listItemsShop.setCellRenderer(new ItemCellRenderer(ItemCellRenderer.Type.SHOP));
listItemsInv.setCellRenderer(new ItemCellRenderer(ItemCellRenderer.Type.INVENTORY));
OLDER
I think it is better to delegate the string method to the inventory/shop instead of coding it in the item class. Like
class Inventory {
public String toString(Item item) {
return item.getName() + " " + item.getStats();
}
}
and for shop
class Shop {
public String toString(Item item) {
return item.getName() + " $" + item.getPrice();
}
}

Java JTable -- Custom Row Sorter

I have a JTable that loads data from a database and then generates a summary row at the bottom of the table. I want the user to be able to sort the table, but I'd like the summary row to always remain at the bottom of the table.
I've been trying to create a custom TableRowSorter, but I'm having some trouble figuring it out and getting it to do what I want.
Anyone know how to do this?
Thanks
You need a class which holds whether the value is a summary or not.
Something like this
public class SummarizedValue {
public Integer value;
public boolean summarized;
public String toString() {
return null == value? "" : value.toString();
}
}
public class SummaryComparator implements Comparator<SummarizedValue> {
public int compare(SummarizedValue v1, SummarizedValue v2) {
if (v1.summarized) return 1;
if (v2.summarized) return -1;
return v1.value.compareTo(v2.value);
}
}
public class SummaryBackComparator implements Comparator<SummarizedValue> {
public int compare(SummarizedValue v1, SummarizedValue v2) {
if (v1.summarized) return 1;
if (v2.summarized) return -1;
return v2.value.compareTo(v1.value);
}
}
You need to display the objects of class SummarizedValue in your column and your row sorter should return SummaryComparator. Also your need to override toggle behaviour in RowSorter to use SummaryBackComparator.

Categories

Resources