Convert ArrayList to Observable List for JavaFX program? - arraylist

I am a semi-beginner Java programmer, learning Java FX from a variety of sources. In my program, I would like to create a ComboBox, and populate the choices with the toString() output of a series of objects from an ArrayList. Here, pizza toppings are defined as an object. They are created and stored in a PizzaMgr object, basically a glorified wrapper for an ArrayList:
public class Topping{
private String name;
public Topping(String a){
this.name=a;
}
public String toString(){
return this.name;
}
}
//=================================================
import java.util.ArrayList;
public class PizzaMgr{
private ArrayList<Topping> OrderedToppings;
public PizzaMgr(){
OrderedToppings = new ArrayList<Topping>();
OrderedToppings.add(new Topping("Pepperoni"));
OrderedToppings.add(new Topping("Mushrooms"));
OrderedToppings.add(new Topping("Onions"));
}
public ArrayList<Topping> getList(){
return OrderedToppings;
}
}
So far, so good. But the hitch I hit is when I want a ComboBox to list all of those items in the PizzaMgr's ArrayList. Ideally, I'd like to use this ComboBox constructor:
ComboBox<T>(ObservableList<T> items)
The problem? How to extract all the ArrayList items into an Observable List? I've been reading up on Arraylists, Observable Lists, interfaces in general, but I can't figure out how to get this to work. I've read that an ArrayList is a Collection, and Observable List can be an interface to a Collection, so I thought I was home free. However, when I try to implement the ComboBox constructor:
import javafx.scene.control.*;
public class Menu{
public static void main(String[] args){
PizzaMgr m = new PizzaMgr();
ComboBox<Topping> topMenu = new ComboBox<Topping>(m.getList());
}
}
I get the compiler error:
Menu.java:18: error: incompatible types: ArrayList<Topping> cannot be converted to ObservableList<Topping>
ComboBox<Topping> topMenu = new ComboBox<Topping>(m.getList());
^
So obviously my ArrayList isn't seen as an Observable List.
What stumps me is: How can I present my ArrayList to the ComboBox constructor, making it seem like an Observable List? Is it a syntax slight-of-hand? Or do I have to convert the ArrayList into another data structure in advance?
Many thanks,
-RAO

ObservableList is a sub interface (specialized version of) List. (ObservableList adds functionality for observing changes to the list.) ArrayList is a particular implementation of List, but is not an implementation of ObservableList. Hence you can pass an ArrayList anywhere a List is expected, but you cannot pass an ArrayList if an ObservableList is expected.
As something of an aside, note it's not really recommended to expose the implementation type, but you should really just expose the interface type:
import java.util.List;
import java.util.ArrayList;
public class PizzaMgr{
private List<Topping> orderedToppings;
public PizzaMgr(){
orderedToppings = new ArrayList<Topping>();
orderedToppings.add(new Topping("Pepperoni"));
orderedToppings.add(new Topping("Mushrooms"));
orderedToppings.add(new Topping("Onions"));
}
public List<Topping> getList(){
return orderedToppings;
}
}
To create an ObservableList from a regular List, you can use
ComboBox<Topping> topMenu
= new ComboBox<Topping>(FXCollections.observableList(m.getList()));
which creates a new ObservableList that "wraps" the array list you provide. I.e. calling get(index) or add(item) on the observable list simply delegates to the list you provide.
You could also do
ComboBox<Topping> topMenu
= new ComboBox<Topping>(FXCollections.observableArrayList(m.getList()));
which would create a new observable list and copy all the elements from the list you provide into it. So subsequently manipulating one list would not change the other.

To create an observableList you need to, first of all, have a predefined list eg an arrayList. Pass the list to an instance of observableList as below...
//Assuming you had this for a list
List<String> list = new ArrayList<String>();
//Pass it over in this manner
ObservableList<String> observableList = FXCollections.observableList(list);
//Then add a listener
observableList.addListener (new ListChangeListener() {
//override the method here
}
Hope it will help...

ArrayList<Site> sites = new ArrayList < Site > ();
sites.add(new Site("Google", "http://www.google.com"));
ObservableList<Site> siteList = FXCollections.observableArrayList(sites);
final ComboBox comboBox = new ComboBox(siteList);
Button btn = new Button();
btn.setText("Read comboBox");
btn.setOnAction(new EventHandler < ActionEvent > () {
#Override
public void handle(ActionEvent event) {
label.setText("selected: " + comboBox.getValue());
Site site = (Site) comboBox.getSelectionModel().getSelectedItem();
System.out.println(site.name);
}
});

Related

How do you pass an ArrayList into the constructor?

import java.util.ArrayList;
public class Finance {
ArrayList<String> title = new ArrayList<String>();
ArrayList<Double> moneySpent = new ArrayList<Double>();
Scanner input = new Scanner(System.in);
public Finance(ArrayList<String> title, ArrayList<Double> moneySpent){
this.title = title;
this.moneySpent = moneySpent;
System.out.println(title);
System.out.println(moneySpent);
}
public static void main(String[] args){
Finance entertainment = new Finance(title.add("Movies"), moneySpent.add(1));
}
When I run the code this, I found 2 errors:
File: D:\Java Programs\Finance.java [line: 19] Error: Cannot make a
static reference to the non-static field title
File: D:\Java
Programs\Finance.java [line: 19] Error: Cannot make a static
reference to the non-static field moneySpent
Although your focus is in creating an instance Finance there are few concepts I'd like to invite you to explore.
To start and to answer your question, the Finance's contructor signature defines the contract for a Finance oject to become an instance.
It expects two arguments, each of which are of ArrayList type.
To create an instance of Finance you have to create two arrays, one made of Strings and the other made of Doubles, on this thread you have many ideas on how to initialise arrays.
An example could be,
new Finance(new ArrayList<>(List.of("Movies")), new ArrayList<>(List.of(1.0)));
Next, I'd like to drag your awareness on this expression in your code:
title.add("Movies")
title is what you want initialised inside your constructor and altough is not a bad idea to have it initialised as an empty ArrayList as you did, it's pointless to add an element to it and then pass it to your constructor for it to change the same instance object.
Next, I'd like to drag your awareness on the types you are using:
In my personal opinion I would use java's List interface when declaring variables, use a plural to name any collection of objects, and in your case, use ArrayList as the List interface implementing class. For example,
List<String> titles;
// and
List<Double> expenses;
Same on the constructor:
public Finance(List<String> titles, List<Double> expenses) {
//...init variables here
}
Note that I renamed moneySpent to expenses. I did this because a money spent on multiple moments it's more likely to be expenses and moneySpent would be the amount spent on a single moment.
Applying Single Resposibility I would refactor the creation of a Finance instance onto a separete (static, why static?) method.
public class Finance {
List<String> titles;
List<Double> expenses;
Scanner input = new Scanner(System.in);
public Finance(List<String> titles, List<Double> expenses) {
this.titles = titles;
this.expenses = expenses;
System.out.println(this.titles);
System.out.println(this.expenses);
}
public static void main(String[] args) {
Finance entertainment = createFinance();
}
private static Finance createFinance() {
return new Finance(
new ArrayList<>(List.of("Movies")),
new ArrayList<>(List.of(1.0)));
}
}
Lastly, Consider driving your implementation guided by tests. I can recommend:
TDD by example, GOOS and Jason Gorman's TDD book

Populating a single Listview with multiple custom array of objects in Xamarin

I am new to xamarin/Mobile development. I got a task to create a single listview which should populate the objects of two different classes using xamarin.forms.
`Class A
{
string PendingRequestID;
string PendingRequestStatus;
string PendingRequest;
}
Class B
{
String CompletedRequestId;
String ApprovedByUsername;
DateTime CompletedTime
}
`
above are the two different entities and I need to populate the list of objects of both in single list view. Each object is having its own separate UI layout.
How can i specify multiple ItemSource in a ListView in xamarin.forms?
Please help me.
Just create a property of type ObservableCollection<object> for ItemsSource on ListView and use a data template selector in order to provide item-type based template(s) to ListView.
An example can be found here
EDIT - 1 : Sample code
class MyDataTemplateSelector : Xamarin.Forms.DataTemplateSelector
{
public MyDataTemplateSelector()
{
// Retain instances!
this._typeADataTemplate = new DataTemplate(typeof(TypeAViewCell));
this._typeBDataTemplate = new DataTemplate(typeof(TypeBViewCell));
}
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item == null)
return null;
return (item is A) ? this._typeADataTemplate : this._typeBDataTemplate;
}
private readonly DataTemplate _typeADataTemplate;
private readonly DataTemplate _typeBDataTemplate;
}
You can't assign multiple types for ItemSource. Therefore, one way is to use a third class as a base class and then derive your A and B from it. Then use this C type as ItemSource.
Class C{
...
}
Class A : C
{
string PendingRequestID;
string PendingRequestStatus;
string PendingRequest;
}
Class B : C
{
String CompletedRequestId;
String ApprovedByUsername;
DateTime CompletedTime
}
Note that you will then need to check for the right subtype during runtime whenever you click on an Item in the list.
Hope it helps!

What's different between Arraylist and Arrayadapter

look at this code and tell if i use
Arraylist whats happen ..i want to know whats a diffrent between ArrayList and Arrayadaptor?
public class structNote {
public String title;
public String description;
public boolean done;
}
public class AdapteNote extends ArrayAdapter<structNote> {
public AdapteNote(ArrayList<structNote> array) {
super(G.context, R.layout.adaptornote, array);
}
ArrayList is list which holds list of int, String...
ArrayAdapter is adapter, which is used for Listing items in screen, like for ListView. It has more functions for that, if item removed in background, ArrayAdapter will remove it as well if you call adapter.notifyDatasetChanged(), it updates screen. You can not use ArrayList as adapter for Listing items on screen, but you can use it for holding list of items in memory.
Picture below ArrayAdapter holds items inside ListView. You can not use ArrayList for such listing.

Add a series of instances of a Class to ArrayList variable

This code seems to match pretty close to an example I found on online, but its not right, and I can't find an example that matches what I'm trying to do. Maybe I just don't have the parameters and fields setup correctly; or maybe my approach is wrong.
package vibrationSimulator;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import sineWaveAnimation.SineDisplay;
import audioOutput.JFrame_sliderSine;
public class VibrationSimulator {
private static List<MachineParameters> machineParameterArray;
private static int ia;
private static MachineParameters machineParameter_1;
public static void main(String[] args) {
Start();
}
public static void Start() {
ArrayList<MachineParameters> machineParameterArray = new ArrayList<MachineParameters>();
MachineParameters machineParameter_1 = new MachineParameters();
machineParameter_1.frame.setVisible(true);
}
public static void Process() {
// machineParameterArray.add(machineParameter_1);
if (MachineParameters.isGoDone()) {
// machineParameterArray[ia] = machineParameter_1;
MachineParameters machineParameter_1 = new MachineParameters();
machineParameter_1.frame.setVisible(true);
} else {
StartAnimations();
}
}
I have MachineParameters Class whith a simple GUI for inputting the values. Start creates the first instance of MachineParameters and Process is supposed to add that instance to the ArrayList when it is called from the MachineParameter Class. Process creates another instance if GoDone is true or starts and animation if false. The ArrayList will be used to set the parameters for the animation. The true/false is set by the Submit or Done buttons on the GUI.
When I add the Remmed out line:
// machineParameterArray.add(machineParameter_1);
machineParameters_1 doesn't refer to the instance.
Also, all instances have the same name; I'm not sure how to increment a variable name - doesn't seem correct.
Laugh at me if you want, but I will get this right eventually; and then I'll know how to do it.
Remove ArrayList from the constructor. Apparently it creates a local variable instead of an instance.
So:
machineParameterArray = new ArrayList();

Serialize class based on one interface it implements with Jackson or Gson

I have the following:
An interface I1 extends Ia, Ib, Ic
An interface I2.
A class C implements I1, I2. And this class has its own setters and getters as well.
C cInstance = new C():
//Jackson
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(new File("somefile.json"), cInstance);
//Gson
Gson gson = new Gson();
String json = gson.toJson(cInstance);
The output will be cInstance serialized according to the properties of C and what it inherited.
However, I like the properties are being serialized to be according to the setters/getters in I1 (only the cInstance properties represented in the I1 interface).
How can I do this with Jackson knowing that I have too many classes with the same problem and I can't modify the class definition or add annotations.
And the same issue applies to Deserialization (Deserializing according to an interface)
Thanks
First of all, you can always attach "mix-in annotations" even without adding annotations directly (see wiki page). With this, annotation to use would be:
#JsonSerialize(as=MyInterface.class)
but if you do not want to use mix-ins, you can force specific type to use with
objectMapper.typedWriter(MyInterface.class).writeValue(....)
Jackson's VisibilityChecker provides an easy way for filtering certain properties, especially because it allows you to test for visibility (equals "will be serialized or not") for each method/field individually.
At least this helps for the serialization phase.
Here is what I did (using Jackson version 1.9.11):
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.introspect.AnnotatedMethod;
import org.codehaus.jackson.map.introspect.VisibilityChecker;
public static class InterfaceVisibilityChecker extends VisibilityChecker.Std {
private final Set<Method> visibleMethods;
public InterfaceVisibilityChecker(Class<?>... clazzes) {
super(JsonAutoDetect.Visibility.PUBLIC_ONLY);
this.visibleMethods = new HashSet<>();
for (Class<?> clz : clazzes) {
this.visibleMethods.addAll(Arrays.asList(clz.getMethods()));
}
}
#Override
public boolean isGetterVisible(Method m) {
return super.isGetterVisible(m) && isVisible(m);
}
#Override
public boolean isGetterVisible(AnnotatedMethod m) {
return isGetterVisible(m.getAnnotated());
}
private boolean isVisible(Method m) {
for (Method visiMthd : visibleMethods) {
if (isOverwriteMethod(m, visiMthd)) return true;
}
return false;
}
private boolean isOverwriteMethod(Method subMethod, Method superMethod) {
// names must be equal
if (! subMethod.getName().equals(superMethod.getName())) return false;
// return types must be assignable
if (! superMethod.getReturnType().isAssignableFrom(subMethod.getReturnType())) return false;
// parameters must be equal
if (! Arrays.equals(subMethod.getParameterTypes(), superMethod.getGenericParameterTypes())) return false;
// classes must be assignable
return superMethod.getDeclaringClass().isAssignableFrom(subMethod.getDeclaringClass());
}
}
The main idea is to use the standard VisibilityChecker and extend it by a check whether the method is declared in one of the given interfaces.
The checker is applied to an ObjectMapper instance using the following snippet:
ObjectMapper om = new ObjectMapper();
om.setVisibilityChecker(new InterfaceVisibilityChecker(
I1.class,
I2.class,
Ia.class,
Ib.class,
Ic.class
));
Some comments on the solution above:
The checker is not complete, methods like isIsGetterVisible or isFieldVisible can be handled in a similar manner if needed.
isOverwriteMethod is not optimized at all, it's checks could be cached.