我将我的列名称建议为here标签,以便我可以获取其名称的工具提示:
for (Entry<String, String> ent : dc.getSortedAssignedOrg().entrySet()) {
TreeTableColumn<String, ArrayList<String>> col = new TreeTableColumn<>();
Label label = new Label(ent.getValue());
col.setGraphic(label);
col.setEditable(false);
col.setSortable(false);
label.setTooltip(new Tooltip(label.getText()));// tooltip for column
.
.
.
现在问题是我的TableMenuButton没有显示列名,而点击treetableview右上角的加号会打开一个列表,其中只有已检查的符号,我可以删除或添加。但名称本身并未显示。我该如何解决这个问题?
答案 0 :(得分:1)
您可以创建自己的表格菜单。自从内置菜单e以来,您最好使用自定义菜单。 G。每次单击按钮时关闭。不幸的是,上下文菜单没有getter,所以你必须通过反射或查找来查找它。
我通过reflection和lookup机制为自定义菜单创建了一个要点。也许对你有所帮助。
您的相关部分将是
CheckBox cb = new CheckBox(tableColumn.getText());
您将菜单项设置为您喜欢的文本,i。即标签的文字。
这是TreeTableView的查找版本:
CustomTreeTableMenuDemo.java
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class CustomTreeTableMenuDemo extends Application {
List<Employee> employees = Arrays.<Employee> asList(new Employee(
"Ethan Williams", "ethan.williams@example.com"), new Employee(
"Emma Jones", "emma.jones@example.com"), new Employee(
"Michael Brown", "michael.brown@example.com"), new Employee(
"Anna Black", "anna.black@example.com"), new Employee(
"Rodger York", "roger.york@example.com"), new Employee(
"Susan Collins", "susan.collins@example.com"));
final TreeItem<Employee> root = new TreeItem<>(new Employee(
"Sales Department", ""));
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
stage.setTitle("Table Menu Demo");
stage.setWidth(500);
stage.setHeight(550);
root.setExpanded(true);
employees.stream().forEach((employee) -> {
root.getChildren().add(new TreeItem<>(employee));
});
stage.setTitle("Tree Table View Sample");
final Scene scene = new Scene(new Group(), 400, 400);
scene.setFill(Color.LIGHTGRAY);
Group sceneRoot = (Group) scene.getRoot();
TreeTableColumn<Employee, String> empColumn = new TreeTableColumn<>(
"Employee");
empColumn.setPrefWidth(150);
empColumn
.setCellValueFactory((
TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(
param.getValue().getValue().getName()));
TreeTableColumn<Employee, String> emailColumn = new TreeTableColumn<>(
"Email");
emailColumn.setPrefWidth(190);
emailColumn
.setCellValueFactory((
TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(
param.getValue().getValue().getEmail()));
TreeTableView<Employee> treeTableView = new TreeTableView<>(root);
treeTableView.getColumns().setAll(empColumn, emailColumn);
sceneRoot.getChildren().add(treeTableView);
stage.setScene(scene);
stage.show();
// enable table menu button and add a custom menu to it
TreeTableUtils.addCustomTreeTableMenu(treeTableView);
}
public class Employee {
private SimpleStringProperty name;
private SimpleStringProperty email;
public SimpleStringProperty nameProperty() {
if (name == null) {
name = new SimpleStringProperty(this, "name");
}
return name;
}
public SimpleStringProperty emailProperty() {
if (email == null) {
email = new SimpleStringProperty(this, "email");
}
return email;
}
private Employee(String name, String email) {
this.name = new SimpleStringProperty(name);
this.email = new SimpleStringProperty(email);
}
public String getName() {
return name.get();
}
public void setName(String fName) {
name.set(fName);
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
}
}
TreeTableUtils.java
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.Label;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.input.MouseEvent;
import com.sun.javafx.scene.control.skin.TableHeaderRow;
import com.sun.javafx.scene.control.skin.TreeTableViewSkin;
public class TreeTableUtils {
/**
* Make table menu button visible and replace the context menu with a custom context menu via reflection.
* The preferred height is modified so that an empty header row remains visible. This is needed in case you remove all columns, so that the menu button won't disappear with the row header.
* IMPORTANT: Modification is only possible AFTER the table has been made visible, otherwise you'd get a NullPointerException
* @param treeTableView
*/
public static void addCustomTreeTableMenu( TreeTableView treeTableView) {
// enable table menu
treeTableView.setTableMenuButtonVisible(true);
// replace internal mouse listener with custom listener
setCustomContextMenu( treeTableView);
}
private static void setCustomContextMenu( TreeTableView treeTableView) {
TreeTableViewSkin<?> treeTableViewSkin = (TreeTableViewSkin<?>) treeTableView.getSkin();
// get all children of the skin
ObservableList<Node> children = treeTableViewSkin.getChildren();
// find the TableHeaderRow child
for (int i = 0; i < children.size(); i++) {
Node node = children.get(i);
if (node instanceof TableHeaderRow) {
TableHeaderRow tableHeaderRow = (TableHeaderRow) node;
// setting the preferred height for the table header row
// if the preferred height isn't set, then the table header would disappear if there are no visible columns
// and with it the table menu button
// by setting the preferred height the header will always be visible
// note: this may need adjustments in case you have different heights in columns (eg when you use grouping)
double defaultHeight = tableHeaderRow.getHeight();
tableHeaderRow.setPrefHeight(defaultHeight);
for( Node child: tableHeaderRow.getChildren()) {
// child identified as cornerRegion in TableHeaderRow.java
if( child.getStyleClass().contains( "show-hide-columns-button")) {
// get the context menu
ContextMenu columnPopupMenu = createContextMenu( treeTableView);
// replace mouse listener
child.setOnMousePressed(me -> {
// show a popupMenu which lists all columns
columnPopupMenu.show(child, Side.BOTTOM, 0, 0);
me.consume();
});
}
}
}
}
}
/**
* Create a menu with custom items. The important thing is that the menu remains open while you click on the menu items.
* @param cm
* @param treeTableView
*/
private static ContextMenu createContextMenu( TreeTableView treeTableView) {
ContextMenu cm = new ContextMenu();
// create new context menu
CustomMenuItem cmi;
// select all item
Label showAll = new Label("Show all");
showAll.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
for (Object obj : treeTableView.getColumns()) {
((TableColumn<?, ?>) obj).setVisible(true);
}
}
});
cmi = new CustomMenuItem(showAll);
cmi.setHideOnClick(false);
cm.getItems().add(cmi);
// deselect all item
Label hideAll = new Label("Hide all");
hideAll.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
for (Object obj : treeTableView.getColumns()) {
((TableColumn<?, ?>) obj).setVisible(false);
}
}
});
cmi = new CustomMenuItem(hideAll);
cmi.setHideOnClick(false);
cm.getItems().add(cmi);
// separator
cm.getItems().add(new SeparatorMenuItem());
// menu item for each of the available columns
for (Object obj : treeTableView.getColumns()) {
TreeTableColumn<?, ?> tableColumn = (TreeTableColumn<?, ?>) obj;
CheckBox cb = new CheckBox(tableColumn.getText());
cb.selectedProperty().bindBidirectional(tableColumn.visibleProperty());
cmi = new CustomMenuItem(cb);
cmi.setHideOnClick(false);
cm.getItems().add(cmi);
}
return cm;
}
}