I tried by implementing my POJO class with Parceable. but it shows error while writing value to object of View.
POJO Class:
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
import android.widget.EditText;
public class FieldData implements Parcelable {
private Integer id;
private String value;
private Integer job_transaction_id;
private Integer field_attribute_master_id;
private Boolean required;
private View view;
private String viewType;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Integer getJob_transaction_id() {
return job_transaction_id;
}
public void setJob_transaction_id(Integer job_transaction_id) {
this.job_transaction_id = job_transaction_id;
}
public Integer getField_attribute_master_id() {
return field_attribute_master_id;
}
public void setField_attribute_master_id(Integer field_attribute_master_id) {
this.field_attribute_master_id = field_attribute_master_id;
}
public Boolean getRequired() {
return required;
}
public void setRequired(Boolean required) {
this.required = required;
}
public View getView() {
return view;
}
public void setView(View view) {
this.view = view;
}
public String getViewType() {
return viewType;
}
public void setViewType(String viewType) {
this.viewType = viewType;
}
protected FieldData(Parcel in) {
id = in.readByte() == 0x00 ? null : in.readInt();
value = in.readString();
job_transaction_id = in.readByte() == 0x00 ? null : in.readInt();
field_attribute_master_id = in.readByte() == 0x00 ? null : in.readInt();
byte requiredVal = in.readByte();
required = requiredVal == 0x02 ? null : requiredVal != 0x00;
view = (View) in.readValue(View.class.getClassLoader());
viewType = in.readString();
}
public FieldData() {
// TODO Auto-generated constructor stub
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (id == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeInt(id);
}
dest.writeString(value);
if (job_transaction_id == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeInt(job_transaction_id);
}
if (field_attribute_master_id == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeInt(field_attribute_master_id);
}
if (required == null) {
dest.writeByte((byte) (0x02));
} else {
dest.writeByte((byte) (required ? 0x01 : 0x00));
}
**dest.writeValue(view);**//Error at this line
dest.writeString(viewType);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<FieldData> CREATOR = new Parcelable.Creator<FieldData>() {
#Override
public FieldData createFromParcel(Parcel in) {
return new FieldData(in);
}
#Override
public FieldData[] newArray(int size) {
return new FieldData[size];
}
};
}
error shown at dest.writeValue(view);
Error : java.lang.RuntimeException: Parcel: unable to marshal value android.widget.EditText#41ac34a8
View is not parcelable.
ideally you can create similar view in the second activity. Required attibutes can be passed from 1st activity to second via intent
make it serializable by implementing Serializable Interface in your pojo class.
then you can put Serializable in Bundle.
public final class SavingsAccount implements Serializable {
{
}
Related
Thanks to those who will try to help me!
First time I sent a message. I'm stuck with my parcel.
I try to send an object Neighbour in a recyclerView for a class DetailedNeighbour. After I send my variable to DetailedActivity.putExtra("DNeighbour", neighbour); is well equal to what I want and after in DetailedNeighbourActivity is equal to null.
Neighbour:
package com.openclassrooms.entrevoisins.model;
/**
* Model object representing a Neighbour
*/
public class Neighbour implements Parcelable {
/** Identifier */
private long id;
/** Full name */
private String name;
/** Avatar */
private String avatarUrl;
/** Adress */
private String address;
/** Phone number */
private String phoneNumber;
/** About me */
private String aboutMe;
/**
* Constructor
* #param id
* #param name
* #param avatarUrl
*/
public Neighbour(long id, String name, String avatarUrl, String address,
String phoneNumber, String aboutMe) {
this.id = id;
this.name = name;
this.avatarUrl = avatarUrl;
this.address = address;
this.phoneNumber = phoneNumber;
this.aboutMe = aboutMe;
}
public Neighbour (Parcel in){ //constructor //Protected ?
id =in.readLong(); //read and set saved values from parcel
name=in.readString();
avatarUrl=in.readString();
address=in.readString();
phoneNumber=in.readString();
aboutMe=in.readString();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAvatarUrl() {
return avatarUrl;
}
public void setAvatarUrl(String avatarUrl) {
this.avatarUrl = avatarUrl;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAboutMe() {
return aboutMe;
}
public void setAboutMe(String aboutMe) {
this.aboutMe = aboutMe;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Neighbour neighbour = (Neighbour) o;
return Objects.equals(id, neighbour.id);
}
#Override
public int hashCode() {
return Objects.hash(id);
}
#Override
public void writeToParcel(Parcel parcel, int flags) { // In this method you add all your class properties to the parcel which are needed to transfer.
parcel.writeString(name);
parcel.writeString(phoneNumber);
parcel.writeString(avatarUrl);
parcel.writeString(aboutMe);
parcel.writeString(address);
parcel.writeLong(id); /// for favoris ?
}
public static final Parcelable.Creator<Neighbour> CREATOR = new Parcelable.Creator<Neighbour>() { ///This is the method which is used to bind everything together. Nothing much is done here.
#Override
public Neighbour createFromParcel(Parcel in) {
return new Neighbour(in);
}
#Override
public Neighbour[] newArray(int size) {
return new Neighbour[size];
}
};
public static Creator<Neighbour> getCREATOR() {
return CREATOR;
}
#Override
public int describeContents() {
return 0;
}
}
RecyclerViewAdapter:
package com.openclassrooms.entrevoisins.ui.neighbour_list;
public class MyNeighbourRecyclerViewAdapter extends RecyclerView.Adapter<MyNeighbourRecyclerViewAdapter.ViewHolder> {
private final List<Neighbour> mNeighbours;
public MyNeighbourRecyclerViewAdapter(List<Neighbour> items) {
mNeighbours = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_neighbour, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Neighbour neighbour = mNeighbours.get(position);
holder.mNeighbourName.setText(neighbour.getName());
Glide.with(holder.mNeighbourAvatar.getContext())
.load(neighbour.getAvatarUrl())
.apply(RequestOptions.circleCropTransform())
.into(holder.mNeighbourAvatar);
holder.mNeighbourName.setOnClickListener(new View.OnClickListener() { /// Observe le clic sur bouton name
#Override
public void onClick(View view) {
Intent DetailedActivity = new Intent(view.getContext(), DetailedNeighbourActivity.class); //
DetailedActivity.putExtra("DNeighbour", neighbour);
view.getContext().startActivity(DetailedActivity);//
EventBus.getDefault();//
Log.i("DEBUG","l'utilisateur essaye d'ouvrir le détaille");
}
});
holder.mDeleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EventBus.getDefault().post(new DeleteNeighbourEvent(neighbour));
}
});
}
#Override
public int getItemCount() {
return mNeighbours.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.item_list_avatar)
public ImageView mNeighbourAvatar;
#BindView(R.id.item_list_name)
public TextView mNeighbourName;
#BindView(R.id.item_list_delete_button)
public ImageButton mDeleteButton;
public ViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
DetailedNeighboursActivity:
public class DetailedNeighbourActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detailed_neighbour);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
Neighbour neighbour = (Neighbour) getIntent().getParcelableExtra("DNeighbour");
String name = neighbour.getName();
EventBus.getDefault();
Log.i("DEBUG", "Le détaille "+ name);
}
}
I'm not really smart ! Sorry for you time .
parcel and writeparcel constructor need the same order for variables. it's ok my code work.
I have a FirebaseRecyclerAdapter fetching data from the firebase database but when I am trying to access firebase data the getter method of the POJO returns null. I am able to get the database reference key.
final Query beveragesQuery = mDatabaseReference.child(FirebaseValues.PRODUCTS)
.child(FirebaseValues.BEVERAGES);
FirebaseRecyclerOptions<GenericProductModel> beveragesOptions =
new FirebaseRecyclerOptions.Builder<GenericProductModel>()
.setQuery(beveragesQuery, GenericProductModel.class)
.build();
adapter = new FirebaseRecyclerAdapter<GenericProductModel, Combos.MovieViewHolder>(
beveragesOptions
) {
#NonNull
#Override
public Combos.MovieViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cards_cardview_layout, parent, false);
return new Combos.MovieViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull Combos.MovieViewHolder viewHolder, int position, #NonNull GenericProductModel model) {
Log.d(TAG, "Item received:"+getRef(position).getKey());
String json = new Gson().toJson(model);
Log.d(TAG, "Item received:"+ json);
Log.d(TAG, "Item received:"+ model.toString());
if (tv_no_item.getVisibility() == View.VISIBLE) {
tv_no_item.setVisibility(View.GONE);
}
Log.d(TAG, "card name:"+model.getCardname());
viewHolder.cardname.setText(model.getCardname());
viewHolder.cardprice.setText("₹ " + Float.toString(model.getCardprice()));
Picasso.get().load(model.getCardimage()).into(viewHolder.cardimage);
viewHolder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Beverages.this, IndividualProduct.class);
intent.putExtra("product", getItem(position));
startActivity(intent);
}
});
}
#Override
public void onError(DatabaseError e) {
Log.e(TAG, "RV Adapter, Error occurred: " + e.getMessage());
}
};
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
adapter.startListening();
mRecyclerView.setAdapter(adapter);
}
My POJO or model class is
public class GenericProductModel implements Serializable {
public int cardid;
public String cardname;
public String cardimage;
public String carddescription;
public float cardprice;
public GenericProductModel() {
}
public GenericProductModel(int cardid, String cardname, String cardimage, String carddescription, float cardprice) {
this.cardid = cardid;
this.cardname = cardname;
this.cardimage = cardimage;
this.carddescription = carddescription;
this.cardprice = cardprice;
}
public int getCardid() {
return cardid;
}
public String getCardname() {
return cardname;
}
public String getCardimage() {
return cardimage;
}
public String getCarddescription() {
return carddescription;
}
public float getCardprice() {
return cardprice;
}
public void setCardid(int cardid) {
this.cardid = cardid;
}
public void setCardname(String cardname) {
this.cardname = cardname;
}
public void setCardimage(String cardimage) {
this.cardimage = cardimage;
}
public void setCarddescription(String carddescription) {
this.carddescription = carddescription;
}
public void setCardprice(float cardprice) {
this.cardprice = cardprice;
}
}
I am implementing Serializable because I am sending this data as an intent to other activity.
Added some more log options for clearity
When I run the app the log output I am getting is:
03-17 15:05:55.200 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: Item received, received:1
03-17 15:05:55.227 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: Item received:{"a":0,"e":0.0}
03-17 15:05:55.227 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: Item received:com.vdeveloper.chaisutta.b.a#63d3fc
03-17 15:05:55.227 4501-4501/com.vdeveloper.chaisutta D/BeveragesTAG: card name:null
Database Screenshot:
I have found a solution myself. The problem was with my POJO. As this project was on androidx I need to add the annotation "#Keep" to stop the compiler from removing methods which it thinks are redundant.
import java.io.Serializable;
import androidx.annotation.Keep;
#Keep
public class GenericProductModel implements Serializable {
public int cardid;
public String cardname;
public String cardimage;
public String carddescription;
public float cardprice;
public GenericProductModel() {
}
public GenericProductModel(int cardid, String cardname, String cardimage, String carddescription, float cardprice) {
this.cardid = cardid;
this.cardname = cardname;
this.cardimage = cardimage;
this.carddescription = carddescription;
this.cardprice = cardprice;
}
public int getCardid() {
return cardid;
}
public String getCardname() {
return cardname;
}
public String getCardimage() {
return cardimage;
}
public String getCarddescription() {
return carddescription;
}
public float getCardprice() {
return cardprice;
}
public void setCardid(int cardid) {
this.cardid = cardid;
}
public void setCardname(String cardname) {
this.cardname = cardname;
}
public void setCardimage(String cardimage) {
this.cardimage = cardimage;
}
public void setCarddescription(String carddescription) {
this.carddescription = carddescription;
}
public void setCardprice(float cardprice) {
this.cardprice = cardprice;
}
}
Thanks, everyone for helping
You are getting null because all your values are null since you are returning in each getter this.fieldName instead of the fieldName. To solve this, please change your getters to:
public int getCardid() {
return cardid;
}
public String getCardname() {
return cardname;
}
public String getCardimage() {
return cardimage;
}
public String getCarddescription() {
return carddescription;
}
public float getCardprice() {
return cardprice;
}
See, there is no this anymore.
This code works but I do not pass the data contained in the arrayList.
public class Percorso implements Parcelable {
int id;
String nome;
double distanza;
int numero_commenti;
double valutazione;
ArrayList<Commento> commenti;
ArrayList<Cordinate> cordinate;
public Percorso(){
}
protected Percorso(Parcel in) {
id = in.readInt();
nome = in.readString();
distanza = in.readDouble();
numero_commenti = in.readInt();
valutazione = in.readDouble();
}
public static final Creator<Percorso> CREATOR = new Creator<Percorso>() {
#Override
public Percorso createFromParcel(Parcel in) {
return new Percorso(in);
}
#Override
public Percorso[] newArray(int size) {
return new Percorso[size];
}
};
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public double getDistanza() {
return distanza;
}
public void setDistanza(double distanza) {
this.distanza = distanza;
}
public int getNumero_commenti() {
return numero_commenti;
}
public void setNumero_commenti(int numero_commenti) {
this.numero_commenti = numero_commenti;
}
public double getValutazione() {
return valutazione;
}
public void setValutazione(double valutazione) {
this.valutazione = valutazione;
}
public ArrayList<Commento> getCommenti() {
return commenti;
}
public void setCommenti(ArrayList<Commento> commenti) {
this.commenti = commenti;
}
public ArrayList<Cordinate> getCordinate() {
return cordinate;
}
public void setCordinate(ArrayList<Cordinate> cordinate) {
this.cordinate = cordinate;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
parcel.writeString(nome);
parcel.writeDouble(distanza);
parcel.writeInt(numero_commenti);
parcel.writeDouble(valutazione);
}
}
//
public class Cordinate implements Parcelable {
double latitudine;
double longitudin;
public Cordinate(){}
protected Cordinate(Parcel in) {
latitudine = in.readDouble();
longitudin = in.readDouble();
}
public static final Creator<Cordinate> CREATOR = new Creator<Cordinate>() {
#Override
public Cordinate createFromParcel(Parcel in) {
return new Cordinate(in);
}
#Override
public Cordinate[] newArray(int size) {
return new Cordinate[size];
}
};
public double getLatitudine() {
return latitudine;
}
public void setLatitudine(double latitudine) {
this.latitudine = latitudine;
}
public double getLongitudin() {
return longitudin;
}
public void setLongitudin(double longitudin) {
this.longitudin = longitudin;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeDouble(latitudine);
parcel.writeDouble(longitudin);
}
}
INTENT
Percorso percorsoClick = listaPercorsi.get(i);
Intent intent = new Intent(getBaseContext(), PercorsoActivity.class);
intent.putExtra("percorso", percorsoClick);
startActivity(intent);
GET INTENT
percorso = getIntent().getParcelableExtra("percorso");
System.out.println(percorso.getNome());
getNome() work because is not a arrayList.
instead get getCordinate not work.
percorso.getCordinate().size() // null
I hope it was clear. I have set the Parcelable implementation on all classes.
Thank you very much for the help
ArrayList<Cordinate> cordinate; is not being parcelled. You still have to take care of write/read in/from Parcel parcel. Eg
protected Percorso(Parcel in) {
id = in.readInt();
nome = in.readString();
distanza = in.readDouble();
numero_commenti = in.readInt();
valutazione = in.readDouble();
cordinate = new ArrayList<Cordinate>();
in.readList(cordinate,Cordinate.class.getClassLoader());
}
and
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
parcel.writeString(nome);
parcel.writeDouble(distanza);
parcel.writeInt(numero_commenti);
parcel.writeDouble(valutazione);
parcel.writeList(cordinate);
}
I'm trying to set an initial input to a treeview but I must forget something because It does not displays anything.
public class TreeEditor extends OperationDetailsAspectEditor {
private TreeViewer fConditionField;
private BooleanOperator root;
#Override
public void createControl(Composite parent, FormToolkit toolkit) {
createConditionControls(parent, toolkit);
}
private void createConditionControls(final Composite parent, FormToolkit toolkit) {
fConditionField = new TreeViewer(parent);
fConditionField.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 5));
fConditionField.setLabelProvider(new ConditionsLabelProvider());
fConditionField.setContentProvider(new ConditionsContentProvider());
fConditionField.setUseHashlookup(true);
fConditionField.setInput(getInitialTreeConditions());
fConditionField.expandAll();
}
private BooleanOperator getInitialTreeConditions(){
root = new BooleanOperator(Operator.AND);
return root;
}
}
public class ConditionsLabelProvider implements ILabelProvider {
#Override
public void addListener(ILabelProviderListener paramILabelProviderListener) {}
#Override
public void dispose() { }
#Override
public boolean isLabelProperty(Object paramObject, String paramString) {return false;}
#Override
public void removeListener(
ILabelProviderListener paramILabelProviderListener) {}
#Override
public Image getImage(Object paramObject) {return null;}
#Override
public String getText(Object element) {
if(element instanceof Model){
return ((Model) element).getDisplayName();
} else {
throw unknownElement(element);
}
}
protected RuntimeException unknownElement(Object element) {
return new RuntimeException("Unknown type of element in tree of type " + element.getClass().getName());
}
}
public class ConditionsContentProvider implements ITreeContentProvider {
private static Object[] EMPTY_ARRAY = new Object[0];
protected TreeViewer viewer;
#Override
public void dispose() {
}
#Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
this.viewer = (TreeViewer) viewer;
}
#Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
#Override
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof BooleanOperator){
BooleanOperator operator = ((BooleanOperator) parentElement);
return concat(operator.getOperators().toArray(),
operator.getExpresions().toArray());
}
return EMPTY_ARRAY;
}
#Override
public Object getParent(Object element) {
if(element instanceof Model) {
return ((Model)element).getParent();
}
return null;
}
#Override
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
protected Object[] concat(Object[] a, Object[] b) {
int aLen = a.length;
int bLen = b.length;
Object[] c = new Object[aLen + bLen];
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
protected Object[] concat(Object[]... arrays) {
Object[] array = arrays[0] != null? arrays[0] : null;
for(int i = 1; i < arrays.length; i++) {
array = concat(arrays[i-1], arrays[i]);
}
return array;
}
}
Models
public abstract class Model {
protected BooleanOperator parent;
protected String displayName;
public String getDisplayName(){ return displayName; }
public void setDisplayName(String displayName){
this.displayName = displayName;
}
public BooleanOperator getParent() { return parent; }
public void setParent(BooleanOperator parent) { this.parent = parent; }
public Model(String displayName) { this.displayName = displayName; }
public Model(){}
}
public class BooleanOperator extends Model {
private Operator operator;
private List<BooleanOperator> operators;
private List<Expression> expressions;
public Operator getOperator() {
return operator;
}
public List<BooleanOperator> getOperators() {
return operators;
}
public List<Expresion> getExpresions() {
return expresions;
}
public BooleanOperator() {
operators = new ArrayList<BooleanOperator>();
expresions = new ArrayList<Expresion>();
}
public BooleanOperator(Operator operator) {
this();
this.operator = operator;
this.displayName = operator.toString();
}
}
The idea is that Tree contains something such as:
AND
|- Attribute_1 == value_1
|- Attribute_2 == value_2
|- OR
|- Attribute_3 == value_3
The nodes are Boolean operators and the leaves are expressions.
I want to find the method that adds nodes to a JTree dynamically, looking through the documentation and the examples, this can only be done at the constructor of the JTree.
If possible please show me the code snippets to do this.
Thanks in advance.
You need to have a custom implementation of a TreeModel and TreeNode, see bellow. Just extend LazyTreeModel and implement loadChildren().
There a few dependencies that you must replace with your implementations : LOG - your logger
and WorkerManager.getInstance().schedule(new LoadNodesWorker()) you can replace it with a Thread() - Worker is the equivalent of Runnable.
public abstract class LazyTreeModel extends DefaultTreeModel implements TreeWillExpandListener {
public LazyTreeModel(TreeNode root, JTree tree) {
super(root);
setAsksAllowsChildren(true);
tree.addTreeWillExpandListener(this);
tree.setModel(this);
}
public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
LazyTreeNode node = (LazyTreeNode) event.getPath().getLastPathComponent();
if (node.isLoaded()) {
return;
}
setLoading(node, false);
WorkerManager.getInstance().schedule(new LoadNodesWorker(node));
}
public void reloadNode(String id) {
LazyTreeNode node = findNode(id);
if (node != null) {
node.setLoaded(false);
setLoading(node, true);
WorkerManager.getInstance().schedule(new LoadNodesWorker(node));
}
}
public void reloadParentNode(String id) {
LazyTreeNode node = findParent(id);
if (node != null) {
node.setLoaded(false);
setLoading(node, true);
WorkerManager.getInstance().schedule(new LoadNodesWorker(node));
}
}
public LazyTreeNode findParent(String id) {
LazyTreeNode node = findNode(id);
if (node != null && node.getParent() != null) {
return (LazyTreeNode) node.getParent();
}
return null;
}
public void loadFirstLevel() {
setLoading((LazyTreeNode) getRoot(), false);
WorkerManager.getInstance().schedule(new LoadNodesWorker((LazyTreeNode) getRoot()));
}
public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
}
protected void setChildren(LazyTreeNode parentNode, LazyTreeNode... nodes) {
if (nodes == null) {
return;
}
int childCount = parentNode.getChildCount();
if (childCount > 0) {
for (int i = 0; i < childCount; i++) {
removeNodeFromParent((MutableTreeNode) parentNode.getChildAt(0));
}
}
for (int i = 0; i < nodes.length; i++) {
insertNodeInto(nodes[i], parentNode, i);
}
}
private void setLoading2(final LazyTreeNode parentNode, final boolean reload) {
if (reload) {
setChildren(parentNode, createReloadingNode());
} else {
setChildren(parentNode, createLoadingNode());
}
}
private void setLoading(final LazyTreeNode parentNode, final boolean reload) {
if (SwingUtilities.isEventDispatchThread()) {
setLoading2(parentNode, reload);
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setLoading2(parentNode, reload);
}
});
} catch (Exception e) {
LOG.error("Cannot create loading node", e);
}
}
}
private LazyTreeNode findNode(String id) {
return findNode(id, (LazyTreeNode) getRoot());
}
private LazyTreeNode findNode(String id, LazyTreeNode parent) {
int count = parent.getChildCount();
for (int i = 0; i < count; i++) {
LazyTreeNode node = (LazyTreeNode) parent.getChildAt(i);
if (id.equals(node.getId())) {
return node;
}
if (node.isLoaded()) {
node = findNode(id, node);
if (node != null) {
return node;
}
}
}
return null;
}
public abstract LazyTreeNode[] loadChildren(LazyTreeNode parentNode);
protected LazyTreeNode createLoadingNode() {
return new LazyTreeNode(null, "Loading...", false);
}
protected LazyTreeNode createReloadingNode() {
return new LazyTreeNode(null, "Refreshing...", false);
}
class LoadNodesWorker implements Worker {
private LazyTreeNode parentNode;
LoadNodesWorker(LazyTreeNode parent) {
this.parentNode = parent;
}
public String getName() {
return "Lazy loading of node " + parentNode.getId();
}
public void execute() throws Exception {
final LazyTreeNode[] treeNodes = loadChildren(parentNode);
if (treeNodes == null) {
return;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
parentNode.setLoaded(true);
setChildren(parentNode, treeNodes);
}
});
}
}
}
public class LazyTreeNode extends DefaultMutableTreeNode {
private boolean loaded;
private String id;
public LazyTreeNode(String id) {
this(id, null);
}
public LazyTreeNode(String id, Object userObject) {
this(id, userObject, true);
}
public LazyTreeNode(String id, Object userObject, boolean allowsChildren) {
super(userObject, allowsChildren);
this.id = id;
}
public String getId() {
return id;
}
protected boolean isLoaded() {
return loaded;
}
protected void setLoaded(boolean loaded) {
this.loaded = loaded;
}
#Override
public boolean isLeaf() {
return !getAllowsChildren();
}
}
Try this
Edit with more explanation: you want your tree model to be based on MutableTreeNode. The link above is an example from the Sun tutorial.
The Sun example tutorial mentioned by I82Much, includes a demo project, DynamicTreeDemo, that is made up of the two source files DynamicTreeDemo.java and DynamicTree.java. You should be able to get to them from these links.