您的位置:首页 > 编程语言 > Java开发

JavaFX初探(菜单)

2015-02-12 11:49 162 查看

JavaFX初探(菜单)

本节我们介绍如何创建菜单、菜单栏、增加菜单项、为菜单分类,创建子菜单、设置菜单上下文。你可以使用下面的类来创建菜单。

MenuBar

MenuItem

Menu

CheckMenuItem

RadioMenuItem

CustomMenuItem

SeparatorMenuItem

ContextMenu

下图是一个典型的菜单的使用:



在应用中构建菜单

一个菜单就是一系列可操作的项目,可以根据用户的需要来表现。当一个菜单可见的时候,用户可以在某一时刻选中其中一个,在用户选中某一项时,这个菜单变成隐藏模式。通过使用菜单,我们可以节省用户界面的空间,因为有一些功能某些时间并不是总要现实出来的。

菜单在菜单栏中被分组,你需要使用下面的菜单项类,当你构建一个菜单的时候。

MenuItem 创建可选项

Menu 创建子菜单

RadioButtonItem 创建一个单选项

CheckMenuItem 这个菜单项可以在选择被无选择之间转换。

为了给菜单分类,可以使用SeparatorMenuItem 类。

菜单通常在窗口的顶部,并且这些菜单是隐藏的,我们可以通过鼠标点击上下文来打开菜单。

创建菜单栏

尽管菜单栏可以放在用户界面的任何地方,但是一般情况我们放到窗口的顶部。并且菜单栏可已自动的改变自己的大小。默认情况下,每一个菜单栏中的菜单像一个按钮一样呈现出来。

想想一个这样的一个应用,他显示植物的名称,图片,以及简单的描述信息。我们创建3个菜单项,:File,Edit,View.并给这三项添加菜单项。代码如下所示:

import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Effect;
import javafx.scene.effect.Glow;
import javafx.scene.effect.SepiaTone;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MenuSample extends Application {

    final PageData[] pages = new PageData[] {
        new PageData("Apple",
            "The apple is the pomaceous fruit of the apple tree, species Malus "
            + "domestica in the rose family (Rosaceae). It is one of the most "
            + "widely cultivated tree fruits, and the most widely known of "
            + "the many members of genus Malus that are used by humans. "
            + "The tree originated in Western Asia, where its wild ancestor, "
            + "the Alma, is still found today.",
            "Malus domestica"),
        new PageData("Hawthorn",
            "The hawthorn is a large genus of shrubs and trees in the rose "
            + "family, Rosaceae, native to temperate regions of the Northern "
            + "Hemisphere in Europe, Asia and North America. "
            + "The name hawthorn was "
            + "originally applied to the species native to northern Europe, "
            + "especially the Common Hawthorn C. monogyna, and the unmodified "
            + "name is often so used in Britain and Ireland.",
            "Crataegus monogyna"),
        new PageData("Ivy",
            "The ivy is a flowering plant in the grape family (Vitaceae) native to"
            + " eastern Asia in Japan, Korea, and northern and eastern China. "
            + "It is a deciduous woody vine growing to 30 m tall or more given "
            + "suitable support,  attaching itself by means of numerous small "
            + "branched tendrils tipped with sticky disks.",
            "Parthenocissus tricuspidata"),
        new PageData("Quince",
            "The quince is the sole member of the genus Cydonia and is native to "
            + "warm-temperate southwest Asia in the Caucasus region. The "
            + "immature fruit is green with dense grey-white pubescence, most "
            + "of which rubs off before maturity in late autumn when the fruit "
            + "changes color to yellow with hard, strongly perfumed flesh.",
            "Cydonia oblonga")
    };

    final String[] viewOptions = new String[] {
        "Title", 
        "Binomial name", 
        "Picture", 
        "Description"
    };

    final Entry<String, Effect>[] effects = new Entry[] {
        new SimpleEntry<>("Sepia Tone", new SepiaTone()),
        new SimpleEntry<>("Glow", new Glow()),
        new SimpleEntry<>("Shadow", new DropShadow())
    };

    final ImageView pic = new ImageView();
    final Label name = new Label();
    final Label binName = new Label();
    final Label description = new Label();

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        stage.setTitle("Menu Sample");
        Scene scene = new Scene(new VBox(), 400, 350);

        MenuBar menuBar = new MenuBar();

        // --- Menu File
        Menu menuFile = new Menu("File");

        // --- Menu Edit
        Menu menuEdit = new Menu("Edit");

        // --- Menu View
        Menu menuView = new Menu("View");

        menuBar.getMenus().addAll(menuFile, menuEdit, menuView);

        ((VBox) scene.getRoot()).getChildren().addAll(menuBar);

        stage.setScene(scene);
        stage.show();
    }

    private class PageData {
        public String name;
        public String description;
        public String binNames;
        public Image image;
        public PageData(String name, String description, String binNames) {
            this.name = name;
            this.description = description;
            this.binNames = binNames;
            image = new Image(getClass().getResourceAsStream(name + ".jpg"));
        }
    }
}


和其他的UI控件不同,Menu类和其他的扩展MenuItem的类都不是扩展自Node类。所以他们不能直接添加到场景中,需要先添加到MenuBar中然后在添加到场景中。运行如下图所示:




你可以使用键盘的方向键来浏览菜单,然而当你选中一个菜单的时候,什么都没有发生,那是因为我们还没有指定行为。

添加菜单项

为文件菜单添加功能。

Shuffle 加载植物的参考信息

Clear 删除参考信息并清空场景

Separator 分离菜单项

Exit 退出应用

使用MenuItem创建了一个Shuffle菜单,并添加了一个图片组件。我们可以为MenuItem指定文本和图片。我们可以通过setAction方法来指定该菜单被点击时候的事件,这个Button是一样的。代码如下:

import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Effect;
import javafx.scene.effect.Glow;
import javafx.scene.effect.SepiaTone;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;

public class MenuSample extends Application {

    final PageData[] pages = new PageData[] {
        new PageData("Apple",
            "The apple is the pomaceous fruit of the apple tree, species Malus "
            +"domestica in the rose family (Rosaceae). It is one of the most "
            +"widely cultivated tree fruits, and the most widely known of "
            +"the many members of genus Malus that are used by humans. "
            +"The tree originated in Western Asia, where its wild ancestor, "
            +"the Alma, is still found today.",
            "Malus domestica"),
        new PageData("Hawthorn",
            "The hawthorn is a large genus of shrubs and trees in the rose "
            + "family, Rosaceae, native to temperate regions of the Northern "
            + "Hemisphere in Europe, Asia and North America. "
            + "The name hawthorn was "
            + "originally applied to the species native to northern Europe, "
            + "especially the Common Hawthorn C. monogyna, and the unmodified "
            + "name is often so used in Britain and Ireland.",
            "Crataegus monogyna"),
        new PageData("Ivy",
            "The ivy is a flowering plant in the grape family (Vitaceae) native"
            +" to eastern Asia in Japan, Korea, and northern and eastern China."
            +" It is a deciduous woody vine growing to 30 m tall or more given "
            +"suitable support,  attaching itself by means of numerous small "
            +"branched tendrils tipped with sticky disks.",
            "Parthenocissus tricuspidata"),
        new PageData("Quince",
            "The quince is the sole member of the genus Cydonia and is native"
            +" to warm-temperate southwest Asia in the Caucasus region. The "
            +"immature fruit is green with dense grey-white pubescence, most "
            +"of which rubs off before maturity in late autumn when the fruit "
            +"changes color to yellow with hard, strongly perfumed flesh.",
            "Cydonia oblonga")
    };

    final String[] viewOptions = new String[] {
        "Title", 
        "Binomial name", 
        "Picture", 
        "Description"
    };

    final Entry<String, Effect>[] effects = new Entry[] {
        new SimpleEntry<>("Sepia Tone", new SepiaTone()),
        new SimpleEntry<>("Glow", new Glow()),
        new SimpleEntry<>("Shadow", new DropShadow())
    };

    final ImageView pic = new ImageView();
    final Label name = new Label();
    final Label binName = new Label();
    final Label description = new Label();
    private int currentIndex = -1;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        stage.setTitle("Menu Sample");
        Scene scene = new Scene(new VBox(), 400, 350);
        scene.setFill(Color.OLDLACE);

        name.setFont(new Font("Verdana Bold", 22));
        binName.setFont(new Font("Arial Italic", 10));
        pic.setFitHeight(150);
        pic.setPreserveRatio(true);
        description.setWrapText(true);
        description.setTextAlignment(TextAlignment.JUSTIFY);

        shuffle();

        MenuBar menuBar = new MenuBar();

        final VBox vbox = new VBox();
        vbox.setAlignment(Pos.CENTER);
        vbox.setSpacing(10);
        vbox.setPadding(new Insets(0, 10, 0, 10));
        vbox.getChildren().addAll(name, binName, pic, description);

        // --- Menu File
        Menu menuFile = new Menu("File");
        MenuItem add = new MenuItem("Shuffle",
            new ImageView(new Image("menusample/new.png")));
        add.setOnAction((ActionEvent t) -> {
            shuffle();
            vbox.setVisible(true);
        });        

        menuFile.getItems().addAll(add);

        // --- Menu Edit
        Menu menuEdit = new Menu("Edit");

        // --- Menu View
        Menu menuView = new Menu("View");

        menuBar.getMenus().addAll(menuFile, menuEdit, menuView);
        ((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);
        stage.setScene(scene);
        stage.show();
    }

    private void shuffle() {
        int i = currentIndex;
        while (i == currentIndex) {
            i = (int) (Math.random() * pages.length);
        }
        pic.setImage(pages[i].image);
        name.setText(pages[i].name);
        binName.setText("(" + pages[i].binNames + ")");
        description.setText(pages[i].description);
        currentIndex = i;
    }

    private class PageData {
        public String name;
        public String description;
        public String binNames;
        public Image image;
        public PageData(String name, String description, String binNames) {
            this.name = name;
            this.description = description;
            this.binNames = binNames;
            image = new Image(getClass().getResourceAsStream(name + ".jpg"));
        }
    }
}


当用户选择Shuffle菜单的时候,会就调用我们指定的setOnAction方法,显示出植物的名字、图片和简单描述。

Clear菜单用来抹除场景中的内容。我们可以使用下面的方法:

MenuItem clear = new MenuItem("Clear");
clear.setAccelerator(KeyCombination.keyCombination("Ctrl+X"));
clear.setOnAction((ActionEvent t) -> {
    vbox.setVisible(false);
});


Exit菜单实现如下:

MenuItem exit = new MenuItem("Exit");
exit.setOnAction((ActionEvent t) -> {
    System.exit(0);
});


我们使用getItems方法来添加这些菜单项,如下:

menuFile.getItems().addAll(add, clear, new SeparatorMenuItem(), exit);


编译运行应用,如下图所示:




View菜单可以来用指定,显示植物的部分信息,

// --- Creating four check menu items within the start method
CheckMenuItem titleView = createMenuItem ("Title", name);                                                       
CheckMenuItem binNameView = createMenuItem ("Binomial name", binName);        
CheckMenuItem picView = createMenuItem ("Picture", pic);        
CheckMenuItem descriptionView = createMenuItem ("Description", description);     
menuView.getItems().addAll(titleView, binNameView, picView, descriptionView);

...

// The createMenuItem method
private static CheckMenuItem createMenuItem (String title, final Node node){
    CheckMenuItem cmi = new CheckMenuItem(title);
    cmi.setSelected(true);
    cmi.selectedProperty().addListener(
        (ObservableValue<? extends Boolean> ov, Boolean old_val, 
        Boolean new_val) -> {
            node.setVisible(new_val);
    });              
    return cmi;
}


CheckMenuItem 是MenuItem类的扩展,他可以选中和非选中,如果被选中了,会显示出一个标记。编译运行如下图所示:



创建子菜单

Edit菜单中定义了两个菜单项:图片效果和无效果。图片效果菜单项有子菜单项。

使用RadioMenuItem 来创建子菜单,代码如下:

//Picture Effect menu
Menu menuEffect = new Menu("Picture Effect");
final ToggleGroup groupEffect = new ToggleGroup();
for (Entry<String, Effect> effect : effects) {
    RadioMenuItem itemEffect = new RadioMenuItem(effect.getKey());
    itemEffect.setUserData(effect.getValue());
    itemEffect.setToggleGroup(groupEffect);
    menuEffect.getItems().add(itemEffect);
}
//No Effects menu
final MenuItem noEffects = new MenuItem("No Effects");

noEffects.setOnAction((ActionEvent t) -> {
    pic.setEffect(null);
    groupEffect.getSelectedToggle().setSelected(false);
});

//Processing menu item selection
groupEffect.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {
    public void changed(ObservableValue<? extends Toggle> ov,
        Toggle old_toggle, Toggle new_toggle) {
            if (groupEffect.getSelectedToggle() != null) {
                Effect effect = 
                    (Effect) groupEffect.getSelectedToggle().getUserData();
                pic.setEffect(effect);
            }
        }
 });
groupEffect.selectedToggleProperty().addListener(
    (ObservableValue<? extends Toggle> ov, Toggle old_toggle, 
    Toggle new_toggle) -> {
        if (groupEffect.getSelectedToggle() != null) {
             Effect effect = 
                 (Effect) groupEffect.getSelectedToggle().getUserData();
             pic.setEffect(effect);
        }
});

//Adding items to the Edit menu
menuEdit.getItems().addAll(menuEffect, noEffects);


如下所示:




我们可以使用setDisable来禁用某一个菜单。

Menu menuEffect = new Menu("Picture Effect");
final ToggleGroup groupEffect = new ToggleGroup();
for (Entry<String, Effect> effect : effects) {
     RadioMenuItem itemEffect = new RadioMenuItem(effect.getKey());
     itemEffect.setUserData(effect.getValue());
     itemEffect.setToggleGroup(groupEffect);
     menuEffect.getItems().add(itemEffect);
}
final MenuItem noEffects = new MenuItem("No Effects");
noEffects.setDisable(true);
noEffects.setOnAction((ActionEvent t) -> {
    pic.setEffect(null);
    groupEffect.getSelectedToggle().setSelected(false);
    noEffects.setDisable(true);
});

groupEffect.selectedToggleProperty().addListener(
    (ObservableValue<? extends Toggle> ov, Toggle old_toggle, 
    Toggle new_toggle) -> {
        if (groupEffect.getSelectedToggle() != null) {
            Effect effect = 
                (Effect) groupEffect.getSelectedToggle().getUserData();
            pic.setEffect(effect);
            noEffects.setDisable(false);
        } else {
                noEffects.setDisable(true);
            }
});

menuEdit.getItems().addAll(menuEffect, noEffects);




添加上下文菜单

如果你的界面中没有为菜单的控件,那么你可以使用上下文菜单。当点击鼠标的时候,弹出上下文菜单。

final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = new MenuItem("Copy Image");
cmItem1.setOnAction((ActionEvent e) -> {
    Clipboard clipboard = Clipboard.getSystemClipboard();
    ClipboardContent content = new ClipboardContent();
    content.putImage(pic.getImage());
    clipboard.setContent(content);
});

cm.getItems().add(cmItem1);
pic.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
    if (e.getButton() == MouseButton.SECONDARY)
       cm.show(pic, e.getScreenX(), e.getScreenY());
});


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: