热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javafx菜单_DOC0324菜单(Menu)

DOC-03-24菜单(Menu)本章将介绍如何创建菜单(Menu)和菜单栏(MenuBar),添加菜单项(MenuItem),将菜单分组,

DOC-03-24 菜单(Menu)

本章将介绍如何创建菜单(Menu)和菜单栏(Menu Bar),添加菜单项(Menu Item),将菜单分组,创建子菜单(Submenu),以及设置上下文菜单(Context Menu)。

你可以使用下面这些JavaFX API中的类来在你的应用程序中构建菜单。

· MenuBar

· MenuItem

· Menu

· CheckMenuItem

· RadioMenuItem

· Menu

· CustomMenuItem

· SeparatorMenuItem

· ContextMenu

图24-1显示了一个包含典型菜单栏的应用程序。

图24-1包含菜单栏和三个菜单分类的应用程序

4db4ac3ad26bb28f025f263e6ba66d33.png

在JavaFX应用程序中构建菜单

一个菜单是一系列可以根据用户的需要进行显示的可响应事件的菜单项。当一个菜单可见时,用户一次可以选择一个菜单项。当用户点击一个菜单项后,菜单就会回到隐藏模式。通过使用菜单,你将一些不需要始终显示的功能放在其中,这样可以节省你的应用程序UI空间。

菜单栏中的菜单通常会分组到不同类别中。编码模式是定义一个菜单栏,定义一些分类菜单,为分类菜单填充菜单项。当在你的JavaFX应用程序中构建菜单时,使用下面的菜单项类。

· MenuItem – 创建一个可响应事件的选项

· Menu – 创建一个子菜单

· RadioButtonItem – 创建一个相互排斥的选项

· CheckMenuItem – 创建一个可在选中和非选中状态切换的选项

在一个分类中对菜单项进行分隔,使用SeparatorMenuItem类。

对于分类组织在菜单栏中的菜单一般位于窗口的上方,scene中其余的空间留给那些重要的控件。基于某种原因,如果你不想在你的UI中为菜单栏分配任何可见空间,你可以使用上下文菜单,它通过用户点击鼠标打开。

创建菜单栏

尽管菜单栏可以被放置在UI的任何其他地方,但是菜单栏一般是位于UI的上方,而且它包含一个或者多个菜单。菜单栏会自动伸缩以适用应用程序窗口的宽度。默认情况下,每个添加到菜单栏的菜单是由带有文本的按钮表示的。

想象一个应用程序,它显示植物的参考信息,如名称,拉丁学名,图片,和简介。你可以创建三个分类菜单:File,Edit和View,然后为这些菜单填充菜单项。例24-1展示了这样一个带有菜单栏的应用程序的源代码。

例24-1 Menu Sample应用程序

Java

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[] effects = new Entry[] {

new SimpleEntry<>("Sepia Tone", new SepiaTone()),

new SimpleEntry<>("Glow", new Glow()),

new SimpleEntry<>("Shadow", new DropShadow())

};

final ImageView pic &#61; new ImageView();

final Label name &#61; new Label();

final Label binName &#61; new Label();

final Label description &#61; new Label();

public static void main(String[] args) {

launch(args);

}

&#64;Override

public void start(Stage stage) {

stage.setTitle("Menu Sample");

Scene scene &#61; new Scene(new VBox(), 400, 350);

MenuBar menuBar &#61; new MenuBar();

// --- Menu File

Menu menuFile &#61; new Menu("File");

// --- Menu Edit

Menu menuEdit &#61; new Menu("Edit");

// --- Menu View

Menu menuView &#61; 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 &#61; name;

this.description &#61; description;

this.binNames &#61; binNames;

image &#61; new Image(getClass().getResourceAsStream(name &#43; ".jpg"));

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

importjava.util.AbstractMap.SimpleEntry;

importjava.util.Map.Entry;

importjavafx.application.Application;

importjavafx.scene.Scene;

importjavafx.scene.control.*;

importjavafx.scene.effect.DropShadow;

importjavafx.scene.effect.Effect;

importjavafx.scene.effect.Glow;

importjavafx.scene.effect.SepiaTone;

importjavafx.scene.image.Image;

importjavafx.scene.image.ImageView;

importjavafx.scene.layout.VBox;

importjavafx.stage.Stage;

publicclassMenuSampleextendsApplication{

finalPageData[]pages&#61;newPageData[]{

newPageData("Apple",

"The apple is the pomaceous fruit of the apple tree, species Malus "

&#43;"domestica in the rose family (Rosaceae). It is one of the most "

&#43;"widely cultivated tree fruits, and the most widely known of "

&#43;"the many members of genus Malus that are used by humans. "

&#43;"The tree originated in Western Asia, where its wild ancestor, "

&#43;"the Alma, is still found today.",

"Malus domestica"),

newPageData("Hawthorn",

"The hawthorn is a large genus of shrubs and trees in the rose "

&#43;"family, Rosaceae, native to temperate regions of the Northern "

&#43;"Hemisphere in Europe, Asia and North America. "

&#43;"The name hawthorn was "

&#43;"originally applied to the species native to northern Europe, "

&#43;"especially the Common Hawthorn C. monogyna, and the unmodified "

&#43;"name is often so used in Britain and Ireland.",

"Crataegus monogyna"),

newPageData("Ivy",

"The ivy is a flowering plant in the grape family (Vitaceae) native to"

&#43;" eastern Asia in Japan, Korea, and northern and eastern China. "

&#43;"It is a deciduous woody vine growing to 30 m tall or more given "

&#43;"suitable support,  attaching itself by means of numerous small "

&#43;"branched tendrils tipped with sticky disks.",

"Parthenocissus tricuspidata"),

newPageData("Quince",

"The quince is the sole member of the genus Cydonia and is native to "

&#43;"warm-temperate southwest Asia in the Caucasus region. The "

&#43;"immature fruit is green with dense grey-white pubescence, most "

&#43;"of which rubs off before maturity in late autumn when the fruit "

&#43;"changes color to yellow with hard, strongly perfumed flesh.",

"Cydonia oblonga")

};

finalString[]viewOptions&#61;newString[]{

"Title",

"Binomial name",

"Picture",

"Description"

};

finalEntry[]effects&#61;newEntry[]{

newSimpleEntry<>("Sepia Tone",newSepiaTone()),

newSimpleEntry<>("Glow",newGlow()),

newSimpleEntry<>("Shadow",newDropShadow())

};

finalImageViewpic&#61;newImageView();

finalLabelname&#61;newLabel();

finalLabelbinName&#61;newLabel();

finalLabeldescription&#61;newLabel();

publicstaticvoidmain(String[]args){

launch(args);

}

&#64;Override

publicvoidstart(Stagestage){

stage.setTitle("Menu Sample");

Scenescene&#61;newScene(newVBox(),400,350);

MenuBarmenuBar&#61;newMenuBar();

// --- Menu File

MenumenuFile&#61;newMenu("File");

// --- Menu Edit

MenumenuEdit&#61;newMenu("Edit");

// --- Menu View

MenumenuView&#61;newMenu("View");

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

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

stage.setScene(scene);

stage.show();

}

privateclassPageData{

publicStringname;

publicStringdescription;

publicStringbinNames;

publicImageimage;

publicPageData(Stringname,Stringdescription,StringbinNames){

this.name&#61;name;

this.description&#61;description;

this.binNames&#61;binNames;

image&#61;newImage(getClass().getResourceAsStream(name&#43;".jpg"));

}

}

}

与其他UI控件不一样&#xff0c;Menu类和其他MenuItem的扩展类不是继承自Node类。他们不能直接添加到应用程序scene中&#xff0c;直到通过getMenus()方法添加到菜单栏中时才可见。

图24-2添加菜单栏到应用程序中

93676c13bd8956559943db4c57d3d6f6.png

你可以使用键盘上的箭头按键来浏览所有的菜单。但是&#xff0c;当你选择一个菜单时&#xff0c;没有动作被执行&#xff0c;因为菜单的行为还没有被定义。

添加菜单项

通过添加以下菜单项为File菜单设置功能&#xff1a;

· Shuffle – 加载植物的参考信息

· Clear – 移除参考信息并清除scene

· Separator – 分隔菜单项

· Exit – 退出应用程序

例24-2中粗体的行通过MenuItem类创建了一个Shuffle 菜单&#xff0c;并添加了一些图像组件到应用程序scene。MenuItem类允许使用文本和图像创建一个可响应事件的菜单项。在用户点击时执行的动作可以通过setOnAction方法来定义&#xff0c;这和Button类很相似。

例24-2添加带图像的Shuffle菜单项

Java

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 &#61; new PageData[] {

new PageData("Apple",

"The apple is the pomaceous fruit of the apple tree, species Malus "

&#43;"domestica in the rose family (Rosaceae). It is one of the most "

&#43;"widely cultivated tree fruits, and the most widely known of "

&#43;"the many members of genus Malus that are used by humans. "

&#43;"The tree originated in Western Asia, where its wild ancestor, "

&#43;"the Alma, is still found today.",

"Malus domestica"),

new PageData("Hawthorn",

"The hawthorn is a large genus of shrubs and trees in the rose "

&#43; "family, Rosaceae, native to temperate regions of the Northern "

&#43; "Hemisphere in Europe, Asia and North America. "

&#43; "The name hawthorn was "

&#43; "originally applied to the species native to northern Europe, "

&#43; "especially the Common Hawthorn C. monogyna, and the unmodified "

&#43; "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"

&#43;" to eastern Asia in Japan, Korea, and northern and eastern China."

&#43;" It is a deciduous woody vine growing to 30 m tall or more given "

&#43;"suitable support, attaching itself by means of numerous small "

&#43;"branched tendrils tipped with sticky disks.",

"Parthenocissus tricuspidata"),

new PageData("Quince",

"The quince is the sole member of the genus Cydonia and is native"

&#43;" to warm-temperate southwest Asia in the Caucasus region. The "

&#43;"immature fruit is green with dense grey-white pubescence, most "

&#43;"of which rubs off before maturity in late autumn when the fruit "

&#43;"changes color to yellow with hard, strongly perfumed flesh.",

"Cydonia oblonga")

};

final String[] viewOptions &#61; new String[] {

"Title",

"Binomial name",

"Picture",

"Description"

};

final Entry[] effects &#61; new Entry[] {

new SimpleEntry<>("Sepia Tone", new SepiaTone()),

new SimpleEntry<>("Glow", new Glow()),

new SimpleEntry<>("Shadow", new DropShadow())

};

final ImageView pic &#61; new ImageView();

final Label name &#61; new Label();

final Label binName &#61; new Label();

final Label description &#61; new Label();

private int currentIndex &#61; -1;

public static void main(String[] args) {

launch(args);

}

&#64;Override

public void start(Stage stage) {

stage.setTitle("Menu Sample");

Scene scene &#61; 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 &#61; new MenuBar();

final VBox vbox &#61; 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 &#61; new Menu("File");

MenuItem add &#61; 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 &#61; new Menu("Edit");

// --- Menu View

Menu menuView &#61; 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 &#61; currentIndex;

while (i &#61;&#61; currentIndex) {

i &#61; (int) (Math.random() * pages.length);

}

pic.setImage(pages[i].image);

name.setText(pages[i].name);

binName.setText("(" &#43; pages[i].binNames &#43; ")");

description.setText(pages[i].description);

currentIndex &#61; 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 &#61; name;

this.description &#61; description;

this.binNames &#61; binNames;

image &#61; new Image(getClass().getResourceAsStream(name &#43; ".jpg"));

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

importjava.util.AbstractMap.SimpleEntry;

importjava.util.Map.Entry;

importjavafx.application.Application;

importjavafx.event.ActionEvent;

importjavafx.geometry.Insets;

importjavafx.geometry.Pos;

importjavafx.scene.Scene;

importjavafx.scene.control.*;

importjavafx.scene.effect.DropShadow;

importjavafx.scene.effect.Effect;

importjavafx.scene.effect.Glow;

importjavafx.scene.effect.SepiaTone;

importjavafx.scene.image.Image;

importjavafx.scene.image.ImageView;

importjavafx.scene.layout.VBox;

importjavafx.scene.paint.Color;

importjavafx.scene.text.Font;

importjavafx.scene.text.TextAlignment;

importjavafx.stage.Stage;

publicclassMenuSampleextendsApplication{

finalPageData[]pages&#61;newPageData[]{

newPageData("Apple",

"The apple is the pomaceous fruit of the apple tree, species Malus "

&#43;"domestica in the rose family (Rosaceae). It is one of the most "

&#43;"widely cultivated tree fruits, and the most widely known of "

&#43;"the many members of genus Malus that are used by humans. "

&#43;"The tree originated in Western Asia, where its wild ancestor, "

&#43;"the Alma, is still found today.",

"Malus domestica"),

newPageData("Hawthorn",

"The hawthorn is a large genus of shrubs and trees in the rose "

&#43;"family, Rosaceae, native to temperate regions of the Northern "

&#43;"Hemisphere in Europe, Asia and North America. "

&#43;"The name hawthorn was "

&#43;"originally applied to the species native to northern Europe, "

&#43;"especially the Common Hawthorn C. monogyna, and the unmodified "

&#43;"name is often so used in Britain and Ireland.",

"Crataegus monogyna"),

newPageData("Ivy",

"The ivy is a flowering plant in the grape family (Vitaceae) native"

&#43;" to eastern Asia in Japan, Korea, and northern and eastern China."

&#43;" It is a deciduous woody vine growing to 30 m tall or more given "

&#43;"suitable support,  attaching itself by means of numerous small "

&#43;"branched tendrils tipped with sticky disks.",

"Parthenocissus tricuspidata"),

newPageData("Quince",

"The quince is the sole member of the genus Cydonia and is native"

&#43;" to warm-temperate southwest Asia in the Caucasus region. The "

&#43;"immature fruit is green with dense grey-white pubescence, most "

&#43;"of which rubs off before maturity in late autumn when the fruit "

&#43;"changes color to yellow with hard, strongly perfumed flesh.",

"Cydonia oblonga")

};

finalString[]viewOptions&#61;newString[]{

"Title",

"Binomial name",

"Picture",

"Description"

};

finalEntry[]effects&#61;newEntry[]{

newSimpleEntry<>("Sepia Tone",newSepiaTone()),

newSimpleEntry<>("Glow",newGlow()),

newSimpleEntry<>("Shadow",newDropShadow())

};

finalImageViewpic&#61;newImageView();

finalLabelname&#61;newLabel();

finalLabelbinName&#61;newLabel();

finalLabeldescription&#61;newLabel();

privateintcurrentIndex&#61;-1;

publicstaticvoidmain(String[]args){

launch(args);

}

&#64;Override

publicvoidstart(Stagestage){

stage.setTitle("Menu Sample");

Scenescene&#61;newScene(newVBox(),400,350);

scene.setFill(Color.OLDLACE);

name.setFont(newFont("Verdana Bold",22));

binName.setFont(newFont("Arial Italic",10));

pic.setFitHeight(150);

pic.setPreserveRatio(true);

description.setWrapText(true);

description.setTextAlignment(TextAlignment.JUSTIFY);

shuffle();

MenuBarmenuBar&#61;newMenuBar();

finalVBoxvbox&#61;newVBox();

vbox.setAlignment(Pos.CENTER);

vbox.setSpacing(10);

vbox.setPadding(newInsets(0,10,0,10));

vbox.getChildren().addAll(name,binName,pic,description);

// --- Menu File

MenumenuFile&#61;newMenu("File");

MenuItemadd&#61;newMenuItem("Shuffle",

newImageView(newImage("menusample/new.png")));

add.setOnAction((ActionEventt)->{

shuffle();

vbox.setVisible(true);

});

menuFile.getItems().addAll(add);

// --- Menu Edit

MenumenuEdit&#61;newMenu("Edit");

// --- Menu View

MenumenuView&#61;newMenu("View");

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

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

stage.setScene(scene);

stage.show();

}

privatevoidshuffle(){

inti&#61;currentIndex;

while(i&#61;&#61;currentIndex){

i&#61;(int)(Math.random()*pages.length);

}

pic.setImage(pages[i].image);

name.setText(pages[i].name);

binName.setText("("&#43;pages[i].binNames&#43;")");

description.setText(pages[i].description);

currentIndex&#61;i;

}

privateclassPageData{

publicStringname;

publicStringdescription;

publicStringbinNames;

publicImageimage;

publicPageData(Stringname,Stringdescription,StringbinNames){

this.name&#61;name;

this.description&#61;description;

this.binNames&#61;binNames;

image&#61;newImage(getClass().getResourceAsStream(name&#43;".jpg"));

}

}

}

当用户选中Shuffle菜单项时&#xff0c;setOnAction方法中指定的shuffle()方法就会被调用&#xff0c;它计算出的元素位置&#xff0c;然后从对应的数组中取值并设置标题&#xff0c;拉丁学名&#xff0c;植物图片和描述。

Clear菜单项用于清除应用程序scene的内容。你可以通过将包含GUI元素的VBox容器设置为不可见来实现此效果&#xff0c;见例24-3。

例24-3创建带快捷键的Clear菜单项

Java

MenuItem clear &#61; new MenuItem("Clear");

clear.setAccelerator(KeyCombination.keyCombination("Ctrl&#43;X"));

clear.setOnAction((ActionEvent t) -> {

vbox.setVisible(false);

});

1

2

3

4

5

MenuItemclear&#61;newMenuItem("Clear");

clear.setAccelerator(KeyCombination.keyCombination("Ctrl&#43;X"));

clear.setOnAction((ActionEventt)->{

vbox.setVisible(false);

});

MenuItem类的实现允许开发者设置一个菜单快捷键&#xff0c;这是一个组合键&#xff0c;能够执行和点击菜单项一样的动作。对于Clear菜单项&#xff0c;用户可以从File菜单中选择动作&#xff0c;也可以同时按下Ctrl和X键。

Exit菜单关闭应用程序窗口。例24-4中展示了为该菜单项设置System.exit(0)响应动作。

例24-4创建Exit菜单项

Java

MenuItem exit &#61; new MenuItem("Exit");

exit.setOnAction((ActionEvent t) -> {

System.exit(0);

});

1

2

3

4

MenuItemexit&#61;newMenuItem("Exit");

exit.setOnAction((ActionEventt)->{

System.exit(0);

});

使用getItems()方法来向File菜单中新增菜单项&#xff0c;见例24-5。你可以创建一个分隔菜单项&#xff0c;并通过getItems()方法将其添加进去&#xff0c;以将Exit菜单隔离开。

例24-5添加菜单项

Java

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

1

menuFile.getItems().addAll(add,clear,newSeparatorMenuItem(),exit);

将例24-2&#xff0c;24-3&#xff0c;24-4&#xff0c;24-5添加到Menu Sample应用程序中&#xff0c;编译并运行之。选择Shuffle菜单项来加载不同植物的参考信息。然后清除scene(Clear菜单项)&#xff0c;并关闭应用程序(Close菜单项)。图24-3显示了选中Clear菜单项的效果。

图24-3带三个菜单项的File菜单

9785564629e89598811c0e2da72b9fc8.png

有了View菜单&#xff0c;你可以隐藏和显示参考信息中的某些元素。实现createMenuItem()方法&#xff0c;并在start()方法中调用以创建四个CheckMenuItem对象。然后添加这些新创建的CheckMenuItem到View菜单中&#xff0c;这些菜单项可以控制标题&#xff0c;拉丁学名&#xff0c;图片和描述的显示与否。例24-6显示了实现了这些功能的两段代码。

例24-6使用CheckMenuItem类来创建开关选项

Java

//在start方法中创建四个Check Menu Item

CheckMenuItem titleView &#61; createMenuItem ("Title", name);

CheckMenuItem binNameView &#61; createMenuItem ("Binomial name", binName);

CheckMenuItem picView &#61; createMenuItem ("Picture", pic);

CheckMenuItem descriptionView &#61; createMenuItem ("Description", description);

menuView.getItems().addAll(titleView, binNameView, picView, descriptionView);

...

//createMenuItem方法

private static CheckMenuItem createMenuItem (String title, final Node node){

CheckMenuItem cmi &#61; 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;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

//在start方法中创建四个Check Menu Item

CheckMenuItemtitleView&#61;createMenuItem("Title",name);

CheckMenuItembinNameView&#61;createMenuItem("Binomial name",binName);

CheckMenuItempicView&#61;createMenuItem("Picture",pic);

CheckMenuItemdescriptionView&#61;createMenuItem("Description",description);

menuView.getItems().addAll(titleView,binNameView,picView,descriptionView);

...

//createMenuItem方法

privatestaticCheckMenuItemcreateMenuItem(Stringtitle,finalNodenode){

CheckMenuItemcmi&#61;newCheckMenuItem(title);

cmi.setSelected(true);

cmi.selectedProperty().addListener(

(ObservableValueov,Booleanold_val,

Booleannew_val)->{

node.setVisible(new_val);

});

returncmi;

}

CheckMenuItem类是MenuItem类的扩展。它可以在选中和非选中状态之间切换。当选中时&#xff0c;Check Menu Item会显示一个对钩标志。

例24-6创建了四个CheckMenuItem对象&#xff0c;并处理了他们的selectedProperty属性变化事件。例如&#xff0c;当用户取消选中picView菜单项&#xff0c;setVisible()方法会被赋以false&#xff0c;然后植物的图片就变得不可见了。当你添加这段代码到应用程序&#xff0c;编译并运行之&#xff0c;你可以尝试选中和取消选中这些菜单项。图24-4显示了标题和图片可见&#xff0c;而拉丁学名和描述不可见时的应用程序效果。

图24-4使用Check Menu Item

988036fc32f80ed7bfcdb77b6a3ddac1.png

创建子菜单

对于Edit菜单&#xff0c;定义两个菜单项&#xff1a;Picture Effect和No Effects。Picture Effect菜单项被设计为包含三个菜单项的子菜单&#xff0c;用于控制三种可用的视觉特效。No Effects 菜单项会移除选中的特效&#xff0c;将图片重置到初始状态。

使用RadioMenuItem来创建子菜单的菜单项。将Radio Menu Item添加到Toggle Group中&#xff0c;使各个菜单项的选中是相互排斥的。例24-7实现了这些功能。

例24-7创建带有Radio Menu Item的子菜单

Java

//Picture Effect菜单

Menu menuEffect &#61; new Menu("Picture Effect");

final ToggleGroup groupEffect &#61; new ToggleGroup();

for (Entry effect : effects) {

RadioMenuItem itemEffect &#61; new RadioMenuItem(effect.getKey());

itemEffect.setUserData(effect.getValue());

itemEffect.setToggleGroup(groupEffect);

menuEffect.getItems().add(itemEffect);

}

//No Effects菜单

final MenuItem noEffects &#61; new MenuItem("No Effects");

noEffects.setOnAction((ActionEvent t) -> {

pic.setEffect(null);

groupEffect.getSelectedToggle().setSelected(false);

});

//处理菜单项的选中事件

groupEffect.selectedToggleProperty().addListener(new ChangeListener() {

public void changed(ObservableValue extends Toggle> ov,

Toggle old_toggle, Toggle new_toggle) {

if (groupEffect.getSelectedToggle() !&#61; null) {

Effect effect &#61;

(Effect) groupEffect.getSelectedToggle().getUserData();

pic.setEffect(effect);

}

}

});

groupEffect.selectedToggleProperty().addListener(

(ObservableValue extends Toggle> ov, Toggle old_toggle,

Toggle new_toggle) -> {

if (groupEffect.getSelectedToggle() !&#61; null) {

Effect effect &#61;

(Effect) groupEffect.getSelectedToggle().getUserData();

pic.setEffect(effect);

}

});

//向Edit菜单添加菜单项

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

//Picture Effect菜单

MenumenuEffect&#61;newMenu("Picture Effect");

finalToggleGroupgroupEffect&#61;newToggleGroup();

for(Entryeffect:effects){

RadioMenuItemitemEffect&#61;newRadioMenuItem(effect.getKey());

itemEffect.setUserData(effect.getValue());

itemEffect.setToggleGroup(groupEffect);

menuEffect.getItems().add(itemEffect);

}

//No Effects菜单

finalMenuItemnoEffects&#61;newMenuItem("No Effects");

noEffects.setOnAction((ActionEventt)->{

pic.setEffect(null);

groupEffect.getSelectedToggle().setSelected(false);

});

//处理菜单项的选中事件

groupEffect.selectedToggleProperty().addListener(newChangeListener(){

publicvoidchanged(ObservableValueov,

Toggleold_toggle,Togglenew_toggle){

if(groupEffect.getSelectedToggle()!&#61;null){

Effecteffect&#61;

(Effect)groupEffect.getSelectedToggle().getUserData();

pic.setEffect(effect);

}

}

});

groupEffect.selectedToggleProperty().addListener(

(ObservableValueov,Toggleold_toggle,

Togglenew_toggle)->{

if(groupEffect.getSelectedToggle()!&#61;null){

Effecteffect&#61;

(Effect)groupEffect.getSelectedToggle().getUserData();

pic.setEffect(effect);

}

});

//向Edit菜单添加菜单项

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

通过setUserData()为每个Radio Menu Item定义了一个视觉特效。当Toggle Group中的菜单项被选中时&#xff0c;对应的特效就会被应用在图片上。当No Effects菜单项被选中时&#xff0c;setEffect()方法被赋值为null&#xff0c;没有特效应用在图片上。

图24-5显示了当用户正在选择Shadow菜单项时的运行效果。

图24-5带有三个Radio Menu Item的子菜单

8d0d298b215062efbcb2d08ac96e9339.png

当DropShadow特效被应用在图片上后&#xff0c;其效果如图24-6所示。

图24-6应用了DropShadow特效的Quince的Picture

f468f2c044e13b95248ecaf1fd809d79.png

你可以使用MenuItem类的setDisable()方法在没有Picture Effect子菜单中的特效被选中时禁用No Effects菜单项。将例24-7按照例24-8进行修改。

例24-8禁用菜单项

Java

Menu menuEffect &#61; new Menu("Picture Effect");

final ToggleGroup groupEffect &#61; new ToggleGroup();

for (Entry effect : effects) {

RadioMenuItem itemEffect &#61; new RadioMenuItem(effect.getKey());

itemEffect.setUserData(effect.getValue());

itemEffect.setToggleGroup(groupEffect);

menuEffect.getItems().add(itemEffect);

}

final MenuItem noEffects &#61; 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() !&#61; null) {

Effect effect &#61;

(Effect) groupEffect.getSelectedToggle().getUserData();

pic.setEffect(effect);

noEffects.setDisable(false);

} else {

noEffects.setDisable(true);

}

});

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

MenumenuEffect&#61;newMenu("Picture Effect");

finalToggleGroupgroupEffect&#61;newToggleGroup();

for(Entryeffect:effects){

RadioMenuItemitemEffect&#61;newRadioMenuItem(effect.getKey());

itemEffect.setUserData(effect.getValue());

itemEffect.setToggleGroup(groupEffect);

menuEffect.getItems().add(itemEffect);

}

finalMenuItemnoEffects&#61;newMenuItem("No Effects");

noEffects.setDisable(true);

noEffects.setOnAction((ActionEventt)->{

pic.setEffect(null);

groupEffect.getSelectedToggle().setSelected(false);

noEffects.setDisable(true);

});

groupEffect.selectedToggleProperty().addListener(

(ObservableValueov,Toggleold_toggle,

Togglenew_toggle)->{

if(groupEffect.getSelectedToggle()!&#61;null){

Effecteffect&#61;

(Effect)groupEffect.getSelectedToggle().getUserData();

pic.setEffect(effect);

noEffects.setDisable(false);

}else{

noEffects.setDisable(true);

}

});

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

当没有RadioMenuItem选项被选中时&#xff0c;No Effects菜单项是被禁用的&#xff0c;如图24-7。当用户选择一个视觉特效&#xff0c;No Effects菜单项就会变得可用。

图24-7 No Effects菜单项被禁用

e3d76d0fe5fdc66972a280f0efc8c7b0.png

添加上下文菜单

当你无法分配任何UI空间给一个需要的功能时&#xff0c;你可以使用上下文菜单。上下文菜单是一个弹出窗口&#xff0c;会由一次鼠标点击事件触发显示出来。一个上下文菜单可以包含一个或者多个菜单项。

在Menu Sample应用程序中&#xff0c;为植物的图片设置一个上下文菜单&#xff0c;使得用户可以复制图像。

使用ContextMenu类来创建上下文菜单&#xff0c;见例24-9。

例24-9定义Context Menu

Java

final ContextMenu cm &#61; new ContextMenu();

MenuItem cmItem1 &#61; new MenuItem("Copy Image");

cmItem1.setOnAction((ActionEvent e) -> {

Clipboard clipboard &#61; Clipboard.getSystemClipboard();

ClipboardContent content &#61; new ClipboardContent();

content.putImage(pic.getImage());

clipboard.setContent(content);

});

cm.getItems().add(cmItem1);

pic.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {

if (e.getButton() &#61;&#61; MouseButton.SECONDARY)

cm.show(pic, e.getScreenX(), e.getScreenY());

});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

finalContextMenucm&#61;newContextMenu();

MenuItemcmItem1&#61;newMenuItem("Copy Image");

cmItem1.setOnAction((ActionEvente)->{

Clipboardclipboard&#61;Clipboard.getSystemClipboard();

ClipboardContentcontent&#61;newClipboardContent();

content.putImage(pic.getImage());

clipboard.setContent(content);

});

cm.getItems().add(cmItem1);

pic.addEventHandler(MouseEvent.MOUSE_CLICKED,(MouseEvente)->{

if(e.getButton()&#61;&#61;MouseButton.SECONDARY)

cm.show(pic,e.getScreenX(),e.getScreenY());

});

当用户右击ImageView对象&#xff0c;上下文菜单的show()方法就会被调用使其显示。

为上下文菜单的Copy菜单项定义的setOnAction()方法创建了一个ClipBoard并添加图像作为其内容。图24-8显示了用户正在选择Copy Image上下文菜单项的瞬间。

图24-8使用Context Menu

你可以尝试复制那个图像然后粘贴到一个图像编辑器中。

为了进一步改进&#xff0c;你可以添加更多的菜单项到上下文菜单中并指定不同的动作。你可以使用CustomMenuItem来创建自定义的菜单。通过这个类&#xff0c;你可以将任何Node作为菜单项添加到一个菜单中&#xff0c;比如Button或者Slider等。

相关API文档

· Menu

· MenuItem

· RadioMenuItem

· CheckMenuItem

· ContextMenu

· SeparatorMenuItem

· CustomMenuItem

打赏一下

支付宝

微信



推荐阅读
  • 1Lock与ReadWriteLock1.1LockpublicinterfaceLock{voidlock();voidlockInterruptibl ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了Java集合库的使用方法,包括如何方便地重复使用集合以及下溯造型的应用。通过使用集合库,可以方便地取用各种集合,并将其插入到自己的程序中。为了使集合能够重复使用,Java提供了一种通用类型,即Object类型。通过添加指向集合的对象句柄,可以实现对集合的重复使用。然而,由于集合只能容纳Object类型,当向集合中添加对象句柄时,会丢失其身份或标识信息。为了恢复其本来面貌,可以使用下溯造型。本文还介绍了Java 1.2集合库的特点和优势。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • 解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因
    本文介绍了解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因。其中包括修改包名、解决service name重复、处理jar包冲突和添加maven依赖等解决方案。同时推荐了一个人工智能学习网站,该网站内容通俗易懂,风趣幽默,值得一看。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • Mono为何能跨平台
    概念JIT编译(JITcompilation),运行时需要代码时,将Microsoft中间语言(MSIL)转换为机器码的编译。CLR(CommonLa ... [详细]
  • AstridDAO 专访:波卡稳定币黑马 BAI
    加入Pol ... [详细]
  • uboot与linux驱动1.uboot本身是裸机程序(1)在裸机中本来是没有驱动概念的(狭义的驱动概念是指在操作系统中用来具体操控硬 ... [详细]
author-avatar
一个萝卜一个坑
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有