如何确保代码在继承时以特定顺序执行
How to ensure code is executed in a specific order on inheritance
我有这个超级 class 扩展 TableView
,我想制作的每个 table 都应该继承自。
这行代码需要为每个继承自 superclass 并需要 ContextMenu
:
的 class 执行
// Sets the context menu for each specific row. This way no
// context menu will appear if we click on a row that is
// empty.
setRowFactory(r -> {
TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(contextMenu);
}
}
};
});
问题是 ContextMenu
需要在这段代码执行之前实例化,因此我不能放入超级 class.
的构造函数
如果 table 需要 ContextMenu
(不总是案例):
- 用
MenuItem
个实例实例化 ContextMenu
(我想 MenuItem
个实例理论上可以在以后实例化和添加)。
- 使用在步骤 1 中实例化的上下文菜单调用上面的 "setRowFactory" 代码。
我已经多次尝试解决这个问题,但仍然没有找到令人满意的解决方案。也许我遗漏了一些明显的东西。
编辑: 如果您能以某种方式禁止用户使用 TableView
的原始 setContextMenu
方法以确保 `ContextMenu 是完美的以正确的方式添加。但我想这是不可能的。
看起来您只是想禁止在 table 中的空行上显示上下文菜单。更简单的方法是
public class MyTableView<T> extends TableView<T> {
public MyTableView() {
setRowFactory(tv -> {
TableRow<T> row = new TableRow<>();
row.setOnContextMenuRequested(e -> {
if (row.isEmpty()) {
e.consume();
}
}
return row ;
});
}
// ...
}
回答您提出的问题(确保您只(且始终)在致电 setContextMenu
后致电 setRowFactory
):
你可以做
public class MyTableView<T> extends TableView<T> {
private final ContextMenu contextMenu ;
public MyTableView(ContextMenu contextMenu) {
this.contextMenu = contextMenu ;
setRowFactory(r -> {
TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(contextMenu);
}
}
};
});
}
// ...
}
或
public class MyTableView<T> extends TableView<T> {
private ContextMenu rowContextMenu ;
public ContextMenu getRowContextMenu() {
return rowContextMenu ;
}
public void setRowContextMenu(ContextMenu contextMenu) {
this.rowContextMenu = contextMenu ;
setRowFactory(r -> new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(rowContextMenu);
}
}
});
}
// ...
}
甚至
public class MyTableView<T> extends TableView<T> {
public MyTableView() {
contextMenuProperty().addListener((obs, oldContextMenu, newContextMenu) -> {
if (newContextMenu == null) {
setRowFactory(r -> new TableRow<>());
} else
setRowFactory(r -> new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(newContextMenu);
}
}
});
}
});
}
// ...
}
我有这个超级 class 扩展 TableView
,我想制作的每个 table 都应该继承自。
这行代码需要为每个继承自 superclass 并需要 ContextMenu
:
// Sets the context menu for each specific row. This way no
// context menu will appear if we click on a row that is
// empty.
setRowFactory(r -> {
TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(contextMenu);
}
}
};
});
问题是 ContextMenu
需要在这段代码执行之前实例化,因此我不能放入超级 class.
如果 table 需要 ContextMenu
(不总是案例):
- 用
MenuItem
个实例实例化ContextMenu
(我想MenuItem
个实例理论上可以在以后实例化和添加)。 - 使用在步骤 1 中实例化的上下文菜单调用上面的 "setRowFactory" 代码。
我已经多次尝试解决这个问题,但仍然没有找到令人满意的解决方案。也许我遗漏了一些明显的东西。
编辑: 如果您能以某种方式禁止用户使用 TableView
的原始 setContextMenu
方法以确保 `ContextMenu 是完美的以正确的方式添加。但我想这是不可能的。
看起来您只是想禁止在 table 中的空行上显示上下文菜单。更简单的方法是
public class MyTableView<T> extends TableView<T> {
public MyTableView() {
setRowFactory(tv -> {
TableRow<T> row = new TableRow<>();
row.setOnContextMenuRequested(e -> {
if (row.isEmpty()) {
e.consume();
}
}
return row ;
});
}
// ...
}
回答您提出的问题(确保您只(且始终)在致电 setContextMenu
后致电 setRowFactory
):
你可以做
public class MyTableView<T> extends TableView<T> {
private final ContextMenu contextMenu ;
public MyTableView(ContextMenu contextMenu) {
this.contextMenu = contextMenu ;
setRowFactory(r -> {
TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(contextMenu);
}
}
};
});
}
// ...
}
或
public class MyTableView<T> extends TableView<T> {
private ContextMenu rowContextMenu ;
public ContextMenu getRowContextMenu() {
return rowContextMenu ;
}
public void setRowContextMenu(ContextMenu contextMenu) {
this.rowContextMenu = contextMenu ;
setRowFactory(r -> new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(rowContextMenu);
}
}
});
}
// ...
}
甚至
public class MyTableView<T> extends TableView<T> {
public MyTableView() {
contextMenuProperty().addListener((obs, oldContextMenu, newContextMenu) -> {
if (newContextMenu == null) {
setRowFactory(r -> new TableRow<>());
} else
setRowFactory(r -> new TableRow<ObservableList<String>>() {
public void updateItem(ObservableList<String> item, boolean empty) {
super.updateItem(item, empty);
if (isEmpty()) {
setContextMenu(null);
} else {
setContextMenu(newContextMenu);
}
}
});
}
});
}
// ...
}