JavaFX setGraphic()未在MenuItem中显示图标



我需要一个MenuItem的图标。

这就像一个"工人类"来获得图标的ImageView

public class IconFactory {
private static ImageView HLP_BOOK_JFX;
public enum ICONS {
    BASCET_REMOVE, BASCET_PUT, SAVE, OPEN, ARROW_RIGHT, ARROW_LEFT, ARROW_UP, ARROW_DOWN, CLOCK, ANALOG_SIGNAL, DIGITAL_SIGNAL, REFRESH, GREEN_PLUS, NETWORK, OK, CANCEL, RIGHT_NAV2, LEFT_NAV2, PLAY, PAUSE, LIST_ADD, PAGE_FIND, SET_PARAM, DOWNLOAD, UPLOAD, LOG_FILE, WARNING, INFO, LOG_DIAG, DATA_TRANS, TREE, FILTER, SEARCH, PARAM, ERASE, RESETDEF, RESETDEF2, DEBUG_BUG, INTERNATIONAL, CLOSE, HLP_BOOK
}
public static ImageView getImage(ICONS en) {
    switch (en) {
        case HLP_BOOK:
            if (HLP_BOOK_JFX == null)
                HLP_BOOK_JFX = new ImageView(new Image(IconFactory.class.getResourceAsStream("help_book.png")));
            return HLP_BOOK_JFX;
    }
    return null;
}

当我将myMenuItem.setGraphic(IconFactory.getImage(ICONS.HLP_BOOK))用于单个菜单项时,它非常有效

但是,当我想在一个循环中生成两个菜单并设置相同的图形时,一个MenuItem没有显示图标(下面代码中循环中的第一个)。


我的代码:

while (keys.hasMoreElements()) {
    // that will do 2 loops, do not care about how
    MenuItem subMenuHelp = new MenuItem("MenuItem");
    subMenuHelp.setGraphic(IconFactory.getImage(ICONS.HLP_BOOK));
    subMenuHelp.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                // do not care
                openHelpFile(link);
            }
    });
        System.out.println(((ImageView) subMenuHelp.getGraphic()).toString());
        myMenu.getItems().add(subMenuHelp);
}

正如您所看到的,我添加了一个System.out.println来查看是否为当前项目设置了图形。控制台中的结果:具有相同ImageView:的两行(MenuItem)

ImageView@79814766[styleClass=image-view]
ImageView@79814766[styleClass=image-view]

我在Swing中做了完全相同的操作(但使用了Icons.setIcons()函数),它运行得非常好。我还寻找了一个"重新绘制"功能来强制显示,但没有办法。

希望你能帮助我!

这是因为同一个Node不能多次附加到场景图,而且正如您所说,您添加的是同一ImageView对象。

来自Node的文档:

如果程序将子节点添加到父节点(包括组、区域等),等等),并且该节点已经是不同Parent或场景的根,节点会自动(并且静默地)从其前母公司。

解决方案是修改IconFactorygetImage方法,在每次调用时返回一个新的ImageView实例,或者返回Image实例而不是ImageView实例(我认为第二个更适合"IconFactory"这个名称)。

您可以存储Image实例,而不是存储ImageView,以避免重新加载Image本身。您可以将此问题作为参考:在JavaFX 上的同一场景中多次重复使用同一ImageView

IconFactory的可能更新:

public class IconFactory {
    private static HashMap<ICON, Image> images = new HashMap<ICON, Image>();
    public enum ICON {
        BASCET_REMOVE, BASCET_PUT, SAVE, OPEN, ARROW_RIGHT, ARROW_LEFT, ARROW_UP, ARROW_DOWN, CLOCK, ANALOG_SIGNAL, DIGITAL_SIGNAL, REFRESH, GREEN_PLUS, NETWORK, OK, CANCEL, RIGHT_NAV2, LEFT_NAV2, PLAY, PAUSE, LIST_ADD, PAGE_FIND, SET_PARAM, DOWNLOAD, UPLOAD, LOG_FILE, WARNING, INFO, LOG_DIAG, DATA_TRANS, TREE, FILTER, SEARCH, PARAM, ERASE, RESETDEF, RESETDEF2, DEBUG_BUG, INTERNATIONAL, CLOSE, HLP_BOOK
    }
    public static Image getImage(ICON en) {
        if (!images.containsKey(en)) {
            switch (en) {
            case HLP_BOOK:
                images.put(en, new Image(IconFactory.class.getResourceAsStream("help_book.png"))); break;
            default:
                return null;
            }
        }
        return images.get(en);
    }
}

更新后的使用:

subMenuHelp.setGraphic(new ImageView(IconFactory.getImage(ICONS.HLP_BOOK)));

最新更新