In order for the end-user to constrain a search to some columns of the main TableView, I needed a treeview with checkboxes. I decided to embed this TreeView in a popup, showing on click on a custom button.
I have created the following class, inspired from the question: Java FX8 TreeView in a table cell
public class CustomTreeMenuButton extends MenuButton {
private PopupControl popup = new PopupControl();
private TreeView<? extends Object> tree;
private CustomTreeMenuButton me = this;
public void setTree(TreeView<? extends Object> tree) {
this.tree = tree;
}
public CustomTreeMenuButton() {
super();
this.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (!popup.isShowing()) {
Bounds b = me.localToScreen(me.getBoundsInLocal());
double x = b.getMinX();
double y = b.getMaxY();
popup.setAutoHide(true);
// popup.setAutoFix(true);
popup.setAnchorX(x);
popup.setAnchorY(y);
popup.setSkin(new Skin<Skinnable>() {
@Override
public void dispose() {
}
@Override
public Node getNode() {
return tree;
}
@Override
public Skinnable getSkinnable() {
return null;
}
});
popup.show(me.getScene().getWindow());
}
}
});
}
}
The tree I am working with contains CheckBoxTreeItem
objects, and while the popup is working, there is some weird blur on all checkboxes, whenever the focus is not on a checkbox. (See GIF below)
First, I was thinking it was maybe an antialiasing problem, but popup.getScene().getAntiAliasing().toString()
returns DISABLED
Then, I saw that non integer anchor points could cause problems. However popup.setAutoFix(true)
did nothing, nor did the following:
popup.setAnchorX(new Double(x).intValue());
popup.setAnchorY(new Double(y).intValue());
It might be worth noting that I am working with FXML.
How can I get sharp checkboxes regardless of their focus ?
I would suggest a built-in control, CustomMenuItem, rather than reinventing the wheel:
A MenuItem that allows for arbitrary nodes to be embedded within it, by assigning a Node to the content property.
An example
// Create the tree
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("All stuff");
rootItem.setExpanded(true);
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setEditable(true);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
for (int i = 0; i < 8; i++) {
final CheckBoxTreeItem<String> checkBoxTreeItem =
new CheckBoxTreeItem<String>("Stuff" + (i+1));
rootItem.getChildren().add(checkBoxTreeItem);
}
tree.setRoot(rootItem);
tree.setShowRoot(true);
// Create a custom menu item
CustomMenuItem customMenuItem = new CustomMenuItem(tree);
customMenuItem.setHideOnClick(false);
// Create the menu button
MenuButton mb = new MenuButton("Stuffs");
mb.getItems().add(customMenuItem);
And the output
Note: It is important to set the hideOnClickProperty to true
, to avoid closing when the user clicks in the tree, which can be even done in the contructor, so you can shorten the initialization to:
CustomMenuItem customMenuItem = new CustomMenuItem(tree, false);
If you want to remove the hover glow, you can add the following CSS class:
.menu-item {
-fx-padding: 0;
}