Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Capítulo 31 - JavaFX y FXML Avanzado - Liang-Java-Comp11e, Resumos de Informática

Java con JavaFX y FXML Avanzado

Tipologia: Resumos

2018

Compartilhado em 21/07/2018

dddmmm80-5
dddmmm80-5 🇧🇷

4.8

(4)

13 documentos

1 / 49

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Objectives
To specify styles for UI nodes using JavaFX CSS (§31.2).
To create quadratic curve, cubic curve, and path using the QuadCurve,
CubicCurve, and Path classes (§31.3).
To translate, rotate, and scale to perform coordinate transformations
for nodes (§31.4).
To define a shape’s border using various types of strokes (§31.5).
To create menus using the Menu, MenuItem, CheckMenuItem, and
RadioMemuItem classes (§31.6).
To create context menus using the ContextMenu class (§31.7).
To use SplitPane to create adjustable horizontal and vertical panes
(§31.8).
To create tab panes using the TabPane control (§31.9).
To create and display tables using the TableView and TableColumn
classes (§31.10).
To create JavaFX user interfaces using FMXL and the visual Scene
Builder (§31.11).
Advanced JavaFX
and FXML
CHAPTER
31
M31_LIAN0182_11_SE_C31.indd 1 5/29/17 7:16 AM
© 2018 Pearson Education, Inc., Hoboken, NJ. All rights reserved.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31

Pré-visualização parcial do texto

Baixe Capítulo 31 - JavaFX y FXML Avanzado - Liang-Java-Comp11e e outras Resumos em PDF para Informática, somente na Docsity!

Objectives

■ ■ To specify styles for UI nodes using JavaFX CSS (§31.2).

■ ■ To create quadratic curve, cubic curve, and path using the QuadCurve ,

CubicCurve , and Path classes (§31.3).

■ ■ To translate, rotate, and scale to perform coordinate transformations

for nodes (§31.4).

■ ■ To define a shape’s border using various types of strokes (§31.5).

■ ■ To create menus using the Menu , MenuItem , CheckMenuItem , and

RadioMemuItem classes (§31.6).

■ ■ To create context menus using the ContextMenu class (§31.7).

■ ■ To use SplitPane to create adjustable horizontal and vertical panes

■ ■ To create tab panes using the TabPane control (§31.9).

■ ■ To create and display tables using the TableView and TableColumn

classes (§31.10).

■ ■ To create JavaFX user interfaces using FMXL and the visual Scene

Builder (§31.11).

Advanced JavaFX

and FXML

CHAPTER

31-2 Chapter 31 Advanced JavaFX and FXML

31.1 Introduction

JavaFX can be used to develop comprehensive rich Internet applications.

Chapters 14–16 introduced basics of JavaFX, event-driven programming, animations, and

simple UI controls. This chapter introduces some advanced features for developing compre-

hensive GUI applications.

31.2 JavaFX CSS

JavaFX cascading style sheets can be used to specify styles for UI nodes.

JavaFX cascading style sheets are based on CSS with some extensions. CSS defines the style

for webpages. It separates the contents of webpages from its style. JavaFX CSS can be used to

define the style for the UI and separates the contents of the UI from the style. You can define

the look and feel of the UI in a JavaFX CSS file and use the style sheet to set the color, font,

margin, and border of the UI components. A JavaFX CSS file makes it easy to modify the style

without modifying the Java source code.

A JavaFX style property is defined with a prefix –fx- to distinquish it from a property in

CSS. All the available JavaFX properties are defined in http://docs.oracle.com/javafx/2/api/

javafx/scene/doc-files/cssref.html. Listing 31.1 gives an example of a style sheet.

Listing 31.1 mystyle.css

.plaincircle { -fx-fill: white; -fx-stroke: black; } .circleborder { -fx-stroke-width: 5; -fx-stroke-dash-array: 12 2 4 2; } .border { -fx-border-color: black; -fx-border-width: 5; } #redcircle { -fx-fill: red; -fx-stroke: red; } #greencircle { -fx-fill: green; -fx-stroke: green; }

A style sheet uses the style class or style id to define styles. Multiple style classes can

be applied to a single node, and a style id to a unique node. The syntax .styleclass

defines a style class. Here, the style classes are named plaincircle , circleborder , and

circleborder. The syntax #styleid defines a style id. Here, the style ids are named red-

circle and greencircle.

Each node in JavaFX has a styleClass variable of the List type, which

can be obtained from invoking getStyleClass(). You can add multiple style classes to

a node and only one id to a node. Each node in JavaFX has an id variable of the String

type, which can be set using the setID(String id) method. You can set only one id

to a node.

The Scene and Parent classes have the stylesheets property, which can be

obtained from invoking the getStylesheets() method. This property is of the

Point

Key

Point

Key

31-4 Chapter 31 Advanced JavaFX and FXML

The program loads the style sheet from the file mystyle.css by adding it to the

stylesheets property (line 13). The file should be placed in the same directory with

the source code for it to run correctly. After the style sheet is loaded, the program sets the

style class plaincircle for circle1 and circle2 (lines 22 and 23) and sets the style

id redcircle for circle3 (line 24). The program sets style classes circleborder and

plaincircle and an id greencircle for circle4 (lines 28 and 29). The style class

border is set for both pane1 and pane2 (lines 20 and 31).

The style sheet is set in the scene (line 13). All the nodes inside the scene can use this

style sheet. What would happen if line 13 is deleted and the following line is inserted

after line 15?

pane1.getStylesheets().add("mystyle.css");

In this case, only pane1 and the nodes inside pane1 can access the style sheet, but pane

and circle4 cannot use this style sheet. Therefore, everything in pane1 is displayed the same

as before the change, and pane2 and circle4 are displayed without applying the style class

and id, as shown in Figure 31.1b.

Note the style class plaincircle and id greencircle both are applied to circle

(lines 28 and 29). plaincircle sets fill to white and greencircle sets fill to green. The

property settings in id take precedence over the ones in classes. Thus, circle4 is displayed

in green in this program.

31.2.1 How do you load a style sheet to a Scene or a Parent? Can you load multiple style

sheets?

31.2.2 If a style sheet is loaded from a node, can the pane and all its containing nodes access

the style sheet?

31.2.3 Can a node add multiple style classes? Can a node set multiple style ids? 31.2.4 If the same property is defined in both a style class and a style id and applied to a

node, which one has the precedence?

31.3 QuadCurve , CubicCurve , and Path

JavaFX provides the QuadCurve , CubicCurve , and Path classes for creating advanced

shapes.

Section 14.11 introduced drawing simple shapes using the Line , Rectangle , Circle ,

Ellipse , Arc , Polygon , and Polyline classes. This section introduces drawing advanced

shapes using the CubicCurve , QuadCurve , and Path classes.

31.3.1 QuadCurve and CubicCurve

JavaFX provides the QuadCurve and CubicCurve classes for modeling quadratic curves and

cubic curves. A quadratic curve is mathematically defined as a quadratic polynomial. To create

a QuadCurve , use its no-arg constructor or the following constructor:

QuadCurve( double startX, double startY, double controlX, double controlY, double endX, double endY)

where ( startX , startY ) and ( endX , endY ) specify two endpoints and ( controlX , controlY )

is a control point. The control point is usually not on the curve instead of defining the trend of

the curve, as shown in Figure 31.2a. Figure 31.3 shows the UML diagram for the QuadCurve

class.

Point

Check

Point

Key

31.3 QuadCurve, CubicCurve, and Path 31-

A cubic curve is mathematically defined as a cubic polynomial. To create a CubicCurve ,

use its no-arg constructor or the following constructor:

CubicCurve( double startX, double startY, double controlX1, double controlY1, double controlX2, double controlY2, double endX, double endY)

where ( startX , startY ) and ( endX , endY ) specify two endpoints and ( controlX1 ,

controlY1 ) and ( controlX2 , controlY2 ) are two control points. The control points are

usually not on the curve, instead define the trend of the curve, as shown in Figure 31.2b.

Figure 31.4 shows the UML diagram for the CubicCurve class.

F igure 31.2 (a) A quadratic curve is specified using three points. (b) A cubic curve is

specified using four points.

(controlX, controlY)

(startX, startY) (endX, endY)

(controlX1, controlY1)

(startX, startY) (endX, endY)

(controlX2, controlY2)

(a) (b)

Figure 31.3 QuadCurve defines a quadratic curve.

The getter and setter methods for property values and a getter for prop- javafx.scene.shape.QuadCurve erty itself are provided in the class, but omitted in the UML diagram for brevity.

-startX: DoubleProperty -startY: DoubleProperty -endX: DoubleProperty -endY: DoubleProperty -controlX: DoubleProperty -controlY: DoubleProperty

The x-coordinate of the start point (default 0). The y-coordinate of the start point (default 0). The x-coordinate of the end point (default 0). The y-coordinate of the end point (default 0). The x-coordinate of the control point (default 0). The y-coordinate of the control point (default 0). Creates an empty quad curve. Creates a quad curve with the specified arguments.

+QuadCurve() +QuadCurve(startX: double, startY: double, controlX: double, controlY: double, endX: double, endY: double)

The getter and setter methods for property values and a getter for property javafx.scene.shape.CubicCurve itself are provided in the class, but omitted in the UML diagram for brevity.

-startX: DoubleProperty -startY: DoubleProperty -endX: DoubleProperty -endY: DoubleProperty -controlX1: DoubleProperty -controlY1: DoubleProperty -controlX2: DoubleProperty -controlY2: DoubleProperty

The x-coordinate of the start point (default 0). The y-coordinate of the start point (default 0). The x-coordinate of the end point (default 0). The y-coordinate of the end point (default 0). The x-coordinate of the first control point (default 0). The y-coordinate of the first control point (default 0). The x-coordinate of the second control point (default 0). The y-coordinate of the second control point (default 0). Creates an empty cubic curve. Creates a cubic curve with the specified arguments.

+CubicCurve() +CubicCurve(startX: double, startY: double, controlX1: double, controlY1: double, controlX2: double, controlY2: double, endX: double, endY: double)

Figure 31.4 CubicCurve defines a quadratic curve.

31.3 QuadCurve, CubicCurve, and Path 31-

The program creates a CubicCurve with the specified start, first control, second control,

and end points (lines 24 and 25) and places the CubicCurve to the pane (line 29). To illustrate

the control points, the program also displays the control points in the pane (lines 29–32).

Note the curves are filled with color. The program sets the color to white and stroke to black

in order to display the curves (lines 17 and 18, 26 and 27). If these code lines are removed from

the program, the sample run would look like the one in Figure 31.5b.

31.3.2 Path

The Path class models an arbitrary geometric path. A path is constructed by adding path

elements into the path. The PathElement is the root class for the path elements MoveTo ,

HLineTo , VLineTo , LineTo , ArcTo , QuadCurveTo , CubicCurveTo , and ClosePath.

You can create a Path using its no-arg constructor. The process of the path construction can

be viewed as drawing with a pen. The path does not have a default initial position. You need to set

an initial position by adding a MoveTo(startX, startY) path element to the path. Adding a

HLineTo(newX) element draws a horizontal line from the current position to the new x -coordinate.

Adding a VLineTo(newY) element draws a vertical line from the current position to the new

y -coordinate. Adding a LineTo(newX, newY) element draws a line from the current position to

the new position. Adding an ArcTo(radiusX, radiusY, xAxisRotation, newX, newY,

largeArcFlag, sweepArcFlag) element draws an arc from the previous position to the new

position with the specified radius. Adding a QuadCurveTo(controlX, controlY, newX,

newY) element draws a quadratic curve from the previous position to the new position with the

specified control point. Adding a CubicCurveTo(controlX1, controlY1, controlX2,

controlY2, newX, newY) element draws a cubic curve from the previous position to the new

position with the specified control points. Adding a ClosePath() element closes the path by

drawing a line that connects the starting point with the end point of the path.

Listing 31.4 gives an example that creates a path. A sample run of the program is shown

in Figure 31.6.

Listing 31.4 PathDemo.java

1 import javafx.application.Application; 2 import javafx.scene.Scene; 3 import javafx.scene.layout.Pane; 4 import javafx.scene.paint.Color; 5 import javafx.scene.shape.*; 6 import javafx.stage.Stage; 7 8 public class PathDemo extends Application { 9 @Override // Override the start method in the Application class 10 public void start(Stage primaryStage) { 11 Pane pane = new Pane(); 12 13 // Create a Path 14 Path path = new Path(); 15 path.getElements().add( new MoveTo( 50.0 , 50.0 )); 16 path.getElements().add( new HLineTo( 150.5 )); 17 path.getElements().add( new VLineTo( 100.5 )); 18 path.getElements().add( new LineTo( 200.5 , 150.5 )); 19 20 ArcTo arcTo = new ArcTo( 45 , 45 , 250 , 100.5 , 21 false , true ); 22 path.getElements().add(arcTo); 23 24 path.getElements().add( new QuadCurveTo( 50 , 50 , 350 , 100 )); 25 path.getElements().add( 26 new CubicCurveTo( 250 , 100 , 350 , 250 , 450 , 10 ));

31-8 Chapter 31 Advanced JavaFX and FXML

28 path.getElements().add( new ClosePath()); 29 30 pane.getChildren().add(path); 31 path.setFill( null ); 32 Scene scene = new Scene(pane, 300 , 250 ); 33 primaryStage.setTitle( "PathDemo" ); // Set the window title 34 primaryStage.setScene(scene); // Place the scene in the window 35 primaryStage.show(); // Display the window 36 } 37 }

Figure 31.6 You can draw a path by adding path elements.

HLineTo VLineTo

LineTo ArcTo QuadCurveTo CubicCurveTo

ClosePath

The program creates a Path (line 14), moves its position (line 15), and adds a horizontal line

(line 16), a vertical line (line 17), and a line (line 18). The getElements() method returns

an ObservableList.

The program creates an ArcTo object (lines 20 and 21). The ArcTo class contains the

largeArcFlag and sweepFlag properties. By default, these property values are false. You

may set these properties to ture to display a large arc in the opposite direction.

The program adds a quadratic curve (line 24) and a cubic curve (lines 25 and 26) and closes

the path (line 28).

By default, the path is not filled. You may change the fill property in the path to specify

a color to fill the path.

31.3.1 Create a QuadCurve with starting point (100, 75.5), control point (40, 55.5), and

end point (56, 80). Set its fill property to white and stroke to green.

31.3.2 Create CubicCurve object with starting point (100, 75.5), control point 1 (40, 55.5),

control point 2 (78.5, 25.5), and end point (56, 80). Set its fill property to white

and stroke to green.

31.3.3 Does a path have a default initial position? How do you set a position for a path? 31.3.4 How do you close a path? 31.3.5 How do you display a filled path?

31.4 Coordinate Transformations

JavaFX supports coordinate transformations using translation, rotation, and scaling.

You have used the rotate method to rotate a node. You can also perform translations and scaling.

31.4.1 Translations

You can use the setTranslateX(double x) , setTranslateY(double y) , and

setTranslateZ(double z) methods in the Node class to translate the coordinates for a

Point

Check

Point

Key

31-10 Chapter 31 Advanced JavaFX and FXML

The program repeatedly creates 10 rectangles (line 17). For each rectangle, it sets its fill

property to white (line 18) and its stroke property to a random color (lines 19 and 20), and

translates it to a new location (lines 21 and 22). The variables x and y are used to set the

translateX and translateY properties. These two variable values are changed every time

it is applied to a rectangle (see Figure 31.8).

31.4.2 Rotations

Rotation was introduced in Chapter 14. This section discusses it in more depth. You can use

the rotate(double theta) method in the Node class to rotate a node by theta degrees

from its pivot point clockwise, where theta is a double value in degrees. The pivot point is

automatically computed based on the bounds of the node. For a circle, ellipse, and a rectangle,

the pivot point is the center point of these nodes. For example, rectangle.rotate(45)

rotates the rectangle 45 degrees clockwise along the eastern direction from the center, as

shown in Figure 31.9.

Figure 31.9 After performing rectangle.rotate(45) , the rectangle is rotated in 45

degrees from the center.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 1

3 4

7

5 6

2

After rotate

Before rotate

Rectangle.rotate(45)

Figure 31.8 The rectangles are displayed successively in new locations.

Listing 31.6 gives a program that demonstrates the effect of rotation of coordinates. Figure 31.

shows a sample run of the program.

Listing 31.6 RotateDemo.java

1 import javafx.application.Application; 2 import javafx.scene.Scene; 3 import javafx.scene.layout.Pane; 4 import javafx.scene.paint.Color; 5 import javafx.scene.shape.Rectangle; 6 import javafx.stage.Stage; 7 8 public class RotateDemo extends Application { 9 @Override // Override the start method in the Application class 10 public void start(Stage primaryStage) { 11 Pane pane = new Pane(); 12 java.util.Random random = new java.util.Random();

31.4 Coordinate Transformations 31-

13 // The radius of the circle for anchoring rectangles 14 double radius = 90 ; 15 double width = 20 ; // Width of the rectangle 16 double height = 40 ; // Height of the rectangle 17 for ( int i = 0 ; i < 8 ; i++) { 18 // Center of a rectangle 19 double x = 150 + radius * Math.cos(i * 2 * Math.PI / 8 ); 20 double y = 150 + radius * Math.sin(i * 2 * Math.PI / 8 ); 21 Rectangle rectangle = new Rectangle( 22 x − width / 2 , y − height / 2 , width, height); 23 rectangle.setFill(Color.WHITE); 24 rectangle.setStroke(Color.color(random.nextDouble(), 25 random.nextDouble(), random.nextDouble())); 26 rectangle.setRotate(i * 360 / 8 ); // Rotate the rectangle 27 pane.getChildren().add(rectangle); 28 } 29 30 Scene scene = new Scene(pane, 300 , 300 ); 31 primaryStage.setTitle( "RotateDemo" ); // Set the window title 32 primaryStage.setScene(scene); // Place the scene in the window 33 primaryStage.show(); // Display the window 34 } 35 }

Figure 31.10 The rotate method rotates a node.

The program creates eight rectangles in a loop (lines 17–28). The center of each rectangle is

located on the circle centered as (150, 150) (lines 19 and 20). A rectangle is created by speci-

fying its upper left corner position with width and height (lines 21 and 22). The rectangle is

rotated in line 26 and added to the pane in line 27.

31.4.3 Scaling

You can use the setScaleX(double sx) , setScaleY(double sy) , and setScaleY(double

sy) methods in the Node class to specify a scaling factor. The node will appear larger or

smaller depending on the scaling factor. Scaling alters the coordinate space of the node such

that each unit of distance along the axis is multiplied by the scale factor. As with rotation

transformations, scaling transformations are applied to enlarge or shrink the node around the

pivot point. For a node of the rectangle shape, the pivot point is the center of the rectangle.

For example, if you apply a scaling factor ( x = 2, y = 2), the entire rectangle including the

stroke will double in size, growing to the left, right, up, and down from the center, as shown

in Figure 31.11.

31.5 Strokes 31-

43 Scene scene = new Scene(pane, 450 , 200 ); 44 primaryStage.setTitle( "ScaleDemo" ); // Set the window title 45 primaryStage.setScene(scene); // Place the scene in the window 46 primaryStage.show(); // Display the window 47 } 48 }

Figure 31.12 The scale method scales the coordinates in the node.

The program creates a polyline (line 13) and adds the points for a sine curve into the polyline

(lines 14–17). Since  sin( x ) 6 = 1, the y -coordinates are too small. To see the sine curve,

the program scales the y -coordinates up by 50 times (line 21) and shrinks the x -coordinates

by half (line 20).

Note scaling also causes the stroke width to change. To compensate it, the stroke width is

purposely set to 1.0 / 25 (line 22).

31.4.1 Can you perform a coordinate transformation on any node? Does a coordinate trans-

formation change the contents of a Shape object?

31.4.2 Does the method setTranslateX(6) move the node’s x -coordinate to 6? Does the

method setTranslateX(6) move the node’s x -coordinate 6 pixel right from its

current location?

31.4.3 Does the method rotate(Math.PI / 2) rotate a node 90 degrees? Does the

method rotate(90) rotate a node 90 degrees?

31.4.4 How is the pivot point determined for performing a rotation?

31.4.5 What method do you use to scale a node two times on its x -axis?

31.5 Strokes

Stroke defines a shape’s border line style.

JavaFX allows you to specify the attributes of a shape’s boundary using the methods in Figure 31.13.

Point

Check

Point

Key

The setStroke(paint) method sets a paint for the stroke. The width of the stroke can be

specified using the setStrokeWidth(width) method.

Figure 31.13 The Shape class contains the methods for setting stroke properties.

javafx.scene.shape.Shape +setStroke(paint: Paint): void +setStrokeWidth(width: double): void +setStrokeType(type: StrokeType): void

+setStrokeLineCap(type: StrokeLineCap): void +setStrokeLineJoin(type: StrokeLineJoin): void +getStrokeDashArray(): ObservableList +setStrokeDashOffset(distance: double): void

Sets a paint for the stroke. Sets a width for the stroke (default 1). Sets a type for the stroke to indicate whether the stroke is placed inside, centered, or outside of the border (default: CENTERED). Specifies the end cap style for the stroke (default: BUTT). Specifies how two line segments are joined (default: MITER). Returns a list that specifies a dashed pattern for line segments.

Specifies the offset to the first segment in the dashed pattern.

31-14 Chapter 31 Advanced JavaFX and FXML

The setStrokeType(type) method sets a type for the stroke. The type defines whether the

stroke is inside, outside, or in the center of the border using the constants StrokeType.INSIDE ,

StrokeType.OUTSIDE , or StrokeType.CENTERED (default), as shown in Figure 31.14.

Figure 31.15 (a) No decoration for a BUTT line cap. (b) A half circle is added to an

unclosed path. (c) A square with half of the stroke width is extended to an unclosed path.

(a) BUTT (b) ROUND (c) SQUARE

Figure 31.16 Path segments can be joined in three ways: (a) MITER, (b) BEVEL, and

(c) ROUND.

(a) MITER (b) BEVEL (c) ROUND

Figure 31.17 The numbers in the list specify the opaque and transparent segments of the

stroke alternately.

10 20 30 40

… [10.0, 20.0, 30.0, 40.0]

10 20 30 40

10 20 30 40

… [10.0, 20.0, 30.0, 40.0, 50]

50 10 20 30 40 50

Figure 31.14 (a) No stroke is used. (b) A stroke is placed inside the border. (c) A stroke is

placed in the center of the border. (d) A stroke is placed outside of the border.

(a) (b) (c) (d)

Note for the centered style, the stroke is applied by extending the boundary of the node by

a distance of half of the strokeWidth on either side (inside and outside) of the boundary.

The setStrokeLineCap(capType) method sets an end cap style for the stroke. The styles

are defined as StrokeLineCap.BUTT (default), StrokeLineCap.ROUND , and StrokeLine-

Cap.SQUARE , as illustrated in Figure 31.15. The BUTT stroke ends an unclosed path with no

added decoration. The ROUND stroke ends an unclosed side of a path with an added half circle

whose radius is half of the stroke width. The SQUARE stroke ends an unclosed side of a path

with an added square that extends half of the stroke width.

The setStrokeLineJoin method defines the decoration applied where path segments meet.

You can specify three types of line join using the constants StrokeLineJoin.MITER (default),

StrokeLineJoin.BEVEL , and StrokeLineJoin.ROUND , as shown in Figure 31.16.

The Shape class has a property named strokeDashArray of the ObservableList

type. This property is used to define a dashed pattern for the stroke. Alternate numbers in the

list specify the lengths of the opaque and transparent segments of the dashes. For example, the

list [10.0, 20.0, 30.0, 40.0] specifies a pattern as shown in Figure 31.17.

31-16 Chapter 31 Advanced JavaFX and FXML

46 Pane pane = new Pane(); 47 pane.getChildren().addAll(rectangle1, rectangle2, rectangle3, 48 line1, line2, line3, line4); 49 50 Scene scene = new Scene(pane, 610 , 180 ); 51 primaryStage.setTitle( "StrokeDemo" ); // Set the window title 52 primaryStage.setScene(scene); // Place the scene in the window 53 primaryStage.show(); // Display the window 54 } 55 56 // Launch the program from command-line 57 public static void main(String[] args) { 58 launch(args); 59 } 60 }

Figure 31.19 You can specify the attributes for strokes.

miter join (^) bevel join round join square cap

butt cap (^) round cap

dash line

The program creates three rectangles (lines 12–29). Rectangle 1 uses default miter join, rec-

tangle 2 uses bevel join (line 22), and rectangle 3 uses round join (line 29).

The program creates three lines with butt, round, and square end cap (lines 31–41).

The program creates a line and sets dash pattern for this line (line 44). Note the

strokeDashArray property is of the ObservableList type. You have to add

Double values to the list. Adding a number such as 10 would cause an error.

31.5.1 Are the methods for setting a stroke and its attributes defined in the Node or

Shape class?

31.5.2 How do you set a stroke width to 3 pixels? 31.5.3 What are the stroke types? What is the default stroke type? How do you set a

stroke type?

31.5.4 What are the stroke line join types? What is the default stroke line join type? How

do you set a stroke line join type?

31.5.5 What are the stroke cap types? What is the default stroke cap type? How do you

set a stroke cap type?

31.5.6 How do you specify a dashed pattern for strokes?

31.6 Menus

You can create menus in JavaFX.

Menus make selection easier and are widely used in window applications. JavaFX provides

five classes that implement menus: MenuBar , Menu , MenuItem , CheckMenuItem , and

RadioButtonMenuItem.

Point

Check

Point

Key

31.6 Menus 31-

MenuBar is a top-level menu component used to hold the menus. A menu consists of

menu items that the user can select (or toggle on or off). A menu item can be an instance of

MenuItem , CheckMenuItem , or RadioButtonMenuItem. Menu items can be associated with

nodes and keyboard accelerators.

31.6.1 Creating Menus

The sequence of implementing menus in JavaFX is as follows:

1. Create a menu bar and add it to a pane. For example, the following code creates a pane

and a menu bar, and adds the menu bar to the pane:

MenuBar menuBar = new MenuBar(); Pane pane = new Pane(); pane.getChildren().add(menuBar);

2. Create menus and add them under the menu bar. For example, the following creates two

menus and adds them to a menu bar, as shown in Figure 31.20a:

Menu menuFile = new Menu("File"); Menu menuHelp = new Menu("Help"); menuBar.getMenus().addAll(menuFile, menuHelp);

Figure 31.20 (a) The menus are placed under a menu bar. (b) Clicking a menu on the

menu bar reveals the items under the menu. (c) Clicking a menu item reveals the submenu

items under the menu item.

(a) (b) (c)

3. Create menu items and add them to the menus.

menuFile.getItems().addAll( new MenuItem("New"), new MenuItem("Open"), new MenuItem("Print"), new MenuItem("Exit"));

This code adds the menu items New, Open, Print, and Exit, in this order, to the File menu,

as shown in Figure 31.20b.

3.1. Creating submenu items.

You can also embed menus inside menus so the embedded menus become submenus.

Here is an example:

Menu softwareHelpSubMenu = new Menu("Software"); Menu hardwareHelpSubMenu = new Menu("Hardware"); menuHelp.getItems().add(softwareHelpSubMenu); menuHelp.getItems().add(hardwareHelpSubMenu); softwareHelpSubMenu.getItems().add(new MenuItem( "Unix" )); softwareHelpSubMenu.getItems().add(new MenuItem( "Windows" )); softwareHelpSubMenu.getItems().add(new MenuItem( "Mac OS" ));

31.6 Menus 31-

Menu menuFile = new Menu( "File" , new ImageView( "image/usIcon.gif" )); MenuItem menuItemOpen = new MenuItem( "New" , new ImageView( "image/new.gif" )); CheckMenuItem checkMenuItem = new CheckMenuItem( "Check it" , new ImageView( "image/us.gif" )); RadioMenuItem rmiBlue = new RadioMenuItem( "Blue" , new ImageView( "image/us.gif" ));

6. A key accelerator lets you select a menu item directly by pressing the CTRL and the

accelerator key. For example, by using the following code, you can attach the accelerator

key CTRL+N to the Open menu item:

menuItemOpen.setAccelerator( KeyCombination.keyCombination( "Ctrl+O" ));

31.6.2 Example: Using Menus

This section gives an example that creates a user interface to perform arithmetic. The inter-

face contains labels and text fields for Number 1, Number 2, and Result. The Result text field

displays the result of the arithmetic operation between Number 1 and Number 2. Figure 31.

contains a sample run of the program.

Figure 31.22 Arithmetic operations can be performed by clicking buttons or by choosing

menu items from the Operation menu.

Here are the major steps in the program (Listing 31.9):

1. Create a menu bar and add it into a VBox. Create the menus Operation and Exit, and add

them to the menu bar. Add the menu items Add, Subtract, Multiply, and Divide under the

Operation menu and add the menu item Close under the Exit menu.

2. Create an HBox to hold labels and text fields and place it into the VBox.

3. Create an HBox to hold the four buttons labeled Add, Subtract, Multiply, and Divide and

place it into the VBox.

4. Implement the handlers to process the events from the menu items and the buttons.

Listing 31.9 MenuDemo.java

1 import javafx.application.Application; 2 import javafx.geometry.Pos; 3 import javafx.scene.Scene; 4 import javafx.scene.control.Button; 5 import javafx.scene.control.Label; 6 import javafx.scene.control.Menu; 7 import javafx.scene.control.MenuBar; 8 import javafx.scene.control.MenuItem; 9 import javafx.scene.control.TextField; 10 import javafx.scene.input.KeyCombination;

31-20 Chapter 31 Advanced JavaFX and FXML

11 import javafx.scene.layout.HBox; 12 import javafx.scene.layout.VBox; 13 import javafx.stage.Stage; 14 15 public class MenuDemo extends Application { 16 private TextField tfNumber1 = new TextField(); 17 private TextField tfNumber2 = new TextField(); 18 private TextField tfResult = new TextField(); 19 20 @Override // Override the start method in the Application class 21 public void start(Stage primaryStage) { 22 MenuBar menuBar = new MenuBar(); 23 24 Menu menuOperation = new Menu( "Operation" ); 25 Menu menuExit = new Menu( "Exit" ); 26 menuBar.getMenus().addAll(menuOperation, menuExit); 27 28 MenuItem menuItemAdd = new MenuItem( "Add" ); 29 MenuItem menuItemSubtract = new MenuItem( "Subtract" ); 30 MenuItem menuItemMultiply = new MenuItem( "Multiply" ); 31 MenuItem menuItemDivide = new MenuItem( "Divide" ); 32 menuOperation.getItems().addAll(menuItemAdd, menuItemSubtract, 33 menuItemMultiply, menuItemDivide); 34 35 MenuItem menuItemClose = new MenuItem( "Close" ); 36 menuExit.getItems().add(menuItemClose); 37 38 menuItemAdd.setAccelerator( 39 KeyCombination.keyCombination( "Ctrl+A" )); 40 menuItemSubtract.setAccelerator( 41 KeyCombination.keyCombination( "Ctrl+S" )); 42 menuItemMultiply.setAccelerator( 43 KeyCombination.keyCombination( "Ctrl+M" )); 44 menuItemDivide.setAccelerator( 45 KeyCombination.keyCombination( "Ctrl+D" )); 46 47 HBox hBox1 = new HBox( 5 ); 48 tfNumber1.setPrefColumnCount( 2 ); 49 tfNumber2.setPrefColumnCount( 2 ); 50 tfResult.setPrefColumnCount( 2 ); 51 hBox1.getChildren().addAll( new Label( "Number 1:" ), tfNumber1, 52 new Label( "Number 2:" ), tfNumber2, new Label( "Result:" ), 53 tfResult); 54 hBox1.setAlignment(Pos.CENTER); 55 56 HBox hBox2 = new HBox( 5 ); 57 Button btAdd = new Button( "Add" ); 58 Button btSubtract = new Button( "Subtract" ); 59 Button btMultiply = new Button( "Multiply" ); 60 Button btDivide = new Button( "Divide" ); 61 hBox2.getChildren().addAll(btAdd, btSubtract, btMultiply, btDivide); 62 hBox2.setAlignment(Pos.CENTER); 63 64 VBox vBox = new VBox( 10 ); 65 vBox.getChildren().addAll(menuBar, hBox1, hBox2); 66 Scene scene = new Scene(vBox, 300 , 250 ); 67 primaryStage.setTitle( "MenuDemo" ); // Set the window title 68 primaryStage.setScene(scene); // Place the scene in the window 69 primaryStage.show(); // Display the window 70