Convert ArrayList to Observable List for JavaFX program?
Asked Answered
S

3

8

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

Szabo answered 14/4, 2016 at 17:2 Comment(0)
D
11

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.

Diversion answered 14/4, 2016 at 17:4 Comment(1)
It works!!! So awesome!!! I'm over the moon right now, you have no idea. Thanks a million, this is really great. :)Szabo
R
5

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...

Rudolfrudolfo answered 10/10, 2017 at 8:29 Comment(0)
P
1
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);
    }
});
Pergrim answered 2/4, 2018 at 20:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.