Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Setting checkboxes in a TreeTable
I have Checkboxes as the property in the first (tree) column of my treetable. When a branch (parent) is checked, I want all of its leaves (children) to also be checked. Same thing when the parent's checkbox is un-checked. However, I cannot seem to access the childrens' checkboxes when the parent is checked. I've written a method that is called when the parent is checked, and here's where the problem lies:
logger.log(Level.INFO, "Item property is a " + treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product").getType().getName()); // com.vaadin.ui.CheckBox
CheckBox cbod = (CheckBox)treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product");
cbod.setValue(true);
In line 1, the result in the console is com.vaadin.ui.CheckBox. However, the next line throws a ClassCastException, stating that I cannot cast a com.vaadin.data.util.IndexedContainer$IndexedContainerProperty to a com.vaadin.ui.CheckBox. Eclipse was the one suggesting that I cast it, even though line #1 above returns a CheckBox anyway. What am I doing wrong?
Can you please share your source code a bit, So that I can help troubleshooting your issue. I have done something similar in my last project using tree table, I would be glad to help you out...
Sure, I'll show you what I think are the most important parts. And thanks for replying, @Krishna!
Okay, so here is the basic structure of the two main Java Beans:
public class Job {
// The variables this bean holds.
private Date shipDate;
private String jobId;
private String customerName;
private String customerPO;
private Timestamp proofSpecDate;
private Timestamp jobCompleted;
private PrintingCompany printingCompany;
private boolean overruns;
private List<OrderDetail> orderDetailList;
private boolean treeExpanded = true;
... (getters and setters) ...
}
public class OrderDetail {
// The variables this bean holds.
private int id;
private String orderId;
private String productId;
private String productDetail;
private PrintType printType;
private long numColors;
private long quantity;
private Timestamp itemCompleted;
private int proofNum;
private Timestamp proofDate;
private String thumbnail;
... (getters and setters) ...
}
As you can see, each Job bean contains a collection of OrderDetail beans. Sometimes, one Job will have only one OrderDetail, but sometimes it will have 2 or 3 or a dozen, etc. And the OrderDetail bean's orderId matches the Job bean's jobId to which it belongs. This forms the hierarchy that will be needed for the TreeTable.
Since it seems SQLContainer doesn't implement Container.Hierarchical, and since I have yet to figure out any other Container class to use, I decided to just keep them as beans, they way they are in my desktop Swing application.
It may be terribly inefficient, but here's how I've put them into a Vaadin TreeTable (this is in the main init method):
// Get a list of jobs on a particular date.
LocalDate tempDate = new LocalDate(2015, 7, 23);
List<Job> jobsList = null;
try {
jobsList = JobManager.getJobsByDate(tempDate);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (jobsList != null) {
// As long as the list of Jobs isn't empty.
for (Job j : jobsList) {
// Go through each item in the Jobs list and add it
// (along with all of its OrderDetail items) to the TreeTable.
Object jobItemId;
CheckBox cbj = new CheckBox(j.getCustomerName(), j.getJobCompleted() != null);
cbj.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
// TODO Auto-generated method stub
layout.addComponent(new Label("Job checkbox changed: " + cbj.getCaption() + ", value is now: " + event.getProperty().getValue()));
JobManager.jobClicked(event, j, treeTable);
}
});
jobItemId = treeTable.addItem(new Object{
userCanMarkAsDone ? cbj : j.getCustomerName(),
j.getJobId(), "", null, null, null}, j.getJobId());
logger.log(Level.INFO, "This Job's ItemID: " + jobItemId);
for (OrderDetail od : j.getOrderDetailList()) {
// Add each OrderDetail item to the TreeTable as well,
// and set their parent.
CheckBox cbod = new CheckBox(od.getProductId(), od.getItemCompleted() != null);
cbod.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChange(ValueChangeEvent event) {
// TODO Auto-generated method stub
layout.addComponent(new Label("OrderDetail checkbox changed: " + cbod.getCaption() + ", value is now: " + event.getProperty().getValue()));
layout.addComponent(new Label("Number of siblings: " + (j.getOrderDetailList().size() - 1)));
}
});
Object odItemId = treeTable.addItem(new Object{
userCanMarkAsDone ? cbod : od.getProductId(),
od.getProductDetail(), od.getPrintType().getValue(), od.getNumColors(), od.getQuantity(), (od.getNumColors() * od.getQuantity())}, od.getId());
treeTable.setParent(odItemId, jobItemId);
}
}
}
So each Job, then each Job's OrderDetail gets added to the TreeTable. The key part is on line 24 in that last bit of code, which calls a method which will (hopefully) write to the bean and database whenever someone checks/unchecks a Job. (I'll need to do the same for the OrderDetail part, too.) I think I can do that bit, but I also need it to check each of its children (OrderDetail) items. Here's what I've got so far:
@SuppressWarnings("unchecked")
public static void jobClicked(ValueChangeEvent event, Job job, TreeTable treeTable) {
if ((boolean)event.getProperty().getValue()) {
logger.log(Level.INFO, "Job " + job.getJobId() + " checked, setting to timestamp: " + System.currentTimeMillis());
// TODO Here is where the code goes for setting the Job bean's completed property to the current time,
// then updating the database.
// Also set each of the job's OrderDetail items to the same timestamp if they haven't already been set.
for (OrderDetail orderDetail : job.getOrderDetailList()) {
if (orderDetail.getItemCompleted() == null) {
// Only set the current OrderDetail item to completed if it isn't already set as completed.
logger.log(Level.INFO, "Setting the OrderDetail " + orderDetail.getProductId() + " to completion at " + System.currentTimeMillis());
// TODO Somehow set the checkbox as checked.
logger.log(Level.INFO, "Item property is a " + treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product").getType().getName()); // com.vaadin.ui.CheckBox
CheckBox cbod = (CheckBox)treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product");
cbod.setValue(true);
}
}
} else {
logger.log(Level.INFO, "Job " + job.getJobId() + " unchecked, clearing timestamp.");
// TODO Code here for setting the Job bean's completed property to null,
// then updating the database.
// Also set each of the job's OrderDetail items to the same timestamp if they haven't already been set.
for (OrderDetail orderDetail : job.getOrderDetailList()) {
if (orderDetail.getItemCompleted() != null) {
// Only set the current OrderDetail item to completed if it isn't already set as completed.
logger.log(Level.INFO, "Clearing the OrderDetail " + orderDetail.getProductId() + "'s completion date.");
// TODO Somehow set the checkbox as checked.
treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product").setValue(false);
}
}
}
}
And, of course, the error that I mentioned in the original post happens on line 17.
Now, I know this is a lot of code and, despite my efforts to comment it up, it is still difficult to follow, so please don't hesitate to ask questions about it if you're confused by why I did one thing or another. And thanks again for the offer to help! I greatly appreciate it!
Replacing line 16 in that last block of code with these three lines, I get some unusual (to me) results:
logger.log(Level.INFO, "Item property is of type " + treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product").getType().getName()); // com.vaadin.ui.CheckBox
logger.log(Level.INFO, "And its class is " + treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product").getClass().getName()); // com.vaadin.data.util.IndexedContainer$IndexedContainerProperty
logger.log(Level.INFO, "And its value is currently " + treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product").getValue()); // com.vaadin.ui.CheckBox@489b213b
Especially that third line, where I was expecting a true or false, I get--I think--a CheckBox object instance. So, I changed the problem line to:
CheckBox cbod = (CheckBox)treeTable.getItem(orderDetail.getId()).getItemProperty("Name / Product").getValue();
and it actually seems to work! So, to get to the actual checkbox, I have to get the ItemProperty's value first. Wow, that was confusing!