JAVA程序设计基础-第6版陈国君2006-学习笔记4

JAVA程序设计基础-第6版陈国君2006-学习笔记4

[TOC]

JAVA程序设计基础-第6版陈国君2006-学习笔记4

第十四章 图形界面设计

图形用户界面概述

图形用户界面(Graphics User Interface,GUI),是指用图形的方式,借助菜单、按钮等标准界面元素和鼠标操作,帮助用户方便地向计算机系统发出指令、启动操作,并将系统运行的结果以图形方式显示给用户的技术。GUI又称为图形用户接口。

Java语言的早期版本提供了两个处理图形用户界面的包:java.awt和javax.swing。

JDK 8版本JavaFX替代了AWT和Swing,方便开发富因特网应用(Rich Internet Applications, RIA)。
富因特网应用,是一种Web应用,表现一般桌面应用具有的特点和功能。JavaFX为支持触摸设备提供了多点触控支持,并且还内建了对2D、3D、动画的支持,以及视频和音频的回放功能,JavaFX程序可以无缝地在桌面或Web浏览器中运行。

图形用户界面工具包JavaFX

JavaFX是一个强大的图形和多媒体处理工具包集合,它不仅可以用于开发RIA,而且还可以用来开发桌面程序以及移动设备上的程序。

  • JavaFX主要的类及节点类面板类和控件类的继承关系

JavaFX组件分类

节点(node):构成图形用户界面的各种元素。

构建图形用户界面的类主要分成三类:面板类(pane class)、控件类(control class)和辅助类(helper class)。

面板是一种容器,是用来包含各种控件和形状的类。

控件类又称为控件或组件,控件的作用是完成与用户的交互,包括接收用户的命令、接收用户输入的文本或用户的选择、向用户显示文本或图形等。

辅助类是用来描述控件属性的,例如,颜色类Color、字体类Font、图像类Image和图像显示类ImageView等。面板类和控件类等都是Node的子类,但辅助类并不都是Node类的子类。

JavaFX的基本概念

JavaFX程序用户界面的顶层称为舞台Stage,代表窗口。
舞台Stage中摆放的是场景Scene,场景Scene中可以包含各种布局面板和控件共同组成用户界面。

  • 舞台Stage:是用于显示场景的窗口,它是JavaFX程序用户界面的顶层容器。
  • 场景Scene:是摆放在舞台中的对象,也是一个容器,其中可放置面板和节点等对象。
  • 节点Node:是可视化的组件,可以是面板、控件、图像视图、形状等。
  • 面板Pane:面板中可以摆放各种节点。JavaFX提供了多种面板供用户在窗口中组织节点。
  • 控件Control:包括标签、按钮、复选框、单选按钮、文本框、文本区等。
  • 形状Shape:是指文本、直线、圆、椭圆、矩形、弧、多边形、折线等。

JavaFX窗口结构

任何JavaFX程序至少要有一个舞台和一个场景。
舞台是一个支持场景的平台,一个程序中只能有一个主舞台。
主舞台是应用程序自动访问的一个Stage对象,它是在应用程序启动时由系统创建的,通过start()方法的参数获得,用户不能自己创建。

场景Scene中可以包含面板Pane或控件Control,但不能包含形状Shape和图像显示类ImageView;面板Pane可以包含Node的任何子节点。

在JavaFX应用程序中,场景中的内容是通过层次结构表示的。
场景中的元素称为节点,每个节点都表示一个用户界面的可视元素。

节点可以有子节点,有子节点的节点称为父节点或分支节点,没有子节点的节点称为叶节点。
在场景图中有一个称为根节点的特殊节点,根节点是顶级节点,它是唯一没有父节点的节点。根节点通常是一个面板。

应用程序的父类Application、舞台Stage和场景Scene

所有的JavaFX 主程序都需要继承抽象类javafx.application.Application

继承了Application类的子类必须重写start()方法。
start()方法一般用于将控件放入场景中,并在舞台中显示场景。

  • javafx.application.Application类的常用方法
常用方法 功能说明
public static void launch(String… args) 启动一个独立的JavaFX 程序。利用可变参数args接收命令行参数,该方法通常是从main()方法调用的。它不能被多次调用,否则将抛出异常。
public void init() 程序初始化方法,加载Application 类之后该方法立即被调用。在此方法中不能创建舞台和场景,但可以创建其他JavaFX对象来进行初始化操作,若没有初始化部分,不用覆盖此方法。
public abstract void start(Stage primaryStage) JavaFX程序的人口点。参数primaryStage是程序的主舞台。可以设置程序场景。如果程序作为applet启动,主舞台将被嵌人到浏览器中。如果需要,程序可以创建其他舞台,但它们不是主要舞台,也不会嵌人到浏览器中。该方法在init()之后被调用。
public void stop() 该方法在程序停止时调用,为程序退出和销毁资源提供了方便。
  • javafx.stage.Stage类的构造方法
构造方法 功能说明
public Stage() 创建一个新舞台
public Stage(StageStyle style) 以style为舞台创建一个新舞台,style的取值是枚举StageStyle中的常量

StageStyle.DECORATED:有标题栏装饰即有最大最小和关闭按钮(默认选项)
StageStyle.UNDECORATED:纯白背景且无标题栏装饰
StageStyle.TRANSPARENT:透明背景且没有标题栏装饰
StageStyle.UNIFIED:有最大最小等按钮但没有标题栏装饰
StageStyle.UTILITY:有标题栏装饰但只有关闭按钮

  • javafx.stage.Stage类的常用方法
常用方法 功能说明
public final void show() 显示窗口
public final void setTitle(String value) 设置窗口的标题
public final void setScene(Scene value) 将场景value置于窗口中
public final void setMaxmized(boolean value) 设置窗口是否可以最大化
public final void setAlwaysOnTop(boolean value) 设置窗口是否在项层
public final void setResizable(boolean value) 设置是否可以改变窗口大小
public void close() 关闭舞台。这个调用等同于hide()方法隐藏窗口
  • javafx.scene.Scene类的构造方法
构造方法 功能说明
public Scene(Parent root) 以root为根节点创建一个场景,通常使用某种面板对象作为根节点,场景的大小会根据其中节点的大小自动计算
publc Scene(Parent root, double width, ouble height) 创建宽为width、高为height像素的场景,并将节点root放人场景中
public Scene(Parent root, Paint fill) 创建以root为根节点的场景,fill作为场景的背景填充色
public Scene(Parent root, double width, double height, Paint fill) 创建指定大小和填充色的场景,并将根节点root放入场录中
  • javafx.scene.Scene类的常用方法
常用方法 功能说明
public final < T extends Event > void addEventHandler(EventType < T > eventType, EventHandler < ? super T > eventHandler) 向场景注册事件监听者
public final void setFill(Paint value) 设置场景的背景填充色为value
public final void setRoot(Parent value) 设置场景的根节点
public final void setOnContextMenuRequested(EventHandler < ? super ContextMenuEvent > value) 为场最注册快捷菜单动作事件监听者

命令按钮

可以用鼠标单击它来控制程序运行的流程。javafx.scene.control包提供了Button类,用来处理按钮控件的相关操作。按钮创建之后通过面板的add()方法将其放入到面板中。

  • javafx.scene.control.Button类的构造方法
构造方法 功能说明
public Button() 创建一个没有文字的按钮
public Button(String text) 创建一个以text为文字的按钮
public Button(String text, Node graphic) 创建一个文字为text、图标为graphie的按钮
  • javafx.scene.control.Button类及其父类的常用方法
常用方法 功能说明
public final void setText(String value) 用value设置按钮上的文字
public final void setGraphic(Node value) 用value设置按钮上的图标
public void setPrefSize(double prefWidth, double prefHeight) 用指定的宽、高像素值设置按钮尺寸,取代系统自动计算出的默认尺寸
public final void setOnAction(EventHandler < ActionEvent > value) 为按钮注册单击事件监听者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//创建主舞台即窗口,并创建一个场景和一个按钮,然后将按钮放入场景中,再把场景放入舞台上,最后将窗口显示出来。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
public class App14_1 extends Application {
@Override
public void start(Stage primaryStage) {
Button bt = new Button("我是按钮");
Scene scene = new Scene(bt, 210, 80);

primaryStage.setTitle("我的JavaFX窗口");
primaryStage.setScene(scene);
primaryStage.show();
}

//如果用户是从命令行运行JavaFX程序,则主方法main()不是必需的;当从一个不完全支持JavaFX的IDE中启动JavaFX程序的时候,可能会需要主方法main()。
//当运行一个没有主方法main()的JavaFX程序时,JVM将自动调用launch()方法以运行应用程序。
public static void main(String[] args) {
Application.launch(args); //定义在Application类中的静态方法,用于启动一个独立的JavaFX程序,该方法必须在mian()方法中调用才会启动JavaFX程序
}
}

舞台默认是不显示的,舞台对象必须调用自己的show()方法才能将窗口显示出来。

JavaFX的布局面板

虽然可以直接将节点置于场景中,但更好的办法是先将节点放入面板中,然后再将面板放入场景中。

面板类Pane和JavaFX CSS

面板是一种没有标题栏、没有边框的容器,用来组织节点,面板可以包含Node的任何子类型。

面板类主要有如下几种:

  • 栈面板类StackPane
  • 边界面板类BorderPane
  • 流式面板类FlowPane
  • 网格面板类GridePane
  • 单行面板类HBox和单列面板类VBox

面板类Pane

Pane是所有其他面板的根类。
javafx.scene.layout.Pane类对象通常用作显示形状的画布,而其子类面板则主要用作摆放节点。

  • javafx.scene.layout.Pane类的构造方法
常用方法 功能说明
public Pane() 创建一个空面板,以后可向其添加其他控件和形状
public Pane(Node… children) 创建面板,并将参数指定的多个节点添加到面板中

每个面板都包含一个列表用于存放面板中的节点, 这个列表是javafx.collections.ObservableList类的实例,ObservableList类似于ArrayList,是一个用于存储元素的集合。

使用add(node)可以将一个节点添加到面板中,调用addAll(node1, node2, ..., noden)可以将多个节点同时添加到面板中。

调用remove(node)方法从面板中删除一个节点或调用removeAll()方法删除面
板中的所有节点。

  • javafx.scene.layout.Pane类及父类中的常用方法
常用方法 功能说明
public ObservableList < Node > getChildren() 返回面板用于存放节点的列表
public final void setPadding(Insets value) 利用Insets对象value设置面板四周边缘内侧空白空间的距离,单位是像素
public void setPrefSize(doule prefWidth, double prefHeight) 以给定的宽、高值作为偏好尺寸,来代替系统自动对该节点计算出的默认尺寸。即以给定的宽、高值优先设置面板的大小
public boolean isResizable() 判断面板是否可调整尺寸
public final void setStyle(Stirng value) 设置面板或节点的样式
public final void setRotate(double values) 以度为单位,设置节点围绕它的中心旋转value角度,若value为正,顺时针旋转,否则逆时针旋转
public final void setTranslateX(double value) 将节点在x轴方向上平移value像素
public final void setTranslateY(double value) 将节点在y轴方向上平移value像素
public final void setTranslateZ(double value) 将节点在z轴方向上平移value像素
public final double getLayoutX() 返回节点左上角的x坐标
public final double getLayoutY() 返回节点左上角的y坐标
public final void setCache(boolean value) 是否为节点设置缓冲,以提高性能
public final void setOnContextMenuRequested(EventHandler < ? super ContextMenuEvent value >) 为节点注册快捷菜单(上下文菜单)的动作事件

一个节点只能添加到一个面板中。

JavaFX CSS

JavaFX的样式属性类似于Web页面中指定HTML元素样式的叠层样式表(Cascading Style Sheet,CSS),因此,JavaFX的样式属性称为JavaFX CSS。

的setStyle()方法是Pane从其父类Node继承来的方法。

栈面板类StackPane

java.scene.layout.StackPane

将所有节点都摆放在面板中央,后加入的节点添加到前一个节点之上,多个节点以叠加的形式放入栈面板中。

  • javafx.scene.layout.StackPane类的构造方法
构造方法 功能说明
public StackPane() 创建栈面板,面板中的节点默认中心对齐
public StackPane(Node… children) 创建栈面板,并将参数指定的多个节点添加到面板,并中心对齐
  • javafx.scene.layout.StackPane类的常用方法
常用方法 功能说明
public static void clearConstraints(Node child) 删除面板的child节点
public static void setMargin(Node child, Insets value) 为面板中节点设置外侧边缘周围的空白空间的距离
public static void setAlignment(Node child, Pos value) 设置节点child在面板中的对齐方式,value是取自枚举Pos中的枚举常量
public final void setAlignment(Pos value) 设置节点的整体对齐方式
  • javafx.geometry.Pos类中代表对齐方式常用的静态常量
静态常量名 对齐方式
TOP_CENTER 顶部居中对齐
TOP_LEFT 顶部左对齐
TOP_RIGHT 顶部右对齐
CENTER 中部居中对齐
CENTER_LEFT 中部左对齐
CENTER_RIGHT 中部右对齐
BOTTOM_CENTER 底部居中对齐
BOTTOM_LEFT 底部左对齐
BOTTOM_RIGHT 底部右对齐
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
//创建栈面板,将在其上放置两个按钮,并用样式属性设置按钮和栈面板的外观样式。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;

public class App14_3 extends Application {
Button bt = new Button("确定");

@Override
public void start(Stage primaryStage) {
StackPane sPane = new StackPane();
bt.setStyle("-fx-border-color: blue");

Button bt1 = new Button("按钮1");
bt1.setPrefSize(80, 50);
bt1.setStyle("-fx-border-color: green");
bt1.setRotate(-45);

sPane.getChildren().addAll(bt1, bt);
sPane.setRotate(45);
sPane.setStyle("-fx-border-color: red; -fx-background-color: lightgray");
Scene scene = new Scene(sPane, 180, 100);

primaryStage.setTitle("栈面板");
primaryStage.setScene(scene);
primaryStage.show();
}
}

默认情况下,一个控件系统会基于其中的内容计算出默认的尺寸,并将它作为偏好尺寸。

流式面板类FlowPane

javafx.scene.layout.FlowPane

将节点按水平方式一行一行地摆放,或者是按垂直方式一列一列地摆放。

  • 节点按照加入流式面板的先后顺序从左向右排列摆放,或者是从上向下排列摆放;
  • 一行或一列排满节点之后就自动地转到下一行或下一列继续从左向右或从上向下排列;
  • 每一行或每一列中的组件默认设置为居中排列。

  • javafx.scene.layout.FlowPane类的主要构造方法

构造方法 功能说明
public FlowPane() 创建流式水平布局面板,容器中的节点居中对齐,节点间水平和垂直间距均默认为0像素
public FlowPane(double hgap, double vgaps) 功能同上,但节点间水平间距为hgap像素,垂直间距为vgap像素
public FlowPane(Orientation orientation) 创建节点排列方向为orientation、节点间水平和垂直间距均默认为0像素的流式面板。
orientation取值为Orientation. HORIZONTAL,表示水平布局;
Orientation.VERTICAL,表示垂直布局
public FlowPane(double hgap, double vgap, Node… children) 创建流式面板,并将参数指定的多个节点添加到面板中,节点间水平间距为hgap像素,垂直间距为vgap像素
public FlowPane(Orientation orientation, Node… children) 创建节点排列方向为orientation,并将參数指定的多个节点添加到面板中,节点水平和垂直间距均默认为0像素
  • javafx.scene.layout.FlowPane类及父类中的常用方法
常用方法 功能说明
public final void setHgap(double value) 设置布局面板中各节点之间水平间距的像素数
public final void setVgap(double value) 设置布局面板中各节点之间垂直间距的像素数
public final void setOrientation(Orientation value) 设置流式布局中节点的摆放方向,orientation取值见上表
public final void setAlignment(Pos value) 设置布局面板中整体对齐方式,value是枚拳Pos中的值
1
2
//设置面板边缘内侧四周空白的距离
rootNode.setPadding(new Insets(12, 13, 14, 15));

边界面板类BoderPane

类javafx.scene.layout.BorderPane

边界面板将显示区域分为上(top)、下(bottom)、左(left)、右(right)、中(center)五个区域,每个区域可以放置一个控件或其他面板,每个区域的大小是任意的,如果程序不需要某个区域,可以不定义,也不用留出空间。

  • javafx.scene.layout.BorderPane类的构造方法
构造方法 功能说明
public BorderPane() 创建边界式面板对象
public BorderPane(Node center) 用指定节点center为中央区域控件创建边界式面板对象
public BorderPane(Node center, Node top, Node right, Node bottom, Node left) 创建边界式面板对象,并指定每个区域的节点
  • javafx.scene.layout.BorderPane类的常用方法
常用方法 功能说明
public final void setTop(Node value) 将节点value放置在边界式面板的顶部区域
public final void setBottom(Node value) 将节点value放置在边界式面板的底部区域
public final void setLeft(Node value) 将节点value放置在边界式面板的左部区域
public final void setRight(Node value) 将节点value放置在边界式面板的右部区域
public final void setCenter(Node value) 将节点value放置在边界式面板的中央区域
public static void setAlignment(Node child, Pos value) 设置节点的对齐方式

如果要将某个区域的节点移除,如将顶部区域的节点删除,可以调用rootPane.setTop(null)方法来完成。如果一个区域没有被占用,那么不会分配空间给这个区域。

网格面板类GridPane

javafx.scene.layout.GridPane

网格面板类似表格,由行和列组成的单元格用来放置节点。一个节点可以被放于任何单元格内,也可以根据需要占用多行或者多列摆放。

  • javafx.scene.layout.GridPane类的构造方法
构造方法 功能说明
public GridPane() 创建网络面板
  • javafx.scene.layout.GridPane类及父类中的常用方法
常用方法 功能说明
public final void setHgap(double value) 设置面板中节点间的水平间距为value像素
public final void setVgap(double value) 设置面板中节点间的垂直间距为value像素
public void add(Node child, int columnIndex, int rowIndex) 将节点child添加到网格面板的第columnIndex列和第rowIndex行单元格中
public void add(Node child, int columnIndex, int rowIndex, int colspan, int rowspan) 将节点添加到指定单元格中,并占用colspan列和rowspan行
public static void setConstrains(Node child, int columnIndex, int rowIndex) 将节点添加到指定的单元格中
public static void setConstrains(Node child, int columnIndex, int rowIndex, int columnspan, int rowspan) 将节点添加到指定的单元格中,并占用columnspan列和rowspan行
public void addColumn(int columnIndex, Node… children) 将参数指定的多个节点添加到指定的列
public void addRow(int rowIndex, Node… children) 将参数指定的多个节点添加到指定的行
public static Integer getClumnIndex(Node child) 返回给定节点child的列序号
public static Integer getRowIndex(Node child) 返回给定节点child的行序号
public static void setColumnIndex(Node child, Integer value) 将节点设置到新的列,该方法重新定位节点
public static void setColumnIndex(Node child, Integer value) 将节点设置到新的行,该方法重新定位节点
public final void setGridLinesVisible(boolean value) 设置是否显示网格线,默认值为false
public final void setAlignment(Pos value) 设置节点的对齐方式

单行面板类HBox和单列面板类VBox

javafx.scene.layout.HBox

单行面板也称水平面板,是在一行沿水平方向排列节点的方式。

  • javafx.scene.layout.HBox类的构造方法
构造方法 功能说明
public HBox() 创建一个空的单行面板
public HBox(double spacing) 创建单行面板,其上节点的间距为spacing像素
public HBox(Node… children) 创建单行面板,并将参数指定的多个节点添加到面板中,节点的间距为0像素
public HBox(double spacing, Node… children) 创建单行面板,并将参数指定的多个节点添加到面板中,节点间距为spacing像素
  • javafx.scene.layout.HBox类及父类中的常用方法
常用方法 功能说明
public final void setSpacing(double value) 设置面板中节点之间的间距
public static void setMargin(Node child, Insets value) 为面板中的节点设置外边距
pulic final void setAlignment(Pos value) 设置面板中节点整体对齐方式,value是枚举Pos中的值

Group

javafx.scene.Group,

Group是Parent的子类,不是Pane的子类。

Group 面板是一个组, 它包含一个可观察列表类ObservableList的对象,用于存放组的节点,这些节点只是按照出现在改组中的顺序显示,并不负责节点的布局,所以添加到Group中的控件通常需要绝对定位。

Group的主要作用是将一组节点组织在一起,并允许这些节点作为一个组进行操作。

Group是一个可以通过坐标设置控件位置的容器,而且控件和控件之间可以重叠,例如把两个控件的layoutX以及layoutY坐标都设置为0,那么这两个控件都会在Group的左上角出现,同时会重叠。

JavaFX的辅助类

辅助类helper class是用来描述节点属性的

  • 颜色类Color
  • 字体类Font
  • 图像类Image
  • 图像显示类ImageView

辅助类不都是Node类的子类

颜色类Color

javafx.scene.paint.Color是抽象类Paint的子类,Paint是用于绘制节点的类

在JavaFX中每一种颜色都看成是由红、绿、蓝三原色和透明度组成

  • javafx.scene.paint.Color类的构造方法
构造方法 功能说明
public Color(double red, double green, double blue, double opacity) 用指定的red/green/blue三原色和透明度opacity创建对象
  • javafx.scene.paint.Color类中的常用方法
常用方法 功能说明
public static Color color(double red, double green, double blue) 用指定的red、green、blue值创建一个不透明的Color对象。参数取值范围均为0.0~1.0,与构造方法意义相同。
public static Color color(double red, double green, double blue, double opacity) 用指定的red、green、blue值及透明度opacity创建Color对象。参数取值范围均为0.0~1.0,与构造方法意义相同。
public static Color rgb(int red, int green, int blue) 用指定的red、green、blue值创建一个不透明的Color对象。参数取值范围均为0~255,与构造方法意义相似
public static Color rgb(int red, int green, int blue, int opacity) 用指定的red、green、blue值及透明度opacity创建Color对象。颜色参数取值范围均为0~255,opacity取值在0.0~1.0。
public Color brighter() 返回一个具有更大red、green、blue值的Color对象
public Color darker() 创建一个比Color对象更暗的Color对象
  • javafx.scene.paint.Color类中常用的代表颜色的静态常量
静态常量名 代表颜色
BEIGE 浅褐色
BROWN 棕色
GOLD 金色
LIGHTGRAY 浅灰色
ORANGE 桔黄色
SILVER 银色
BLACK 黑色
CYAN 蓝青色
GRAY 灰色
MAGENTA 红紫色
PINK 粉红色
WHITE 白色
BLUE 蓝色
DARKGRAY 深蓝色
GREEN 绿色
NAVY 深蓝色
RED 红色
YEALLOW 黄色

字体类Font

javafx.scene.text.Font

描述字体名、字体粗细和字体大小的类。

  • javafx.scene.text.Font类的构造方法
构造方法 代表颜色
public Font(double size) 创建字体大小为size的字体对象,使用默认的System字体。size 的单位是磅值,1磅值为1/72英寸
public Font(String name, double size) 用给定的字体名称name和大小为size的值创建字体对象
  • javafx.scene.text.Font类的常用方法
常用方法 代表颜色
public static Font font(String family, double size) 创建字体名为family,大小为size的Font对象
public static Font font(String family, FontWeight weight, double size) 创建指定名称、字体粗细和大小的字体对象。字体粗细weight的取值在枚举FontWeight中定义,常用有BOLD(粗体) 、LIGHT(轻体)、NORMAL(正常体)
public static Font font(String family, FontWeight weight, FontPosture posture, double size) 创建指定名称、字体粗细、字体形态和大小的字体对象。字体形态posture的取值在枚举FontPosture中定义,为ITALIC(斜体)和默认的REGULAR(正常体)
public final String getFamily() 返回系统默认的字体
public static List < String > getFamilies() 返回字体集名称的列表
public static List < String > getFontNames() 返回所有字体完整名称的列表,包括字体集和粗细

图像类Image和图像显示类ImageView

JavaFX支持的图像格式有.jpg、.gif、.png和.bmp等。

  • javafx.scene.image.Image类的构造方法
构造方法 代表颜色
public Image(String url) 用图像的url地址创建图像
public Image(String url, boolean backgroundLoading) 用图像的url地址创建图像,并设置是否在后台加载(异步加载)图像
public Image(String url, double requestedWidth, double requestedHeight, boolean preserveRatio, boolean smooth) 创建图像,并指定图像边界框的宽和高(像素),preserveRatio用于设置是否保持图像的高宽比,smooth用于设置是否使用平滑图像算法显示图像
public Image(String url, double requestedWidth, double requestedHeight, boolean preserveRatio, boolean smooth, boolean backgroundLoading) 参数意义同上,并设置是否在后台加载图像

ImageView对象是一个可以显示图像的对象。
ImageView是一个包装器对象,用来引用Image对象。

  • javafx.scene.image.ImageView类的构造方法
常用方法 代表颜色
public ImgaeView() 创建一个不包含图像的lmageView对象
public imageView(String url) 用指定图像对象的url创建ImageView对象
public imageView(Image image) 用指定图像对象image创建ImageView对象
  • javafx.scene.image.ImageView类的常用方法
常用方法 代表颜色
public final void setImage(Image value) 设置显示的图像
public final void setFitWidth(double value) 设置图像视图的宽度为value像素
public final void setFitHeight 设置图像视图的高度为value像素
public final void setPreserveRatio(boolean value) 设置图像是否保持缩放比例
public final void setSmooth(boolean value) 设置是否使用平滑图像算法显示图像
public final void setViewport(Rectangle2D value) 设置图像显示窗口,Rectangle2D对象value中需给出x坐标、y坐标、宽度和高度的像素值

在ImageView类定义了x和y属性,用于表示ImageView图像视图的原点坐标。

image属性表示图像。fitWidth和fitHeight两个属性表示图像改变大小后将边界框调整到适合图像的宽度和高度。

1
2
3
4
5
6
7
8
Image img = new Image("image/test.jpg");
ImageView iv2 = new ImageView();
iv2.setImage(img); //绑定组件

iv2.setFifWidth(80); //视图宽度为80像素
iv2.setPreserveRatio(true); //设置保持缩放比例
iv2.setSmooth(true); //设置平滑显示图像
iv2.setCache(true); //设置缓冲以提高性能

一个Image对象可以被多个ImageView对象所共享,本例中图像对象im被两个ImageView对象iv2和iv3所共享。

但ImageView对象是不可以共享的,即不能将一个ImageView对象多次放入一个面板或一个场景中。

由于ImageView类也是Node类的子类,因此也可以对它进行变换、缩放和模糊等特效操作。

JavaFX的属性绑定和绑定属性

以将一个目标对象与一个源对象绑定,如果源对象中的值改变了,目标对象的值也将自动改变。

目标对象称为绑定对象或绑定属性,源对象称为可绑定对象或可观察对象。

目标对象与源对象的绑定是通过javafx.beans.property.Property接口中定义的void bind(ObservableValue < ? extends T > observable)方法实现的。

1
target.bind(source); //源对象source相当于自变量,目标对象target相当于因变量

JavaFX类中声明绑定属性的类型是形如XxxProperty样式。

JavaFX为基本类型、字符串类型和集合类型定义了绑定属性类型。如基本类型double的绑定属性类型是DoubleProperty,该类型是抽象类,所以不能用它创建对象,而必须用其子类SimpleDoubleProperty来创建具体的对象。

  • JavaFX部分数据类型与其绑定属性类型及用于创建属性绑定对象所对应的子类
类型 绑定属性类型(抽象类) 用于创建绑定属性对象的子类
int IntgerProperty SimpleIntgerProperty
long LongProperty SimpleLongProperty
float FloatProperty SimpleFloatProperty
double DoubleProperty SimpleDoubleProperty
boolean BooleanProperty SimpleBooleanProperty
String StringProperty SimpleStringProperty
List ListProperty SimpleListProperty
Set SetProperty SimpleSetProperty
Map MapProperty SimpleMapProperty

虽然绑定属性要用相应的绑定属性类型来声明,但创建该绑定属性时却要用其相应的子类来创建。

绑定属性:在类中声明为一种特殊数据类型的成员变量。

属性绑定:两个绑定属性之间建立一个绑定关系,这样当源对象的绑定属性值发生变化时,目标对象的绑定属性就会随之变化。

1
2
3
4
5
6
7
8
Pane pane = new Pane();

Circle c = new Circle();
c.setCenterX(100);
c.setCenterY(100);

c.centerXProperty().bind(pane.widthProperty().divide(2));
c.centerYProperty().bind(pane.heightProperty().divide(2));

对于数值类型的绑定属性,如DoubleProperty()都具有add()substract()multiply()divide()方法。

JavaFX属性的主要功能是属性绑定和事件处理。

通过属性的addListener()方法可以为其注册监听者,通过属性的bind()方法可以实现属性绑定。

利用bind()方法进行属性绑定时,只是目标对象随着源对象的变化而变化,这种绑定称为单向绑定
有时候需要同步两个属性,即目标和源双方都既是绑定对象也是可观察对象,这时可使用bindBidirectional()方法进行属性的双向绑定

属性双向绑定后,两者中不管哪一个发生变化,另一方也会被相应地更新。

JavaFX常用控件

标签、按钮、复选框、单选按钮、文本框、文本区、组合框、列表视图等,控件是节点Node的子类。

与面板不同,控件类对象不能再包含其他控件,控件的作用是完成与用户的交互,包括接收用户的命令、接收用户的输入或用户的选择或向用户显示信息等。

控件名称 类名 控件名称 类名
标签 Label 菜单条 MenuBar
命令按钮 Button 菜单 Menu
单选按钮 RadioButton 菜单项 MenuItem
文本框 TextField 单选菜单按钮 RadioMenuItem
密码文本框 PsswordField 复选菜单按钮 CheckMenuItem
文本区 TextArea 弹出菜单 ContextMenu
复选框 CheckBox 滚动条 ScrollBar
组合框 ComboBox 进度条 ProgressBar
选择框 ChoiceBox 滑动条 Slider
列表视图 ListView 工具栏 ToolBar
表格视图 TableView 工具提示 ToolTip
树视图 TreeView 颜色选择器 ColorPicker
选项卡面板 TabPane 日期选择器 DatePicker
选项卡 Tab 对话框 Dialog
微调选择器 Spinner 超链接 Hyperlink

标签类Label

javafx.scene.control.Label

用来显示文字、图片的控件,标签上的内容只能显示不可编辑,所以标签常用来给文本控件或其他控件作为标签用。

  • javafx.scene.control.Label类的构造方法
控件名称 类名
public Label() 创建一个没有文字与图像的标签
public Label(String text) 创建标签,并以text为标签上的文字
public Label(String text, Node graphic) 以text为文字、以graphic为图形创建标签

以Labeled类中定义的方法可为标签和按钮所共用

  • javafx.scene.control.Labeled类中标签和按钮的常用方法
控件名称 类名
public final void setText(String value) 设置控件上的文本
public final void setFont(Font value) 设置控件上的字体
public final void setGraphic(Node value) 设置控件上的图形为value
public final vaoid setAlignment(Pos value) 设置控件上文本和节点的对齐方式为value, value的取值是枚举Pos中的枚举常量
public final void setTextFill(Paint value) 设置文本的颜色
public final void setWrapText(boolean value) 设置如果文本超出宽度,是否自动换行
public final void setUnderline(boolean value) 设置文本是否加下画线
public fianl void setConetntDisplay(ContentDisplay value) 使用枚举ContentDisplay的常量值TOP、BOTTOM、LEFT和RIGHT等设置节点相对于文本的位置

文本编辑控件TextField、PasswordFiled、TextArea与滚动面板ScrollPane

文本编辑控件是可以接收用户的文本输入并具有一定编辑功能的界面元素。

文本编辑控件分为三种:

  • 第一种是单行文本编辑控件,简称文本框,也称文本行;
  • 第二种是密码文本框控件,是通过PasswordField类实现的;
  • 第三种是多行文本编辑控件,简称文本区,是通过TextArea类实现的。

TextField类和TextArea类是javafx.scene.control.TextInputControl类的子类,而PasswordField类是TextField的子类。

  • javafx.scene.control.TextInputControl类的常用方法
常用方法 类名
public void appendText(String text) 将文本text追加到输入框中
public void clear() 清除文本控件中的所有文本
public void deleteText(int start, int end) 在文本控件中删除start与end之间的文本
public final String getSelectedText() 返回选中的文本
public final String getText() 返回文本控件中的所有文本
public String getText(int start, int end) 返回start与end之间的文本
public final void setEditable(boolean value) 设置文本组件是否可编辑
public final boolean isEditable() 判断文本组件是否可编辑
public void paste() 将剪贴板中的内容粘贴到文本中,用于替换当前选择的文本。如果没有选择的文本,则插人到当前光标所在的位置
public void selectAll() 选中文本控件中的所有文本
public final void setFont(Font value) 设置文本控件中文本的字体
public fianl void setText(String value) 将字符串value设置为文本控件中的文本
public final void setPromptText(String value) 设置文本框的提示文本

文本框控件TextField

  • javafx.scene.control.TextField类的构造方法
构造方法 功能说明
public TextField() 创建一个不包含文本的空白文本框
public TextField(String text) 创建初始文本为text的文本框
  • javafx.scene.control.TextField类的常用方法
常用方法 功能说明
public final void setAlignment(Pos value) 设置文本框中文本的对齐方式,value是枚举Pos中的值
public final void setPrefColumnCount(int value) 设置文本框的显示宽度为value列
public final void setOnAction(EventHandler < ActionEvent > value) 设置文本框动作事件监听者

密码文本框控件PasswordField

javafx.scene.control.PasswordField

只有一个无参的构造方法public PasswordField()。密码文本框控件多用其父类的方法。

文本区控件TextArea与滚动面板ScrollPane

javafx.scene.control.TextArea

文本区实际上是多行文本输入框,因为文本框只能输入一行文字,所以在需要输入和显示较多的文字时, 就可使用文本区。

  • javafx.scene.control.TextArea类的构造方法
构造方法 功能说明
public TextArea() 创建一个不包含文本的空文本区
public TextArea(String text) 创建一个默认文本为text的文本区
  • javafx.scene.control.TextArea类的常用方法
常用方法 功能说明
public final void setPrefColumnCount(int value) 设置文本区的显示列数为value
public final void setPreRow(int value) 设置文本区的显示行数为value
public final void setWrapText(boolean value) 设置当文本区行的长度大于文本区的宽度时是否自动换行,Value的默认值为false,不换行

文本区中显示的文本行数和列数都有可能超出文本区的范围,这时就需要使用滚动条来进行滚动操作。

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
//在窗口中利用面板组织文本编辑控件,并利用滚动面板实现文本区的滚动功能。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextArea;
import javafx.scene.layout.GridPane;
import javafx.scene.control.ScrollPane;
import javafx.geometry.Insets;

public class App14_11 extends Application {
final Label lab1 = new Label("用户名: ");
final Label lab2 = new Label("密码: ");
final PasswordField pf = new PasswordField();
final TextField tf = new TextField();
final TextArea ta = new TextArea("你好,我是文本区");

@Override
public void start(Stage primaryStage) {
GridPane rootGP = new GridPane();
rootGP.setPadding(new Insets(10,8,10,8));
rootGP. setHgap(5);
rootGP. setVgap(5);

tf.setPromptText("输人用户名");
rootGP.add(lab1, 0, 0);
rootGP.add(tf, 1, 0);

pf.setPromptText("输人密码");
rootGP.add(lab2, 0, 1);
rootGP.add(pf, 1, 1);

Button bt1 = new Button("确认密码");
Button bt2 = new Button("编辑文本");
rootGP.add(bt1,0, 2);
rootGP.add(bt2,1,2);

final ScrollPane scro = new ScrollPane(ta);
ta.setPrefColumnCount(12);
ta.setEditable(false);

rootGP.add(scro, 2, 0, 4, 3);
Scene scene = new Scene(rootGP, 400, 120);
primaryStage.setTitle("网格与文本控件");
primaryStage.setScene(scene) ;
primaryStage.show();
}
}

JavaFX的任何节点都可放置在滚动面板ScrollPane中。如果控件太大以致不能在显示区内完整显示时,滚动面板ScrollPane提供了垂直和水平方向的滚动支持。

复选框CheckBox和单选按钮RadioButton

javafx.scene.control.CheckBox
javafx.scene.control.RadioButton

复选框和单选按钮都是让用户选取项目的一种组件,用户利用该组件来获得相应的输入。

其中复选框可以单独使用,而单选按钮必须配合javafx.scene.control.ToggleGroup类将其组成单选按钮组来使用,所有隶属于同一ToggleGroup组的RadioButton组件具有互斥属性。

  • javafx.scene.control.CheckBox类的构造方法
构造方法 功能说明
public CheckBox() 创建一个没有文字、初始状态未被选中的复选框
public CheckBox(String box) 创建一个以text为文字、初始状态未被选中的复选框
  • javafx.scene.control.CheckBox类的常用方法
常用方法 功能说明
public final void setSelected(boolean value) 设置复选框是否被选中
public final boolean isSelected 判断复选框是否被选中,若选中则返回true,否则返回false
public final void setText(String value) 设置复选框上文字为value
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
//在窗口中组织复选框和单选按钮。
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.CheckBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.geometry.Pos;

public class App14_12 extends Application {
final CheckBox chk1 = new CheckBox("粗体");
final CheckBox chk2 = new CheckBox("斜体");
final CheckBox chk3 = new CheckBox("楷体");
final RadioButton rb1 = new RadioButton("红色");
final RadioButton rb2 = new RadioButton("绿色");
final RadioButton rb3 = new RadioButton("蓝色");
final Button bt1 = new Button("确认");
final Button bt2 = new Button("取消");
final TextArea ta = new TextArea("我是文本区");

@Override
public void start(Stage primaryStage) {
chk2.setSelected(true);
VBox vbL = new VBox(3);
vbL.getChildren().addAll(chk1, chk2, chk3);

rb1.setSelected(true);
final ToggleGroup gro = new ToggleGroup();
rb1.setToggleGroup(gro);
rb2.setToggleGroup(gro);
rb3.setToggleGroup(gro);
VBox vbR = new VBox(3);
vbR.getChildren().addAll(rb1, rb2, rb3);

HBox hB = new HBox(20);
hB.getChildren().addAll(bt1, bt2);
hB.setAlignment(Pos.CENTER);

BorderPane rootBP = new BorderPane();
ta.setPrefColumnCount(10); //宽度10列
ta.setPrefRowCount(3) ; //显示高度3行
ta.setWrapText(true); //自动换行

rootBP.setLeft(vbL);
rootBP.setRight(vbR);
rootBP.setCenter(ta);
rootBP.setBottom(hB) ;

Scene scene = new Scene( rootBP);
primaryStage.setTitle("复选框与单选按钮");
primaryStage.setScene( scene) ;
primaryStage.show();
}
}

选项卡面板TabPane和选项卡Tab

在JavaFX中选项卡是由javafx.scene.control.Tab类实现,选项卡必须放入选项卡面板中,选项卡面板是由javafx.scene.control.TabPane类实现的。

可以把多个组件放在多个不同选项卡中,从而使页面不致拥挤,其选项卡的形式也能为程序增色不少。
用户只需单击每个选项卡的标题,就可以切换到不同的选项卡。
选项卡面板中的每个选项卡都可以直接放入节点,也可以添加一个面板来组织其他节点。

  • javafx.scene.control.TabPane类的构造方法
构造方法 功能说明
public TabPane() 创建一个不含选项卡的选项卡面板对象
public TabPane(Tab… tabs) 创建选项卡面板,并将参数指定的多个选项卡添加到选项卡面板中
  • javafx.scene.control.TabPane类的常用方法
常用方法 功能说明
public final void setTabMaxHeight(double value) 设置选项卡面板的最大高度值为value
public final void setTabMaxWidth(double value) 设置选项卡面板的最大宽度值为value
public final void setTabMinHeight(double value) 设置选项卡面板的最小高度值为value
public final void setTabMinWidth(double value) 设置选项卡面板的最小宽度值为value
public final ObservableList < Tab > getTabs() 返回选项卡面板中的节点列表
  • javafx.scene.control.Tab类的构造方法
构造方法 功能说明
public Tab() 创建一个不含标题的选项卡对象
public Tab(String text) 创建一个标题为text的选项卡对象
public Tab(String text, Node content) 创建一个标题为text且包含节点content的选项卡对象
  • javafx.scene.control.Tab类的常用方法
常用方法 功能说明
public final void setContent(Node value) 设置选项卡上包含的节点为value
public final void setTooltip(Tooltip value) 当鼠标悬停在选项卡上时提示信息为value
public final void setText(String value) 设置选项卡的标题为value
public final void setStyle(String value) 设置选项卡的样式
public final void setClosable(boolean value) 设置选项卡是否可以被关闭

本章小结

  • JavaFX的主类必须继承javafx.application.Application类并实现start()方法。JVM自动创建一个主舞台对象并将该对象的引用传递给start()方法。
  • 任何JavaFX程序至少要有一个舞台和一个场景,舞台和场景共同构建了JavaFX程序的图形界面,它是构建应用程序的起点。
  • 场景Scene中可以包含面板Pane或控件Control,但不能包含形状Shape和图像显示类ImageView。
  • 虽然可以直接将节点置于场景中,但更好的办法是先将节点放入面板中,然后再将面板放入场景中。Pane类的对象通常用作显示形状的画布,但其子类面板主要用于包含和组织节点。
  • 场景图是场景中所有节点构成的树形结构图。
  • Node类是所有节点的根类,该类中定义的属性和方法被其子类所共享。
  • Pane类是所有面板的基类,该类的getChildren()方法返回值是一个ObservableList对象,该对象是一个用于存储面板中节点的列表。
  • 使用javafx.scene.image.Image类装载图像, 用javafx.scene.image.ImageView类显示图像。
  • 绑定属性和属性绑定是两个不同的概念。绑定属性是指在类中声明为一种特殊数据类型的成员变量;而属性绑定则是指在两个绑定属性之间建立起一种绑定关系,这样当原对象的绑定属性值发生变化时,目标对象的绑定属性值就会随之变化。
  • 声明绑定属性时,必须用绑定属性类型来声明绑定属性。
  • 因为ToggleGroup不是节点类Node的子类,所以ToggleGroup类创建的单选按钮组对象不能加入到面板中。
  • JavaFX的任何节点都可放置在滚动面板ScrollPane中。

课后习题

  • JavaFX窗口的结构包含哪些内容?
  • JavaFX程序的主舞台是如何生成的?主舞台与其他舞台有何区别?如何显示一个舞台?
  • 如何创建Scene对象?如何在舞台中设置场景?
  • 什么是节点?什么是面板?什么是场景图?
  • 可以直接将控件Control和面板Pane加入到场景Scene中吗?可以直接将形状Shape或者图像视图ImageView加入到场景中吗?
  • 什么是属性绑定?单向绑定和双向绑定有何区别?是否所有属性都可进行双向绑定?
  • 创建Color对象一定要用其构造方法吗?创建Font对象一定要用其构造方法吗?
  • 编程实现输出系统中所有可用的字体?
  • 可以将一个Image设置到多个ImageView上吗? 可以将一个ImageView显示多次吗?
  • 如何将一个节点加入到面板中?
  • 创建一个HBox面板对象,并设置其上控件间距为10像素,然后将两个带有文字和图像的按钮添加到HBox面板中。
  • 创建一个栈面板对象,并将一幅图像放置在栈面板中,然后将栈面板逆时针旋转45°。
  • 编写一个JavaFX程序,在网格面板中,第一行放置标签和文本框,第二行设置文本区和按钮。
  • 编写一个JavaFX程序,顺时针旋转90°显示三行文字,并对每行文字设置一个随机颜色和透明度,并设置不同的外观样式。
  • 创建一个具有三个选项卡的选项卡面板,在每个选项卡中放置一个带有文字的标签。

第十五章 事件处理

使控件能够响应并处理用户的操作,这就是事件处理。

消息处理、事件驱动是面向对象编程技术的主要特点。

路线:

  • 创建窗口:利用主舞台和场景创建窗口。
  • 创建节点:创建组成图形界面元素的各种节点,如按钮、文本框等。
  • 构建场景图:根据具体需要利用面板组织窗口上各节点的布局。
  • 响应事件:定义图形用户界面的事件和界面各元素对不同事件的响应,从而实现图形用户界面与用户的交互功能。

Java语言的事件处理机制——委托事件模型

用户在界面中输入命令是通过键盘或对特定界面元素(如按钮)单击鼠标来实现的。

基本概念

事件

谓事件(event)就是用户使用鼠标或键盘对窗口中的控件进行交互时所发生的事情。

事件用于描述发生了什么事情,对这些事件做出响应的程序,称为事件处理程序(event handler)。

事件源

谓事件源(event source)就是能够产生事件并触发它的控件,如一个按钮就是按钮单击动作事件的事件源。

事件监听者

把对事件进行处理的方法放在一个类对象中,这个类对象就是事件监听者(listener),简称
监听者。

事件源通过调用相应的方法将某个对象设置为自己的监听者,监听者有专门的方法来处理事件。

当事件源上发生事件时,事件监听者能够监听到,并调用相应的方法对发生的事件做出相应的处理。

事件处理程序

javafx.event包中包含了事件类和用来处理事件的接口。

为了让监听者能对事件源发生的事件进行处理,创建该监听者对象的类必须声明实现相应的监听者接口,即必须在类中具体定义该接口中的所有方法,以供监听者自动调用相应事件处理方法来完成对应事件处理的任务,这些处理事件的方法就是事件处理程序。

委托事件模型

委托事件模型(delegation event model)将事件源(如命令按钮)和对事件做出的具体处理(利用监听者来对事件进行具体的处理)分离开来。

控件(事件源)不处理自己的事件,而是将事件处理委托给外部的处理实体(监听者)。

事件对象(eventobject)表示事件的内容,包含了与事件相关的任何属性,事件对象内部封装了一个对事件源的引用和其他信息,这个事件对象将作为参数自动传递给处理该事件的方法。

委托事件模型就是由产生事件的对象(事件源)事件对象以及事件监听者对象之间所组成的关联关系。

一个监听者可以为很多事件源服务,一个事件源可以有多个相同或不同类型的监听者。

多事件监听:一个控件对应多个事件。

单事件监听:多个控件对应一个事件。

事件监听者必须是一个对应的事件监听者接口的实例。JavaFX定义了一个对于事件T的统一的监听者接口EventHandler < T extends Event >

ActionEvent 的每个监听者接口都应实现handle(ActionEvent e)方法,从而处理一个动作事件ActionEvent。

事件监听者对象必须通过事件源进行注册,注册方法依赖于事件类型。

动作事件ActionEvent,事件源是使用setOnAction()方法进行注册。
对于鼠标按下事件,事件源是使用setOnMousePressed()方法进行注册;
对于一个按键事件,事件源是使用setOnKeyPressed()方法进行注册。

定义内部类并让内部类对象来承担监听者

把实现接口的类定义成内部类,内部类可以访问外部类的成员方法与成员变量,包括私有成员。

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
//在一个窗口中摆放两个控件:一个是命令按钮;另一个是文本区。当单击命令按钮后,将文本区中的字体颜色设置为红色。由于按钮触发动作事件,所以触发按钮便把ActionEvent的对象传递给向它注册的监听者,请它负责处理。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.TextArea;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;

public class App15_1 extends Application{
Button bt = new Button("设置字体颜色");
TextArea ta = new TextArea("字体颜色");

@Override
public void start(Stage primaryStage) {
BorderPane bPane = new BorderPane();
bPane.setCenter(ta);
bPane.setBottom(bt);

BorderPane.setAlignment(bt, Pos.CENTER);
Han eh = new Han();
bt.setOnAction(eh);

Scene scene = new Scene(bPane, 180, 100);
primaryStage.setTitle("操作事件");
primaryStage.setScene(scene);
primaryStage.show();
}
class Han implements EventHandler <ActionEvent> {
@Override
public void handle(ActionEvent e) {
ta.setStyle("-fx-text-fill: red");
}
}
}

类在实现监听者接口时,必须在类中具体定义该接口中只声明而未定义的所有方法。因为监听者接口EventHandler < ActionEvent >中只提供了一个handle(ActionEvent e)方法,该方法正是要把事件处理程序编写在里面的方法。

使用匿名内部类来担任监听者

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
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.TextArea;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;

public class App15_2 extends Application {
Button bt = new Button("设置字体颜色");
TextArea ta = new TextArea("字体颜色");

@Override
public void start(Stage primaryStage) {
BorderPane bPane = new BorderPane();
bPane.setCenter(ta);
bPane.setBottom(bt);

BorderPane.setAlignment(bt, Pos.CENTER);

bt.setOnAction(
new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
ta.setStyle("-fx-text-fill: red");
}
}
);

Scene scene = new Scene(bPane, 180, 100);
primaryStage.setTitle("操作事件");
primaryStage.setScene(scene);
primaryStage.show();
}
}

使用Lambda表达式来担任监听者

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
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.TextArea;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;

public class App15_3 extends Application {
Button bt = new Button("设置字体颜色");
TextArea ta = new TextArea("字体颜色");

@Override
public void start(Stage primaryStage) {
BorderPane bPane = new BorderPane();
bPane.setCenter(ta);
bPane.setBottom(bt);

BorderPane.setAlignment(bt, Pos.CENTER);

bt.setOnAction(e -> ta.setStyle("-fx-text-fill: red"));

Scene scene = new Scene(bPane, 180, 100);
primaryStage.setTitle("操作事件");
primaryStage.setScene(scene);
primaryStage.show();
}
}

Java语言的事件类

Java事件类的根是java.util.EventObject,JavaFX事件类的根是javafx.event.Event

1
2
3
//是从事件对象中获取触发事件的事件源
public Object getSource()
//返回的都是Object类型的对象,所以开发人员需要自己编写代码进行对象的强制类型转换。
  • 用户动作、事件源、触发的事件类型和事件注册方法
用户动作 事件源 触发的事件类型 事件注册方法
单击按钮 Button ActionEvent SetOnAction(EventHandler < ActionEvent > e)
在文本框中按Enter键 TextField ActionEvent SetOnAction(EventHandler < ActionEvent > e)
选中或取消选中 RadioButton ActionEvent SetOnAction(EventHandler < ActionEvent > e)
选中或取消选中 CheckBox ActionEvent SetOnAction(EventHandler < ActionEvent > e)
选择一个新选项 ComboBox ActionEvent SetOnAction(EventHandler < ActionEvent > e)
按下鼠标 Node、Scene MouseEvent SetOnMousePressed(EventHandler < MouseEvent > e)
释放鼠标 Node、Scene MouseEvent SetOnMouseReleased(EventHandler < MouseEvent > e)
单击鼠标 Node、Scene MouseEvent SetOnMouseClicked(EventHandler < MouseEvent > e)
鼠标进人 Node、Scene MouseEvent SetOnMouseEntered(EventHandler < MouseEvent > e)
鼠标离开 Node、Scene MouseEvent SetOnMouseExited(EventHandler < MouseEvent > e)
鼠标移动 Node、Scene MouseEvent SetOnMouseMoved(EventHandler < MouseEvent > e)
鼠标拖动 Node、Scene MouseEvent SetOnMouseDragged(EventHandler < MouseEvent > e)
按下键 Node、Scene KeyEvent SetOnKeyPressed(EventHandler < KeyEvent > e)
释放键 Node、Scene KeyEvent SetOnKeyReleased(EventHandler < KeyEvent > e)
单击键 Node、Scene KeyEvent SetOnKeyTyped(EventHandler < KeyEvent > e)

如果一个节点可以触发一个事件,那么这个节点的任何子节点都可以触发同样类型的事件。
如果要删除一个事件源的事件监听者只需用null作为参数,传递给事件注册方法即可。

  • 事件类型、用户动作和事件注册方法所在的类
事件类型 用户操作 时间注册方法所在的类
ActionEvent 单击按钮或选择菜单项 ButtonBase/ComboBoxBase/ContextMenu/MenuItem/TextField
KeyEvent 键盘操作 Node/Scene
MouseEvent 鼠标移动或按下按钮 Node/Scene
MouseDragEvent 按下鼠标、拖放操作 Node/Scene
InputMethodEvent 输人字符操作 Node/Scene
DragEvent 平台支持的拖放操作 Node/Scene
ScrollEvent 对象滚动 Node/Scene
ContextMenuEvent 快捷菜单被请求 Node/Scene
TextEvent 文本事件 Node/Scene
WindowEvent 窗口事件 Node/Scene
ListView.EditEvent ListView条目被编辑 ListView
TreeView.EditEvent TreeView条目被编辑 TreeView
TableColumn.CellEditEvent 表格列被编辑 TableColumn

动作事件ActionEvent

javafx.event.ActionEvent(操作事件)

处理ActionEvent事件时,监听者向事件源注册使用事件源对象.setOnAction(EventHandler < ActionEvent > value)语句,参数value是监听者对象。

鼠标事件MouseEvent

javafx.scene.input.MouseEvent

用鼠标单击事件源、鼠标指针进入或离开事件源,或移动、拖动鼠标等操作均会触发鼠标事件。

  • javafx.scene.input.MouseEvent的常用方法
常用方法 功能说明
public final MouseButton getButton() 返回被单击的鼠标按钮。返回的是枚举值,其含义如下。
MouseButton.PRIMARY:鼠标左按钮;
MouseButton.MIDDLE:鼠标中按钮;
MouseButton.SECONDARY:鼠标右按钮;
MouseButton.NONE:没有鼠标按钮
public final double getX() 返回事件源节点中鼠标点的x坐标
public final double getY() 返回事件源节点中鼠标点的y坐标
public final double getScnenX() 返回场景中鼠标点的x坐标
public final double getScnenY() 返回场景中鼠标点的y坐标
public final double getScreenX() 返回屏幕中鼠标点的x坐标
public final double getScreenY() 返回屏幕中鼠标点的y坐标
public final boolean isAltDown() 如果该事件中Alt键被按下,则返回true
public final boolean isControlDown() 如果该事件中Ctrl键被按下,则返回true
public final boolean isShiftDown() 如果该事件中Shift键被按下,则返回true

面板左上角坐标为(0, 0) ,向右为x轴方向,正向下为y轴方向正,右下角坐标为(pane.getWidth(), pane.getHeight())。

文本类

javafx.scene.text.Text

  • javafx.scene.text.Text的构造方法
构造方法 功能说明
public Text() 创建一个空文本对象
public Text(String text) 以字符串text作为文字创建文本对象
public Text(double x, double y, String text) 以给定的坐标及字符串创建文本对象
  • javafx.scene.text.Text的常用方法
常用方法 功能说明
public final String getText() 返回文本对象中的文字
public final void setText(Stirng value) 设置文本对象中的文字
public final double getX() 返回文本对象的x坐标
public final double getY() 返回文本对象的y坐标
public final void setX(double value) 设置文本对象的x坐标
public final void setY(double value) 设置文本对象的y坐标
public final void setFont(Font value) 设置文本对象中文字的字体
public final void setUnderline(boolean value) 设置文本是否有下画线
public final double getWrappingWidth() 返回文本宽度的像素数
public final void setTextAlignment(TextAlignment value) 设置文本的对齐方式。value 的取值及含义如下。
TextAlignment.CENTER:居中对齐;
TextAlignment.JUSTIFY:两端对齐;
TextAlignment.LEFT:左对齐;
TextAlignment.RIGHT:右对齐
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
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.text.Text;
import javafx.scene.layout.Pane;

public class App15_4 extends Application {
private double tOffX, tOffY;
Text t = new Text(20, 20, "拖动我");

@Override
public void start(Stage stage) {
Pane pane = new Pane();
pane.getChildren().add(t);
Scene scene = new Scene(pane, 200, 100);

t.setOnMousePressed(e -> handleMousePressed(e));
t.setOnMouseDragged(e -> handleMouseDragged(e));

stage.setTitle("拖动操作");
stage.setScene(scene);
stage.show();
}

protected void handleMousePressed(MouseEvent e) {
tOffX = e.getSceneX() - t.getX();
tOffY = e.getSceneY() - t.getY();
}

protected void handleMouseDragged(MouseEvent e) {
t.setX(e.getSceneX() - tOffX);
t.setY(e.getSceneY() - tOffY);
}
}

键盘事件KeyEvent

javafx.scene.input.KeyEvent

当用户在一个节点或一个场景上操作键盘时所触发的事件,如按下释放敲击键盘按键等,都会触发KeyEvent事件。

处理键盘事件KeyEvent的监听者接口是EventHandler < KeyEvent >

  • javafx.scene.input.KeyEvent的常用方法
常用方法 功能说明
public final String getCharacter() 返回按下的Unicode字符
public final KeyCode getCode() 返回按下字符的键值码,键码值由枚举KeyCode定义
public final String getText() 返回键码值对应的字符串
public final boolean isAltDown() 若Alt键被按下则返回true
public final boolean isControlDown() 若Ctrl键被按下则返回true
public final boolean isShiftDown() 若Shift键被按下则返回true
  • 由枚举javafx.scene.input.KeyCode定义的常用键码值表
表示键码的枚举值 键描述 表示键码的枚举值 键描述
A~Z 字母键A~Z UP 上箭头键
0~9 数字键0~9 DOWN 下箭头键
F1~F12 功能键F1~F12 LEFT 左箭头键
HOME Home键 RIGHT 右箭头键
END End键 KP_UP 小键盘上的上箭头键
PAGE_UP PageUp键 KP_DOWN 小键盘上的下箭头键
PAGE_DOWN PageDown键 KP_LEFT 小键盘上的左箭头键
CONTROL Ctrl键 KP_RIGHT 小键盘上的右箭头键
SHIFT Shift键 COMMA 逗号键
ALT Alt键 SEMICOLON 分号键
TAB Tab键 COLON 冒号键
ESCAPE Esc键 PERIOD .键
ENTER Enter键 SLASH /键
INSERT Insert键 BACK_SLASH \键
DELETE Del键 QUOTE 左单引号‘ 键
CAPS 大写字母锁定键 BACK_QUOTE 右单引号’键
NUM_LOCK 数字锁定键 OPEN_BRACKET [键
PAUSE 暂停键 CLOSE_BRACKET ]键
PRINTSCREEN 打印屏幕键 EQUALS =号键
BACK_SPACE 退格键 NUMPAD0~NUMPAD9 小键盘上0~9键
SPACE 空格键 CANCLE 取消键
UNDERSCORE 下画线 CLEAR 清除键
WINDOWS Windows键 UNDEFINED 是未知的键

复选框和单选按钮及相应的事件处理

单击一个 复选框CheckBox/单选按钮RadioButton 将其选中或取消选中时,将会触发动作事件ActionEvent。

要判断一个 复选框/单选按钮 是否被选中,可以调用isSelected()方法。

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
//利用复选框和单选按钮设置文本对象上文字的字体和颜色

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.control.CheckBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.FontPosture;
import javafx.scene.layout.VBox;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;

public class App15_6 extends Application {
Font fN = Font.font("Times New Roman", FontWeight.NORMAL, FontPosture.REGULAR, 16);
Font fB = Font.font("Times New Roman", FontWeight.BOLD, FontPosture.REGULAR, 16);
Font fI = Font.font("Times New Roman", FontWeight.NORMAL, FontPosture.ITALIC, 16);
Font fBI = Font.font("Times New Roman", FontWeight.BOLD, FontPosture.ITALIC, 16);

CheckBox chkB = new CheckBox("粗体");
CheckBox chkI = new CheckBox("斜体");

RadioButton r = new RadioButton("红色");
RadioButton g = new RadioButton("绿色" );
RadioButton b = new RadioButton("蓝色");

Text t = new Text("复选框和单选按钮及相应的事件处理");

@Override
public void start(Stage primaryStage) {
VBox vbL= new VBox(20);
vbL.setStyle("-fx-border-color: green");
vbL.getChildren().addAll(chkB, chkI);

ToggleGroup gro = new ToggleGroup();
r.setToggleGroup(gro);
g.setToggleGroup(gro);
b.setToggleGroup(gro);
VBox vbR = new VBox();
vbR.setStyle("-fx-border-color: blue");
vbR.getChildren().addAll(r, g, b);

BorderPane rootBP = new BorderPane();
t.setFont(fN);
rootBP.setLeft(vbL);
rootBP.setRight(vbR);
rootBP.setCenter(t);

Han hand = new Han();
r.setOnAction(hand);
g.setOnAction(hand);
b.setOnAction(hand);
chkB.setOnAction(hand);
chkI.setOnAction(hand);

Scene scene = new Scene(rootBP, 260, 60);
primaryStage.setTitle("复选框与单选按钮");
primaryStage.setScene(scene);
primaryStage.show();
}

class Han implements EventHandler <ActionEvent> {
@Override
public void handle(ActionEvent e) {
if(r.isSelected())
t.setFill(Color.RED);
if(g.isSelected())
t.setFill(Color.GREEN);
if(b.isSelected())
t.setFill(Color.BLUE);

if(chkB.isSelected() && chkI.isSelected())
t.setFont(fBI);
else if(chkB.isSelected())
t.setFont(fB);
else if(chkI.isSelected())
t.setFont(fI);
else
t.setFont(fN);
}
}
}

文本编辑控件及响应的事件处理

控件类TextField是单行文本框,用于接收用户输入的文本。

密码文本框PresswordField是TextField的子类,在密码文本框中输入的文本不回显,字符显示一个黑点。

组合框及相应的事件处理

组合框(combo box)也称为下拉列表框(drop-down list)
javafx.scene.control.ComboBox < T >

组合框有两种非常不一样的模式:
一种是默认状态下的不可编辑模式,在这种模式下用户只能在下拉列表提供的内容中选择一项;
另一种是可编辑模式,其特点是可以在显示栏中输入组合框列表中不包括的内容。

JavaFX是用带有类型参数的泛型类ComboBox < T >来创建组合框控件,类型参数T为保存在组合框中的元素指定数据类型。

  • javafx.scene.control.ComboBox < T >类的构造方法
构造方法 功能说明
public ComboBox() 创建空的组合框对象
public ComboBox(ObservableList < T > items) 创建一个具有指定选项items的组合框

javafx.collections.ObservableList < T >是一个集合,它定义了一个可观察对象的列表,它能够在添加、更新和删除对象时通知控件。

javafx.collections.FXCollections类中提供的静态方法observableArrayList(ArrayOfElements)用数组ArrayOfElements的元素创建一个ObservableList类对象。

  • javafx.scene.control.ComboBox < T >类的常用方法
常用方法 功能说明
public final void setValue(T value) 设置在组合框中选中的选项值为value
public final T getValue() 返回在组合框中选中的选项值
public final void setItems(ObservableList < T > value) 用value设置组合框中的选项值
public final ObservableList < T > getItems() 返回组合框中存储元素的列表
public final void setEditable(boolean value) 设置组合框是否可编辑
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
//在组合框中显示若干个颜色选项,当选中某个颜色时,将文本区中的文本设置为所选颜
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.collections.FXCollections;
import javafx.scene.control.ComboBox;
import javafx.collections.ObservableList;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;

public class App15_8 extends Application {
private ComboBox<String> cbo = new ComboBox<String>();
private String[] color = {"红色", "绿色", "蓝色"};
private TextArea ta = new TextArea("我喜欢用JavaFX编程");

@Override
public void start(Stage primaryStage) {
ObservableList<String> items = FXCollections.observableArrayList(color);
cbo.getItems().addAll(items);
cbo.setPrefWidth(180);
cbo.setValue("红色");

BorderPane bPane = new BorderPane();
ta.setPrefColumnCount(10);
bPane.setTop(cbo);
bPane.setCenter(ta);

cbo.setOnAction(
new EventHandler <ActionEvent>() {
@Override
public void handle(ActionEvent e) {
if(cbo.getValue().equals("红色"))
ta.setStyle("-fx-text-fill: red");
if(cbo.getValue().equals("绿色"))
ta.setStyle("-fx-text-fill: green");
if(cbo.getValue().equals("蓝色"))
ta.setStyle("-fx-text-fill: blue");
}
}
);
Scene scene = new Scene(bPane, 185, 100);
primaryStage.setTitle("组合框应用");
primaryStage.setScene(scene);
primaryStage.show();
}
}

为绑定属性添加监听者

为控件注册监听者的方式是控件名.setOnXXX(),所以这种事件处理是属于控件级的。

除此之外JavaFX还定义了属性级别的监听,即所有跟属性变化相关的事件,都可以用XXX.xxxxProperty().addListener()的形式来进行事件监听。

过为属性添加一个监听者就可以处理一个可观察对象中值的变化。

  • javafx.beans.Observable接口的常用方法
常用方法 功能说明
void addListener(InvalidationListener listener) 为可观察对象注册监听者
void remove Listener(InvalidationListener listener) 删除为可观察对象注册的监听者

作为参数的监听者listener必须实现InvalidationListener接口, 以覆盖该接口中定义的void invalidated(Observable observable)方法

类表视图控件及相应的事件处理

列表视图控件javafx.scene.control.ListView < T >的功能与组合框相似

列表视图中显示出多个选项供用户选择,而且也可设置是否可以进行多项选择,还可设置列表视图是否可以编辑。

使列表视图具有滚动功能,可以将列表视图添加到一个滚动面板ScrollPane中。

  • javafx.scene.control.ListView < T >类的构造方法
构造方法 功能说明
public ListView() 创建一个空的列表视图
public ListView(ObservableList < T > items) 创建一个列表框,其中的选项由参数items指定

列表视图中选项的序号是从0开始的。

列表视图ListView<T>继承自javafx.scene.control.Control类,所以Control类中的方法都可用于列表视图类ListView<T>。

  • javafx.scene.control.ListView < T >类的常用方法
常用方法 功能说明
public final void setSelectionModel(MultipleSelectionModel < T > value) 设置单选还是多选模式
public final MultipleSelectionModel < T > getSelectionModel() 返回选择模式
public final void setEditable(boolean value) 设置列表视图是否可编辑
public final void setItems(ObservableList < T > value) 用value设置列表视图中的选项
public final ObservableList < T > getItems() 返回列表视图中存储元素的列表
public final void setEditable(boolean value) 设置列表视图是否可编辑
public final void setPreWidth(double value) 设置列表视图的宽度
public final void setPrwHeight(double value) 设置列表视图的高度
public void setPrefSize(double prefWidth, double prefHeight) 设置列表视图的宽度和高度
public final void setOrientation(Orientation value) 设置列表视图的方向。value取值如下:Orientation.HORIZ0NTAL:水平方向;Orientation.VERTICAL:垂直方向

使用ListView<T>有两种基本方法:
第一种方法是可以忽略列表产生的事件,而是在程序需要的时候获得列表中的选中项;
第二种方法是通过注册选项变化监听者,监听列表中选项的变化,这样每次用户改变列表中的选项时就可以做出响应。

  • javafx.scene.control.MultipleSelectionModel < T >的常用方法
常用方法 功能说明
public abstract ObservableList < Integer > getSelectedIndices() 返回选中项下标的列表
public abstract ObservableList < T > getSelectedItems() 返回选中项的列表
public final void setSelectionMode(SelectionMode value) 设置选择模式为枚举SelectionMode中的枚举值。SelectionMode.MULTIPLE:多选;SelectionMode.SINGLE:单选。此为默认选项
public final SelectionMode getSelectionMode() 返回选择模式
public final int getSelectedIndex() 返回选中项的下标,如果有多个选项被选中,则返回最后选中项的下标
public final T getSelectedItem() 返回选中的选项,如果有多个选项被选中,则返回最后被选中的选项
public final ReadOnlyObjectProperty < T > selectedItemProperty() 返回当前选中项的属性
1
2
3
4
5
6
7
8
9
10
ListView<String> lv = new ListView<String>(items);
lv.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

lv.getSelectionModel().selectedItemProperty().addListener(
ov -> {
fp.getChildern().clear();
for(Integer i:lv.getSelectionModel().getSelectedIndices())
fp.getChildren().add(iv[i]);
}
);

ListView控件具有自动添加滚动条的特性。

滑动条及相应的事件处理

javafx.scene.control.Slider
是一个水平或垂直的滑动轨道,其上有一个滑块可以让用户拖曳,滑块所在位置表示一个值,滑动条允许用户在一个有界的区间范围内选取一个值。

滑动条可以是水平的也可以是垂直的,可以设置是否带有刻度线和表明取值范围的标签。

  • javafx.scene.control.Slider类的构造方法
构造方法 功能说明
public Slider() 创建一个默认的水平滑动条
public Slider(double min, doule max, double value) 创建最小值min、最大值max且初始值为value的滑动条
  • javafx.scene.control.Slider类的常用方法
常用方法 功能说明
public final double getValue() 返回滑块所在位置的值
public final void setBlockIncrement(double value) 设置单击滑块轨道时的调节值(块增量),默认值是10
public final void setMax(double value) 设置滑动条区间范围的最大值,默认值是100
public final void setMin(double value) 设置滑动条区间范围的最小值,默认值是0
public final void setValue(double value) 设置滑动条的当前值
public final void setMajorTickUnit(double value) 设置滑动条上主刻度线的间隔,单位是像素
public final void setMinorTickCount(int value) 设置两个主刻度线之间次刻度线的间隔,单位是像素
public final void setOrientation(Orientation value) 设置滑动条的方向。value的取值如下:
Orientation.HORIZONTAL:水平方向,此为默认值;
Orientation.VERTICAL:垂直方向
public final void setShowTickLabels(boolean value) 设置是否显示刻度值
public final void setShowTickMarks(boolean value) 设置是否显示刻度线
public final DoubleProperty valueProperty() 返回滑动条值的属性

由于滑动条的valueProperty是一个绑定属性, 所以可以在valueProperty属性上加一个监听者addListener(InvalidationListener listener),这样当用户要在滑动条中拖曳滑动块时,就能监听到其值的变化并能自动进行处理属性值的变化。

1
2
3
4
5
6
7
sl.valueProperty().addListener(
ov -> {
double size = sl.getValue();
Font font = new Font(size);
t.setFont(font);
}
);

垂直滑动条的值从上向下是减少的。

滚动条javafx.scene.control.ScrollBar
允许用户从一个范围内的值中进行选择的控件。
用户可以拖动滑块、单击滚动条轨道或者单击滚动条左右两边的按钮来改变滚动条的值。

进度条及相应的事件处理

进度条是一个显示用户任务完成前还需等待多长时间的控件,用于跟踪可用数字表示的任务进度。进度条类javafx.scene.control.ProgressBar
ProgressBar是javafx.scene.control.ProgressIndicator的直接子类。
ProgressIndicator类则是将进度动态地显示在一个饼图里。

  • javafx.scene.control.ProgressIndicator类的构造方法
构造方法 功能说明
public ProgressIndicator() 创建进度不确定进度饼图,饼图表现为一个旋转的圆点环
public ProgressIndicator(double progress) 用给定的进度值progress创建一个进度饼形图,进度值progress取值为0.0~1.0,表示0%~100%
  • javafx.scene.control.ProgressIndicator类的常用方法
常用方法 功能说明
public final void setProgress(double value) 用值value设置进度值,进度值value取值为0.0~1.0,表示0%~100%
public final double getProgress() 返回当前进度值,返回值为0.0~1.0,表示0%~100%
public final boolean isIndeterminate() 判断进度是否是不确定状态
public final DoubleProperty progressProperty() 返回进度的绑定属性
  • javafx.scene.control.ProgressBar类的构造方法
构造方法 功能说明
public ProgressBar() 创建进度不确定的进度条,滑块在进度条内左右移动
public ProgressBar(double progress) 用给定的progress值创建一个进度条,progress的取值为0.0~1.0,表示0%~100%

有时程序并不能确定一个任务完成的时间,这时进度饼图和进度条就保持在不确定状态直到可以确定任务的长度。
当进度条中的值不为0.0~1.0时进度饼图和进度条也会处于不确定状态。

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
//在窗口放置一个滑动条、一个进度条和一个进度饼图,拖动滑动条并用其当前值表示的进度来摸拟任务的完成情况。

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Slider;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class App15_11 extends Application {
@Override
public void start(Stage stage) {
final Slider slider = new Slider();
slider.setMin(0);
slider.setMax(50);
final ProgressBar pb = new ProgressBar();
final ProgressIndicator pi = new ProgressIndicator();

ChangeListener<Number> cListener = new ChangeListener<Number>(){
public void changed(ObservableValue <? extends Number> ov,
Number oldVal, Number newVal) {
pb.setProgress(newVal.doubleValue() / 50);
pi.setProgress(newVal.doubleValue() / 50);
}
};

slider.valueProperty().addListener(cListener);

final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(slider, pb, pi);
Scene scene = new Scene(hb);
stage.setScene(scene);
stage.setTitle("进度条应用程序");
stage.show();
}
}

菜单设计

每一个应用程序都会有菜单工具为用户的操作进行导航。

菜单通常有两种:
一种是窗口菜单或称下拉式菜单;
另一种是上下文菜单,也称弹出菜单或快捷菜单。

窗口菜单是相对于窗口的,它一般放在窗口标题栏的下面,总是与窗口同时出现。

每个菜单中再包含若干个菜单项,每个菜单项实际上可看作是另一种形式的命令按钮,也是在用户单击时引发一个动作事件,所以整个菜单就是一组经层次化组织、管理的命令集合。

弹出菜单是相对于某个指定控件的,当鼠标指向某控件并右击时,则会出现弹出菜单,弹出菜单也是由若干个菜单项组成,弹出菜单的结构相对简单。

在菜单程序设计中通常会用到五种菜单类:MenuBarMenuItemMenuCheckMenuItemRadioMenuItem

  • 菜单栏类MenuBar:该类是Node类的子类,菜单栏是菜单的容器,它包含管理菜单所必需的方法。
  • 菜单项类MenuItem:该类是Object类的子类,它包含了管理菜单项所必需的方法。菜单项可以用来触发动作事件,也可以是一个子菜单。
  • 菜单类Menu:该类是MenuItem类的子类,它包含了管理菜单的方法。单击某个菜单时,菜单就会展开并显示出菜单项的列表。单击某个菜单项会产生一个动作事件。
  • 复选菜单项类CheckMenuItem:该类是MenuItem类的子类,它包含管理具有开关状态的菜单项所必需的方法。当某个CheckMenuItem对象被选中时,会在菜单项左边出现一个复选标记 ,再次选择该菜单项时取消选中,此时复选标记中的勾号会被清除。
  • 单选菜单项类RadioMenuItem:该类是MenuItem类的子类,它与复选菜单项类CheckMenuItem一样是一种具有开关功能的菜单项。当多个RadioMenuItem对象作为ToggleGroup组的一部分来维护时,这组单选菜单项在同一时刻只能有一个被选中。

由于MenuItem类没有继承Node类,因此MenuItem的实例只能放在菜单中,而不能以其他方式加入场景图中。

菜单基本知识

要创建一个菜单系统,首先要创建一个菜单栏对象MenuBar。

再在菜单栏上添加若干个菜单对象Menu。

菜单项是MenuItem、CheckMenuItem或RadioMenuItem的对象。

菜单栏MenuBar

javafx.scene.control.MenuBar

菜单的容器,它是为应用程序提供主菜单控制。

  • javafx.scene.control.MenuBar类的构造方法
构造方法 功能说明
public MenuBar() 创建菜单栏对象
  • javafx.scene.control.MenuBar类的常用方法
常用方法 功能说明
public final ObservableList < Menu > getMenus() 返回一个由菜单栏管理的菜单列表,菜单将被添加到该列表中

向菜单栏上添加菜单,实际上是将菜单添加到ObservableList上。

可以通过调用getMenus()方法返回由菜单栏管理的菜单列表ObservableList的对象,然后调用它的add()addAll()方法,将Menu对象添加到该菜单栏列表中。

所添加的菜单将按照添加顺序,从左到右排列在菜单栏中。也可使用void add(int idx, Menu menu)方法将菜单添加到菜单栏中的指定位置。

菜单的下标从0开始,从左到右编号。

可以通过getMenus()方法返回的ObservableList对象调用remove(menu)方法从菜单栏中删除不需要的菜单,若要获得菜单栏中所包含的菜单个数,可以用该列表对象调用size()方法。

菜单Menu

javafx.scene.control.Menu

添加到菜单栏上的对象。

菜单Menu由菜单项MenuItem来填充。

Menu的对象可以是另一个Menu对象中的选项,从而能够创建二级子菜单。

  • javafx.scene.control.Menu类的构造方法
构造方法 功能说明
public Menu() 创建Menu对象
public Menu(String text) 创建显示名称为text的Menu对象
public Menu(String text, Node graphic) 创建显示名字为text图标为graphic的菜单对象
public Menu(String text, Node graphie, Menultem… items) 功能同 上,并将参数指定的多个菜单项添加到菜单中
  • javafx.scene.control.Menu类的常用方法
常用方法 功能说明
public final ObservableList < MenuItem > getItems() 返回当前与菜单关联的菜单项列表
public final void setText(String value) 将菜单的显示名字设置为value
public final void setGraphie(Node value) 为菜单添加图标

在菜单项列表中可以添加菜单分隔线,该分隔线是SeparatorMenuItem类的对象。利用分隔线可
以将相关的菜单项分组,从而有助于组织长菜单。

菜单项MenuItem

javafx.scene.control.MenuItem

  • javafx.scene.control.MenuItem类的构造方法
构造方法 功能说明
public Menulterm() 创建一个空的菜单项对象
public Menultem(String text) 创建一个名称为text的菜单项对象
public Menultem(String text, Node graphic) 创建一个名称为text,图标为graphic的菜单项对象
  • javafx.scene.control.MenuItem类的常用方法
常用方法 功能说明
public final void setDisable(boolean value) 设置菜单项是否禁用
public final void setGraphic(Node value) 为菜单项设置图标
public final void setText(String value) 将菜单项的显示名字设置为value
public void fire() 在菜单项上引发动作事件
public final void setAccelerator(KeyCombination value) 设置菜单项的快捷键(加速键)
public final void setMnemonicParsing(boolean value) 设置热健(助记符)是否有效,默认为true

MenuItem对象被选中时会产生动作事件,可以调用setOnAction()方法为MenuItem对象注册监听者,就像处理按钮事件一样。

热键又称助记符,快捷键也称加速键。
热键是在菜单展开的情况下,同时按下”Alt+热键”即可选择菜单项。
而快捷键是在不用展开菜单的情况下,同时按下”Ctrl+快捷键”即可直接选择菜单中的菜单项。

若要为Menu和MenuItem设置热键,只需在菜单和菜单项中为想要用作热键的字符前面添加一条下画线即可,因为默认情况下热键是有效的,否则只需调用setMnemonicParsing(true)将其设置为真即可。

1
Menu fileMenu = newMenu("_File");

若要为菜单项设置快捷键,需要调用MenuItem的setAccelerator(KeyCombination value)方法。
通常用KeyCombination类的静态方法public static KeyCombination keyCombination(String name)进行设置

1
opemMI.setAccelerator(KeyCombination.keyCombination("Ctrl + O"));

复选菜单项ChcekMenuItem和单选菜单项RadioMenuItem

复选菜单类:javafx.scene.control.CheckMenuItem
单选菜单类:javafx.scene.control.RadioMenuItem

  • javafx.scene.control.CheckMenuItem类的构造方法
构造方法 功能说明
public CheckMenultem() 创建没有名称与图标、最初状态未选中的复选菜单项
public CheckMenuItem(String text) 创建名为text、初始状态未选中的复选菜单项
public CheckMenultem(String text, Node graphic) 创建名为text,图标为graphie,初始状态未选中的复选菜单项
  • javafx.scene.control.CheckMenuItem类的常用方法
常用方法 功能说明
public final boolean isSelected() 判断复选菜单项是否被选中
public final void setSelected(boolean value) 设置复选菜单项的选中状态
public final BooleanProperty selectedProperty() 返回复选菜单项的状态属性

窗口菜单

菜单项实际上可以看作是另一种形式的命令按钮,所以选择菜单项后会产生动作事件EventAction,因此需调用setOnAction()方法为MenuItem对象注册监听者。

使用动作事件处理程序来处理所有菜单选择时,确定选中了哪个菜单项的一种方法是检查选择的名称。

单独的匿名内部类或Lambda表达式来处理每个菜单项的动作事件,此时所选菜单项已知,所以不需要通过检查名称来确定哪个菜单项被选中。

弹出菜单

javafx.scene.control.ContextMenu

ContextMenu的直接父类是javafx.scene.control.PopupControl,它的一个间接父类是javafx.stage.PopupWindow

当在某个控件上右击时,会弹出一个菜单供选择,所以弹出菜单又称上下文菜单或称快捷菜单。

  • javafx.scene.control.ContextMenu类的构造方法
构造方法 功能说明
public ContextMenu() 创建一个不含菜单项的弹出菜单对象
public ContextMenu(Menultenm… items) 用参数指定的多个菜单项创建一个弹出菜单对象
  • javafx.scene.control.ContextMenu类的常用方法
常用方法 功能说明
public final ObservableList < Menultem > getItems() 返回与弹出菜单关联的菜单项列表
public void show(Node anchor, double screenX, double screenY) 在屏幕的(x,y)位置处显示弹出菜单,anchor指定弹出菜单所依附的组件
public void hide() 隐藏弹出菜单
public final void setContextMenu(ContextMenu value) 建立组件与弹出菜单value的关联

首先创建菜单项,然后将其添加到弹出菜单中。

将弹出菜单与控件关联起来非常简单,只需对控件调用setContextMenu()方法,并传入对弹出菜单的引用即可。

也可以将弹出菜单与场景关联起来, 方法是对场景的根节点调用setOnContextMenuRequested()方法。该方法定义在Node类中。

1
public final void setOnContextMenuRequested(EventHandler < ? super ContextM enuEvent> value

参数value指定当收到弹出菜单的请求时调用的处理程序。
处理程序必须调用ContextMenu定义的show()方法。

工具栏设计

将一些常用的命令按钮放置到工具栏上。

javafx.scene.control.ToolBar工具栏类

工具栏上的控件通常是以图标形式出现的。

可以在工具栏上放置命令按钮,然后再把图标设置在命令按钮上。

工具栏中添加的多为命令按钮,所以其事件处理也是动作事件ActionEvent

  • javafx.scene.control.ToolBar类的构造方法
构造方法 功能说明
public ToolBar() 创建一个空的水平工具栏
public ToolBar(Node..items) 创建一个由参数指定的多个节点的水平工具栏
  • javafx.scene.control.ToolBar类的常用方法
常用方法 功能说明
public final ObservableList < Node > getItems() 返回工具栏的节点列表
public final void setOrientation(Orientation value) 设置工具栏的方向,参数value取值如下:
Orientation.HORIZONTAL:水平方向,此为默认值;
Orientation.VERTICAL:垂直方向

向工具栏添加按钮或其他控件的方式与把菜单添加到菜单栏的方式基本相同,就是对getItems()方法返回的列表引用调用add()方法,但是通常在ToolBar构造方法中指定它们更方便。

1
2
Button but1 = new Button("打开", new ImageView("icon/openFile.jpg"));
but1.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); //只显示按钮上的图标

文件选择对话框

javafx.stage.FileChooser

用户经常使用该类创建”打开”或”保存”文件对话框,所以它是一种用于文件选择控件。

  • javafx.stage.FileChooser类的构造方法
构造方法 功能说明
public FileChooser() 创建打开默认目录的文件选择对话框
  • javafx.stage.FileChooser类的常用方法
常用方法 功能说明
public final void setTitle(String value) 设置文件选择对话框的标题
public final void setlnitialDirectory(File value) 设置文件选择对话框的初始显示目录
public ObservableList < FileChooser.ExtensionFilter > getExtensionFilters() 返回文件对话框中使用的扩展名过滤器的文件选项列表
public File showOpenDialog(Window ownerWindow) 显示打开文件对话框,参数ownerWindow为文件对话框的所属窗口,通常是主舞台,返回值是用户选择的文件,若没选文件则返回null
public List < File > showOpenMultipleDialog(Window ownerWindowr) 显示打开文件对话框,返回在对话枢中选择的多个文件,并保存到List < File >对象中
public File showSaveDialog(Window ownerWindow) 显示保存文件对话框,返回选择的文件,若没有选择文件则返回null。多数ownerWindow为文件对话框的所属窗口

可以通过设置initialDirectory和title属性来配置文件选择对话框窗口。文件选择对话框既可用作打开文件对话框,用于选择单个文件或多个文件,也可作为文件保存对话框。

对话框一般分为模态和非模态两种。
模态对话框一定要处理完本对话框内的操作之后,才能返回到它的所属窗口继续运行。
非模态对话框在显示时,用户还可以操作其他窗口。
FileChooser类中的打开和保存对话框都是模态的。

1
2
//文件过滤器
FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("所有.java文件", "*.java");

颜色选择器

通过一组单选按钮提供一组颜色值列表供用户选择。

javafx.scene.control.ColorPicker

它用于显示一个窗格,允许用户在一个调色板上通过单击颜色来选取一种颜色值,或在自定义颜色面板中选择颜色。

  • javafx.scene.control.ColorPicker类的构造方法
构造方法 功能说明
public ColorPicker() 创建初始颜色为白色的颜色选择器
public ColorPicker(Color color) 创建初始颜色为color的颜色选择器
  • javafx.scene.control.ColorPicker类的常用方法
常用方法 功能说明
public final T getValue() 返回选中选项的值(父类中方法)
public final ObservableList < Color > getCustomColors() 返回用户添加到调色板的自定义颜色列表

ColorPicker控件包括颜色选择框、调色板以及自定义颜色面板。

颜色选择框是一个组合框,包括了所有可以选择的颜色和颜色指示器,颜色指示器显示了当前选中的颜色;
调色板包含了预定义的颜色集合以及自定义颜色的链接;
自定义颜色面板是一个模态窗口,可以通过单击调色板上的链接打开。

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
//颜色选择器程序设计,在窗口中放置一个文本和一个颜色选择器,用在颜色选择器中选择的颜色来设置文本的颜色。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class App15_16 extends Application {
@Override
public void start(Stage stage) {
HBox hB = new HBox();
final ColorPicker cP = new ColorPicker(Color.RED);

final Text t= new Text("请选择颜色来设置我");
hB.getChildren().addAll(cP, t);
t.setFill(cP.getValue());
cP.setOnAction(e -> t.setFill(cP.getValue()));

Scene scene = new Scene(hB, 260, 100);
stage.setTitle("颜色选择器应用");
stage.setScene(scene);
stage.show();
}
}

音频与视频程序设计

JavaFX提供了丰富的媒体类用于媒体的播放,主要有Media、MediaPlayer、MediaView等类。

目前JavaFX支持的音频格式有MP3、AIFF、WAV及MPEG-4等,支持的视频格式有FLVM和PEG-4。

媒体源是由类javafx.scene.media.Media

  • javafx.scene.media.Media类的构造方法
构造方法 功能说明
public Media(String source) 用名字source创建一个媒体对象,目前它仅支持HTTP、FILE、URL和JAR格式的媒体源路径,设置后不可改变
  • javafx.scene.media.Media类的常用方法
常用方法 功能说明
publie final Duration getDuration() 返回媒体源以秒计时的持续时间对象
publie final int getWidth() 返回媒体视频以像素为单位的宽度
public final int getWidth() 返回媒体视频以像素为单位的高度
  • javafx.scene.media.MediaPlayer类的构造方法
构造方法 功能说明
public MediaPlayer(Media media) 为媒体media创建一个播放器
  • javafx.scene.media.MediaPlayer类的常用方法
常用方法 功能说明
public final void setAutoPlay(boolean value) 设置媒体是否自动播放
public final void setCycleCount(int value) 设置媒体播放次数
public final void setVolume(double value) 设置音频音量的大小,取值为0.0~1.0(最大)
public final void setMute(boolean value) 设置音频是否禁音
public final void setBalance(double value) 设置左、右声道的平衡值,最左边为-1,中间为0,最右边为1
public void play() 播放媒体
public void pause() 暂停媒体播放
public void stop() 停止媒体播放
public void seek(Duration seekTime) 将播放器定位到一个新的播放时间点
  • javafx.scene.media.MediaView类的构造方法
构造方法 功能说明
public MediaView() 创建一个不与媒体播放器关联的媒体视图
public MediaView(MediaPlayer mediaPlayer) 创建一个与指定媒体播放器mediaPlayer关联的媒体视图
  • javafx.scene.media.MediaView类的常用方法
常用方法 功能说明
public final void setX(double value) 设置媒体视图的x坐标
public final void setY(double value) 设置媒体视图的y坐标
publie final void setFitWidth(double value) 设置媒体视图的宽度
public final void setFitHeight(double value) 设置媒体视图的高度
public final void setMediaPlayer(MediaPlaver value) 设置媒体视图的播放器为value

一个Media对象可以被多个媒体播放器所共享,一个MediaPlayer也可以被多个MediaView所使用。

本章小结

  • 委托事件模型是指当事件发生时,产生事件的对象会把此信息转给事件监听者处理的一种方式,而这个信息事实上是JavaFX中的javafx.event事件包里的某个类所建立的对象。
  • JavaFX中javafx.event.Event类中包含了用来处理事件的监听者接口,用于事件处理的方法就声明在这些接口中。
  • 一个对象要成为事件源的事件监听者,满足两个条件即可:一是事件监听者必须是一个对应的事件监听者接口的实例,从而保证该监听者具有正确的事件处理方法;二是事件监听者对象必须通过事件源进行注册,注册方法依赖于事件类型。
  • 对控件的什么操作触发什么事件类型、注册事件监听者及处理事件的方法见表15.1和表15.2。
  • JavaFX的监听分为两种:组件级别监听和属性级别监听。属性级别的监听主要用于绑定属性。

课后习题

  • 什么是事件?简述Java语言的委托事件模型。
  • 若要处理事件,就必须要有事件监听者,担任监听者需满足什么条件?
  • 写出控件与可能触发的事件之间的对应关系。
  • 对于按下键和释放键的事件,使用什么方法来获得键的编码值?使用什么方法从一个键的单击事件中获得该键的字符?
  • 设计一个窗口,在窗口内放置一个按钮,当不断地单击该按钮时,在其上显示它被单击的次数。
  • 创建一个窗口,隐藏窗口的标题栏和边框,并在其上添加一个”退出”按钮。将鼠标指针放在窗口内的任意位置进行拖动窗口,当单击”退出”命令按钮后,结束程序运行。
  • 在窗口的中央区域放置一个文本区控件,在窗口的下部区域添加红、绿、蓝三个单选按钮,并用其设置文本区中文本的颜色。
  • 在窗口的中央区域放置一个文本区控件,在窗口的下部区域添加”粗体”和”斜体”两个复选框,并用其设置文本区中文本的字体。
  • 编程,实现利用在滑动条中拖动滑块的方法对文本字体的大小进行设置。
  • 编写一个简单的音频播放器,在程序中创建一个MediaPlayer对象,并用命令按钮实现播放、暂停和重放功能。

第十六章 绘图与动画程序设计

图形坐标系与形状类

javafx.scene.shape.Shape

形状类Shape是抽象类,它所派生的子类主要有Text、Line、Rectangle、Circle、Ellipse、Arc、Polygon、Polyline等。

Shape类是Node类的子类,所以形状类作为节点可以添加到面板上。

每个形状都具有大小、位置、形状、颜色、维数等属性。

  • javafx.scene.shape.Shape类的常用方法
常用方法 功能说明
public final void setFill(Paint value) 设置填充形状内部区域的颜色为value
public final void setStroke(Paint value) 设置画笔颜色为value
public final void setStrokeWidth(double value) 设置画笔宽度为value
public final void setSmooth(boolean value) 设置是否对形状使用平滑算法
public final void setStrokeDashOffset(double value) 设置虛线的起始偏移量为value,即虛线往后移的量
public final ObservableList < Double > getStrokeDashArray() 定义表示虚线段长度的数组,数组中的值依次为不透明和透明段长度
public final void setStrokeLineCap ( StrokeLineCap value) 设置形状端点的风格,参数value取值如下:
StrokeLinCap.BUTT:线条末端平直,此为默认值;
StrokeLineCap.ROUND:端点加一圆形线帽;
StrokeLineCap.SQUARE:端点加一正方形线帽
public final void setStrokeType(StrokeType value) 设置节点边界周围绘制描边的类型,参数value取值如下:
StrokeType.CENTERED:从中间向内外两侧;
StrokeType.INSIDE:向内侧;
StrokeType.OUTSIDE:向外侧

直线类Line

javafx.scene.shape.Line

一条直线有起点、终点、线宽、颜色等属性,用户可根据这些属性画出需要的直线。

  • javafx.scene.shape.Line类的构造方法
构造方法 功能说明
public Line() 创建一个空的直线
public Line(double startX, double startY, double endX, double endY) 以(startX, startY)为起点,以(endX, endY)为终点创建一条直线
  • javafx.scene.shape.Line类的常用方法
常用方法 功能说明
public final void setStartX(double value) 设置起点的x坐标
public final void setStartY(double value) 设置起点的y坐标
public final void setEndX(double value) 设置终点的x坐标
public final void setEndY(double value) 设置终点的y坐标
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
//绘制红、绿、蓝三条直线,红线设置为虚线。绿、蓝两条直线通过坐标的属性绑定使它们成为交叉线。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.layout.Pane;
import javafx.scene.shape.StrokeLineCap;

public class App16_1 extends Application {
@Override
public void start(Stage stage) {
Pane pane = new Pane();

Line rL= new Line(10,20, 20,20);
rL.setStroke(Color.RED);
rL.setStrokeWidth(10);
rL.setStrokeLineCap(StrokeLineCap.BUTT); //设置线条两端平直
rL.getStrokeDashArray().addAll(10d, 5d, 15d); //设置虚线段长度,依次为不透明和透明段的长度
rL.setStrokeDashOffset(0); //虚线的后偏移量
rL.endXProperty().bind(pane.widthProperty().subtract(10)); //属性绑定

Line gL = new Line(10, 50, 10, 10);
gL.setStroke(Color.GREEN);
gL.setStrokeWidth(5);
gL.endXProperty().bind(pane.widthProperty().subtract(10));
gL.endYProperty().bind(pane.heightProperty().multiply(4).divide(5));

Line bL = new Line(10,50,10,10);
bL.setStroke(Color.BLUE);
bL.setStrokeWidth(10);
bL.setStrokeLineCap(StrokeLineCap.ROUND); //设置线条两端具有圆形线帽
bL.startXProperty().bind(pane.widthProperty().subtract(10));
bL.endYProperty().bind(pane.heightProperty().multiply(4).divide(5));

pane. getChildren().addAll(rL, gL, bL);
Scene scene = new Scene(pane, 210, 120);
stage.setTitle("绘制直线");
stage.setScene(scene);
stage.show();
}
}

矩形类Rectangele

javafx.scene.shape.Rectangle

  • javafx.scene.shape.Rectangle类的构造方法
构造方法 功能说明
publie Rectangle(double width,double height) 创建宽为width,高为height的矩形
public Rectangle(double width, double height, Paint fill) 创建宽为width,高为height,填充色为fill的矩形
public Rectangle(double x, double y, double width, double height) 创建一个以(x,y)为左上角,宽为width,高为height的矩形
  • javafx.scene.shape.Rectangle类的常用方法
常用方法 功能说明
publie final void setX(double value) 设置矩形左上角的x坐标为value
public final void setY(double value) 设置矩形左上角的y坐标为value
public final void setWidth(double value) 设置矩形的宽度为value
public final void setHeight(double value) 设置矩形的高度为value
public final void setAreWidth(double value) 设置矩形圆角弧的水平直径为value
public final void setArcHeight(double value) 设置矩形圆角弧的垂直直径为value
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
//用循环在面板上添加四个矩形,每个都进行旋转,且画笔的颜色是随机的。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.layout.Pane;

public class App16_2 extends Application {
@Override
public void start(Stage stage) {
Pane pane = new Pane();
for(int i=0; i<4; i++) {
Rectangle r = new Rectangle(50, 50, 80,20);
r.setArcWidth(10); //设置圆角弧水平直径为10像素
r.setArcHeight(6); //设置圆角弧垂直直径为6像素
r.setRotate(i*360/8); //设置旋转
r.setStroke(Color.color(Math.random(), Math.random(), Math. random()));
r.setFill(null); //不填充颜色
pane.getChildren().add(r);
}
Scene scene = new Scene(pane, 200, 130);
stage.setTitle("矩形程序设计");
stage.setScene(scene);
stage.show();
}
}

圆形Circle

javafx.scene.shape.Circle

  • javafx.scene.shape.Circle类的构造方法
构造方法 功能说明
publie Circle(double radius) 创建半径为radius的圆
public Circle(double centerX, double centerY, double radius) 创建以( centerX, centerY)为圆心,以radius为半径的圆
public Circle(double centerX, double centerY, double radius, Paint fill) 创建以(centerX.centerY)为圆心,以radius为半径,以fill为填充色的圆
  • javafx.scene.shape.Circle类的常用方法
常用方法 功能说明
public final void setCenterX(double value) 设置圆心的x坐标为value
public final void setCenterY(double value) 设置圆心的y坐标为value
public final void setRadius(double value) 设置圆的半径为value

椭圆类Ellipse

javafx.scene.shape.Ellipse

  • javafx.scene.shape.Ellipse类的构造方法
构造方法 功能说明
public Ellipse(double radiusX, double radiusY) 创建水平半径为radiusX 、垂直半径为radiusY的椭圆
public Ellipse(double centerX, double centerY, double radiusX, double radiusY) 创建以(centerX, centerY)为圆心,以radiusX 为水平半径,以radiusY为垂直半径的椭圆
  • javafx.scene.shape.Ellipse类的常用方法
常用方法 功能说明
public final void setCenterX(double value) 设置椭圆圆心的x坐标为value
public final void setCenterY(double value) 设置椭圆圆心的y坐标为value
public final void setRadiusX(double value) 设置椭圆水平半径为value
public final void setRadiusY(double value) 设置椭圆垂直半径为value

弧类Arc

javafx.scene.shape.Arc

  • javafx.scene.shape.Arc类的构造方法
构造方法 功能说明
public Arc() 创建一条空的弧
public Arc(double centerX, double centerY,double radiusX, double radiusY, double startAngle, double length) 以(centerX,centerY)为弧中心,以radiusX 为水平半径、radiusY为垂直半径、startAngle为起始角度、length为转过的角度创建一条弧
  • javafx.scene.shape.Arc类的常用方法
常用方法 功能说明
public final void setCenterX(double value) 设置弧中心点的x坐标
public final void setCenterY(double value) 设置弧中心点的y坐标
public final void setRadiusX(double value) 设置弧所在椭圆的水平半径
public final void setRadiusY(double value) 设置弧所在椭圆的垂直半径
public final void setStartAngle(double value) 设置弧的起始角,以度(°)为单位,正角度为逆时针旋转
public final void setLength(double value) 设置弧转过的角度,以度(°)为单位,正角度为逆时针旋转
public final void setType(ArcType value) 设置弧的类型,参数value取值如下:
ArcType.CHORD:闭合弧,弧的端点之间有连线;
ArcType.ROUND:扇形弧;
ArcTypeOPEN:开弧,弧的端点之间没有连线。

0°是向右的x轴方向,正角度表示逆时针方向旋转。

多边形类Polygon与折线类Polyline

多边形:javafx.scene.shape.Polygon,一个连接点序列的闭合多边形。
折线类:javafx.scene.shape.Polyline,一个连接点序列的折线,折线不会自动闭合。

  • javafx.scene.shape.Polygon类的构造方法
构造方法 功能说明
public Polygon() 创建一个空的多边形对象
public Polygon(double… points) 以点集points作为顶点坐标创建一个多边形
  • javafx.scene.shape.Polygon类的常用方法
常用方法 功能说明
public final ObservableList < Double > getPoints() 返回一个双精度值列表作为顶点集的x坐标和y坐标

交互式程序设计

交互式程序设计就是用鼠标在面板上随意画图。

动画程序设计

在JavaFX中动画被分为过渡动画和时间轴动画。
过渡动画类javafx.animation.Transition和时间轴动画类javafx.animation.Timeline都是动画类javafx.animation.Animation的子类。

  • javafx.animation.Animation类的常用方法
常用方法 功能说明
public void play() 从当前位置播放动画
public void pause() 暂停动画播放
public void playFromStart() 从头播放动画
public void stop() 停止动画并重置动画
protected final void setStatus(Animation.Status value) 设置动画的状态为value,value取值如下:
Animation.Status.PAUSED:暂停;
Animation.Status.RUNNING:播放;
Animation.Status.STOPPED:停止
public final void setRate(double value) 设置动画播放的方向和速度
public final void setCycleCount(int value) 设置动画循环播放的次数
public final void setAutoReverse(boolean value) 设置在下一个周期动画中是否需要倒转方向

过渡动画

javafx.animation.Transition

最简单的动画可以通过过渡效果实现,使用特定的过渡类,定义有关的属性,然后把它应用到某种节点,最后播放动画即可。

淡入淡出效果

javafx.animation.FadeTransition

指在给定时间内改变节点的不透明度效果来实现,即通过改变节点透明度实现目标节点逐渐消失的效果, 再通过setAutoReverse()方法实现节点的或隐或现效果。

  • javafx.animation.FadeTransition类的构造方法
构造方法 功能说明
public FadeTransition() 创建一个空的淡人淡出效果对象
public FadeTransition(Duration duration) 创建一个指定持续时间的淡人淡出效果对象,持续时间duration的取值如下:
Duration.INDEFINITE:无限循环;
Duration.ONE: 1ms;
Duration.UNKNOWN:未知;
Duration.ZERO: 0
public FadeT ransition (Duration duration, Node node) 创建一个持续时间同上,应用在节点node上的淡入淡出效果对象
  • javafx.animation.FadeTransition类的常用方法
常用方法 功能说明
public final void setDuration(Duration value) 设置转换持续时间为value,持续时间见上表
public final void setNode(Node value) 设置动画应用在节点value上,即转换的目标节点上
public final void setFromValue(double value) 设置动画的起始透明度为value,1.0表示不透明,0.0表示透明
public final void setToValue(double value) 设置动画结束的透明度为value,l.0表示不透明,0.0表示透明
public final void setByValue(double value) 设置动画透明度的递增值为value

Duration定义了事件持续的时间,它是一个不可更改类。

  • javafx.util.Duration类的构造方法
构造方法 功能说明
public Duration(double millis) 创建持续millis毫秒(ms)的持续时间对象
  • javafx.util.Duration类的常用方法
常用方法 功能说明
public Duration add(Duration other) 与调用者进行持续时间相加运算
public Duration subtract(Duration other) 与调用者进行持续时间相减运算
public Duration multiply(double n) 执行持续时间相乘运算
public Duration divide(double n) 执行持续时间除法运算
public static Duration millis(double ms) 返回指定ms毫秒数的持续时间
public static Duration minutes(double m) 返回指定m分钟数的持续时间
public double toHours() 返回持续时间值的小时数
public double toMinutes() 返回持续时间值的分钟数
public double toSeconds() 返回持续时间值的秒数
public double toMillis() 返回持续时间值的毫秒数
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
//编制程序对圆实现淡入淡出效果

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.animation.Animation;
import javafx.animation.FadeTransition;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;
public class App16_8 extends Application {
@Override
public void start(Stage stage) {
StackPane pane = new StackPane();

Circle c = new Circle(50);
c.setStroke(Color.BLUE);
c.setFill(Color.RED);
pane.getChildren().add(c);

FadeTransition ft = new FadeTransition(Duration.millis(2000));
ft.setFromValue(1.0);
ft.setToValue(0.0);
ft.setCycleCount(Animation.INDEFINITE);
ft.setAutoReverse(true);
ft.setNode(c);
ft.play();

c.setOnMousePressed(e -> ft.pause());
c.setOnMouseReleased(e -> ft.play());
Scene scene = new Scene(pane, 200, 120);
stage.setTitle("淡人淡出动画");
stage.setScene(scene);
stage.show();
}
}

移动效果

javafx.animation.PathTransition

一个在给定时间内节点沿着一条路径从一个端点到另一端点的移动动画。

  • javafx.animation.PathTransition类的构造方法
构造方法 功能说明
public PathTransition() 创建一个空的移动效果对象
public PathTransition(Duration duration, Shape path) 创建一个持续时间为duration、路径为path的移动效果对象
public Path ransition(Duration duration, Shape path, Node node) 功能同上,移动效果应用在node节点上
  • javafx.animation.PathTransition类的常用方法
常用方法 功能说明
public final void setDuration(Duration value) 设置转换持续的时间为value
public final void setNode(Node value) 设置动画应用在节点value上,即转换的目标节点
public final void setOrientation(PathTransition.OrientationType value) 设置节点沿路径的移动方式,参数value 的取值是枚举PathTransition.OrientationType中的枚举常量,含义如下:
NONE:移动路径保持不变,保持与路径切线平行;
ORTHOGONAL_TO_ANGENT:与路径的切线垂直
public final void setPath(Shape value) 设置形状value为节点移动的路径

时间轴动画

javafx.animation.Timeline

就是动画中最小单位的单幅图像或影像画面,相当于电影胶片上的每一个镜头。

关键帧是节点运动或变化中关键动作所处的那一帧。

关键帧与关键帧之间可以插入一些中间帧(或称为过渡帧)。

这些过渡帧由数学算法来调整其位置、不透明度、颜色以及动作所需的其他方面。由系统决定在两个关键帧的持续时间内需要插入多少过渡帧。在两个关键帧之间插入过渡帧的过程称为内插。

关键帧按照指定的持续时间散布在这个时间轴上。

这些关键帧中可能包含关键值,关键值表示的是特定应用程序值的最终状态,程序值包括位置、不透明度、颜色或在关键时间点执行的动作等。

关键值中包含一个用来说明在插入过渡帧的过程中所使用的算法,这个算法称为插值器

关键帧就是在某一帧当中,设置某些关键性的属性值。

时间轴Timeline对象是一个包含多个关键帧KeyFrame对象的动画序列,这些KeyFrame按照它们在时间轴内的相对时间排序。

时间轴允许在一段时间之后使用插值器将动画属性修改为新的目标值,即通过更改节点的属性创建动画。

时间轴在时间方向上既可以向前移动,也可以向后移动。

可以循环播放一次或多次,甚至是无限循环播放。可指定每次循环时改变方向,这样它就能够先向前播放而后再向后播放。还可以加快或减慢播放的速率。

Timeline类是Animation类的子类

  • javafx.animation.Timeline类的构造方法
构造方法 功能说明
public Timeline() 创建一个空的时间轴对象
public Timeline(double targetFramerate) 创建以targetFramerate为帧速率(每秒刷新图片的帧数)创建时间轴对象
public Timeline(KeyFrame… keyFrames) 以参数指定的多个关键帧来创建时间轴对象
public Timeline(double targetFramerate, KeyFrame… keyFrames) 以targetFramerate为帧速率,以参数指定的多个关键帧来创建时间轴对象
  • javafx.animation.Timeline类的常用方法
常用方法 功能说明
public final ObservablelList < KeyFrame > getKeyFrames() 返回时间轴上的关键帧列表
  • javafx.animation.KeyFrame类的构造方法
构造方法 功能说明
public KeyFrame(Duration time, KeyValue… values) 以time为持续时间,以给定的多个参数为关键值创建关键帧对象
public KeyFrame(Duration time, String name, KeyValue… values) 以time为持续时间,以name为名字并以给定的多个关键值创建关键帧对象
public KeyFrame(Duration time, EventHandler < ActionEvent > onFinished, KeyValue… values) 创建关键帧对象,参数同上;但onFinished是关键帧持续时间结束后被调用的事件处理方法
  • javafx.animation.KeyFrame类的常用方法
常用方法 功能说明
public String getName() 返回关键帧的名称
publice Set < KeyValue > getValues() 返回关键值实例集
public Duration getTime() 返回关键帧的时间偏移量
  • javafx.animation.KeyValue类的构造方法
构造方法 功能说明
public KeyValue(WritableValue < T > target, T endValue) 创建以target为目标,以endValue为结束关键值对象,使用默认插值器Interpolator.LINEAR
public KeyValue(WritableValue< T > target, T endValue, Interpolator interpolator) 功能同上,使用的插值器为interpolator,取值如下:
Interpolator, LINEAR:线性;
Interpolator.DISCRETE:离散;
Interpolator.EASEIN:渐快;
Interpolator.EASEOUT:减速;
Interpolator.EASE_BOTH:增减速交替
  • javafx.animation.KeyValue类的常用方法
常用方法 功能说明
public WritableValue < ? > getTarget() 返回关键值中的目标
public Object getEndValue() 返回关键值中的结束值
public Interpolator get Interpolator() 返回关键值中的插值器
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
//利用时间轴动画,编写一个字幕滚动程序

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.geometry.VPos;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.util.Duration;
public class App16_10 extends Application {
@Override
public void start(Stage stage) {
Text t = new Text("滚动字幕");
t.setTextOrigin(VPos.TOP);
t.setFont(Font.font(24));

Pane root = new Pane(t);
root.setPrefSize(300, 60);
Scene scene = new Scene(root);

stage.setScene(scene);
stage.setTitle("时间轴动画程序设计");
stage.show();

double sceneWidth = scene.getWidth();
double tWidth = t.getLayoutBounds().getWidth();

KeyValue sKeyValue = new KeyValue(t.translateXProperty(), sceneWidth);
KeyFrame sFrame = new KeyFrame(Duration.ZERO, sKeyValue);
KeyValue eKeyValue = new KeyValue(t.translateXProperty(), -1.0*tWidth);
KeyFrame eFrame = new KeyFrame(Duration.seconds(5), eKeyValue);

Timeline timeline = new Timeline(sFrame, eFrame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
}

该程序中用到的方法getLayoutBounds()translateXProperty()均是 Node类中的方法 。

本章小结

  • JavaFX的绘图面板中,原点在左上角,向右为x轴方向,向下为y轴方向。
  • 形状类javafx.scene.shape.Shape是Node的子类。
  • 抽象类Animation提供了JavaFX中动画制作的核心功能。
  • 关键帧KayFrame是设置某些关键性属性值的帧。
  • 关键值KeyValue是包含在KeyFrame对象中的某些参数值。
  • 从一个关键帧过渡到另一个关键帧的过程中用于计算中间过渡帧的算法称为插值器。

课后习题

  • 编程题,画一个圆角矩形,宽度200像素,高度100像素,左上角位于(20,20),圆角处的水平直径为30像素,垂直直径为20像素,并用红色填充。
  • 编程题,画一个椭圆,中心在(150,100),水平半径为100像素,垂直半径为50像素,画笔颜色随机产生,不填充颜色,生成16个椭圆,每个椭圆旋转一个角度后都添加到面板中。
  • 编程题,画一个半径为50像素的上半圆的轮廓。
  • 编程题,画一个半径为50像素的下半圆,并用蓝色填充。
  • 编程题,在窗口中放置“顺转”和“逆转”两个按钮,当单击按钮时,将椭圆每次都旋转30°。
  • 编程题,画一个以(20,40)、(30,50)、(40,90)、(90,10)和(10,30)为顶点的多边形。
  • 编程题,画一个以(20,40)、(30,50)、(40,90)、(90,10)和(10,30)为顶点的折线。
  • 编程题,用动画实现一个钟摆,即一条直线上端固定,下端连接一个小球,小球来回摆动。
文章作者: HibisciDai
文章链接: http://hibiscidai.com/2022/01/05/JAVA程序设计基础-第6版陈国君2006-学习笔记4/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HibisciDai
好用、实惠、稳定的梯子,点击这里