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

时间:2016-07-26 11:43:17

标签: java javafx imageview icons

我需要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以查看是否为当前项目设置了图形。 控制台中的结果:两行(MenuItem)具有相同的ImageView

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

我在Swing中完成了相同的操作(但使用Icons.setIcons()功能)并且效果非常好。我也寻找一个“重绘”功能来强制显示,但没办法。

希望你能帮助我!

1 个答案:

答案 0 :(得分:3)

这是因为同一个Node无法多次附加到场景图上,而且 - 正如您所说的那样 - 您正在添加相同的ImageView对象。

来自documentation of Node

  

如果程序将子节点添加到父节点(包括组,区域,   等)并且该节点已经是不同父节点或子节点的子节点   在场景的根,自动(并静默)删除节点   它的前任父母。

解决方案是修改getImage的{​​{1}}方法,以便在每次调用时返回新的IconFactory实例,或返回ImageView个实例而不是Image个实例(第二个更适合我想的“IconFactory”这个名字。)

您可以存储ImageView实例,而不是存储Image,以避免重新加载ImageView本身。您可以将此问题视为参考:Reusing same ImageView multiple times in the same scene on JavaFX

Image的可能更新:

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);
    }
}