来自字符串列表的 ContextMenu 子菜单
ContextMenu sub-menus from a List of Strings
我正在尝试制作一个类似于下图中的上下文菜单:
我想显示其中一个组中的字符串列表。
这可以通过使用 controlsFX 库中的 ActionGroup 来实现。为了重现图片中的示例,请使用该代码:
public class HelloActionGroup{
Label label = new Label("hello world, I'm a label");
label.setContextMenu(ActionUtils.createContextMenu(action));
private Collection<? extends Action> action = Arrays.asList(
new ActionGroup("Group 1", new DummyAction("Action 1")),
new DummyAction("Action 2"),
new DummyAction("Action 3"))
);
private static class DummyAction extends Action{
public DummyAction(String name){
super(name);
}
}
}
为了在您的代码中制作该代码 运行,只需将该标签放在您的根父级中:
yourPaneName.getChildren().add(label);
如您所见,我必须对“第 1 组”中显示的所有项目进行硬编码,即“Action1”、“Action2”和“Action3”。如何在“第 1 组”中放置一个字符串列表?
类似于:
List<String> list = new ArrayList<>();
list.add("Action1");
list.add("Action2");
list.add("Action3");
private Collection<? extends Action> action = Arrays.asList(
new ActionGroup("Group 1", new DummyAction(list)));
更新:使用循环在上下文菜单中插入列表项,设法真正接近:
List<String> list = new ArrayList<>();
list.add("string1");
list.add("string2");
for (String str: list) {
action2.add(new ActionGroup("action1",new DummyAction(str)));
}
结果:
string2 显示在所选 (action1)
下方
我知道它正在创建多个 ActionGroup 因为语句“new ActionGroup”,现在我只需要找到一种方法来只创建一个 ActionGroup 并向其中添加多个 DummyAction(strings from list)
菜单只是一种 MenuItem,所以只要可以放置 MenuItem,就可以放置 Menu,而 Menu 又可以有子菜单项。
就 ControlsFX 控件而言,我不知道它们,因为我不使用它们。但是对于您所描述的问题,我看不出需要它们。如果在您的应用程序中,您确实需要使用 ControlsFX 来实现其他功能,也许您可以调整此解决方案中的信息来实现这一点。
例子
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.stream.IntStream;
public class SubContext extends Application {
private static final int N_ITEMS_PER_MENU = 5;
@Override
public void start(Stage stage) {
MenuGenerator menuGenerator = new MenuGenerator();
Menu[] contextTopicMenus = menuGenerator.generateMenus(
N_ITEMS_PER_MENU
);
for (Menu menu: contextTopicMenus) {
menu.getItems().setAll(
menuGenerator.generateMenuItems(
N_ITEMS_PER_MENU
)
);
}
ContextMenu contextMenu = new ContextMenu(contextTopicMenus);
Label label = new Label("Click for context");
label.setContextMenu(contextMenu);
Pane layout = new VBox(label);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
private static final class MenuGenerator {
private final Lorem lorem = new Lorem();
public Menu generateMenu() {
return new Menu(lorem.nextString());
}
public MenuItem generateMenuItem() {
return new MenuItem(lorem.nextString());
}
public Menu[] generateMenus(int n) {
return IntStream.range(0, n)
.mapToObj(i -> generateMenu())
.toArray(Menu[]::new);
}
public MenuItem[] generateMenuItems(int n) {
return IntStream.range(0, n)
.mapToObj(i -> generateMenuItem())
.toArray(MenuItem[]::new);
}
}
private static final class Lorem {
private static final String[] lorem = "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua".split(" ");
private int idx = 0;
public String nextString() {
return lorem[getAndIncrementIdx()];
}
private int getAndIncrementIdx() {
int retVal = idx;
idx = (idx + 1) % lorem.length;
return retVal;
}
}
public static void main(String[] args) {
Application.launch(args);
}
}
示例中花哨的菜单生成器和 lorem 只是为了便于数据生成。对于您的实际应用程序,您不需要它,相反,您将创建适用的菜单、菜单项及其适当的操作函数并使用它们而不是生成的。
首先,创建一个ActionGroup的集合,然后从同类型的集合(ActionGroup)中创建一个单独的实例。之后,运行 一个循环,以便将列表中的每个项目插入到 ActionGroup 实例中。它是这样的:
Collection<ActionGroup> action = new LinkedList<>();
ActionGroup actionGroup = new ActionGroup("My list items:");
List<String> list = new ArrayList<>();
list.add("string 1");
list.add("string 2");
list.add("string 3");
for (String str : list) {
actionGroup.getActions().add(new DummyAction(str));
}
action.add(actionGroup);
node.setContextMenu(ActionUtils.createContextMenu(action));
结果:
我正在尝试制作一个类似于下图中的上下文菜单:
我想显示其中一个组中的字符串列表。
这可以通过使用 controlsFX 库中的 ActionGroup 来实现。为了重现图片中的示例,请使用该代码:
public class HelloActionGroup{
Label label = new Label("hello world, I'm a label");
label.setContextMenu(ActionUtils.createContextMenu(action));
private Collection<? extends Action> action = Arrays.asList(
new ActionGroup("Group 1", new DummyAction("Action 1")),
new DummyAction("Action 2"),
new DummyAction("Action 3"))
);
private static class DummyAction extends Action{
public DummyAction(String name){
super(name);
}
}
}
为了在您的代码中制作该代码 运行,只需将该标签放在您的根父级中:
yourPaneName.getChildren().add(label);
如您所见,我必须对“第 1 组”中显示的所有项目进行硬编码,即“Action1”、“Action2”和“Action3”。如何在“第 1 组”中放置一个字符串列表?
类似于:
List<String> list = new ArrayList<>();
list.add("Action1");
list.add("Action2");
list.add("Action3");
private Collection<? extends Action> action = Arrays.asList(
new ActionGroup("Group 1", new DummyAction(list)));
更新:使用循环在上下文菜单中插入列表项,设法真正接近:
List<String> list = new ArrayList<>();
list.add("string1");
list.add("string2");
for (String str: list) {
action2.add(new ActionGroup("action1",new DummyAction(str)));
}
结果:
我知道它正在创建多个 ActionGroup 因为语句“new ActionGroup”,现在我只需要找到一种方法来只创建一个 ActionGroup 并向其中添加多个 DummyAction(strings from list)
菜单只是一种 MenuItem,所以只要可以放置 MenuItem,就可以放置 Menu,而 Menu 又可以有子菜单项。
就 ControlsFX 控件而言,我不知道它们,因为我不使用它们。但是对于您所描述的问题,我看不出需要它们。如果在您的应用程序中,您确实需要使用 ControlsFX 来实现其他功能,也许您可以调整此解决方案中的信息来实现这一点。
例子
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.stream.IntStream;
public class SubContext extends Application {
private static final int N_ITEMS_PER_MENU = 5;
@Override
public void start(Stage stage) {
MenuGenerator menuGenerator = new MenuGenerator();
Menu[] contextTopicMenus = menuGenerator.generateMenus(
N_ITEMS_PER_MENU
);
for (Menu menu: contextTopicMenus) {
menu.getItems().setAll(
menuGenerator.generateMenuItems(
N_ITEMS_PER_MENU
)
);
}
ContextMenu contextMenu = new ContextMenu(contextTopicMenus);
Label label = new Label("Click for context");
label.setContextMenu(contextMenu);
Pane layout = new VBox(label);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
private static final class MenuGenerator {
private final Lorem lorem = new Lorem();
public Menu generateMenu() {
return new Menu(lorem.nextString());
}
public MenuItem generateMenuItem() {
return new MenuItem(lorem.nextString());
}
public Menu[] generateMenus(int n) {
return IntStream.range(0, n)
.mapToObj(i -> generateMenu())
.toArray(Menu[]::new);
}
public MenuItem[] generateMenuItems(int n) {
return IntStream.range(0, n)
.mapToObj(i -> generateMenuItem())
.toArray(MenuItem[]::new);
}
}
private static final class Lorem {
private static final String[] lorem = "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua".split(" ");
private int idx = 0;
public String nextString() {
return lorem[getAndIncrementIdx()];
}
private int getAndIncrementIdx() {
int retVal = idx;
idx = (idx + 1) % lorem.length;
return retVal;
}
}
public static void main(String[] args) {
Application.launch(args);
}
}
示例中花哨的菜单生成器和 lorem 只是为了便于数据生成。对于您的实际应用程序,您不需要它,相反,您将创建适用的菜单、菜单项及其适当的操作函数并使用它们而不是生成的。
首先,创建一个ActionGroup的集合,然后从同类型的集合(ActionGroup)中创建一个单独的实例。之后,运行 一个循环,以便将列表中的每个项目插入到 ActionGroup 实例中。它是这样的:
Collection<ActionGroup> action = new LinkedList<>();
ActionGroup actionGroup = new ActionGroup("My list items:");
List<String> list = new ArrayList<>();
list.add("string 1");
list.add("string 2");
list.add("string 3");
for (String str : list) {
actionGroup.getActions().add(new DummyAction(str));
}
action.add(actionGroup);
node.setContextMenu(ActionUtils.createContextMenu(action));
结果: