本章介绍如何向JavaFX应用程序添加分页控件。它教授如何向应用程序添加分页控件,管理其页面项,以及使用CSS样式设置控件元素的样式。
分页控件,用于浏览分成较小部分的多页内容。典型用途包括浏览邮箱中的电子邮件或在搜索结果中进行选择。在触摸设备中,分页控件可用于浏览文章的单个页面或在屏幕之间导航。图25-1显示了一个分页控件,它显示了操作系统中可用的字体。
图25-1分页控制
创建分页控件
分页控件由页面内容和页面导航区域组成。页面内容区域根据应用程序逻辑呈现和布置内容。页面导航区域包含预制控件,用于预览内容的特定部分。图25-2显示了导航区域的结构和基本元素。
图25-2分页控制的导航区域
您可以通过单击特定页面指示器或单击“下一页”和“上一页”按钮来浏览页面。选择第一页时,将禁用“上一页”按钮。同样,当选择最后一个导航指示器时,将禁用“下一页”按钮。
JavaFX SDK API提供了Pagination
将分页控件添加到JavaFX应用程序的类。例25-1显示了Pagination
该类的三个可用构造函数。
例25-1分页类的三个构造函数
//Creates a Pagination control with an INDETERMINATE page count
//and the current page index equal to zero
pagination1 = new Pagination();
//Creates a Pagination control with 5 pages
//and the current page index equal to zero
pagination2 = new Pagination(5);
//Creates a Pagination control with 5 pages
//and the current selected index equal to 2
pagination3 = new Pagination(5, 2);
例25-1中的pagination3控件显示在图25-3中。
图25-3没有内容的分页控制
请注意,页面索引从0开始。因此,要从选择的第三个页面开始,您需要将其设置currentPageIndexProperty
为2。
pagination3控件的页面为空,因为没有内容添加到控件。
您不能将任何项目直接添加到分页控件,它需要设置页面工厂。使用类的setPageFactory
方法Pagination
通过实现页面工厂来定义页面内容。
实施页面工厂
将setPageFactory
被用于定义分页控件的页面工厂。应用程序开发人员创建一个回调方法并将分页页面工厂设置为使用此回调。选择页面时将调用回调方法。它加载并返回所选页面的内容。null
如果所选页面索引不存在,则必须返回该值。例25-2创建了一个包含28页的分页控件,并使用搜索结果填充页面,每页分配8个项目。
示例25-2将超链接添加到分页控件
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.Node;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class PaginationSample extends Application {
private Pagination pagination;
public static void main(String[] args) throws Exception {
launch(args);
}
public int itemsPerPage() {
return 8;
}
public VBox createPage(int pageIndex) {
VBox box = new VBox(5);
int page = pageIndex * itemsPerPage();
for (int i = page; i < page + itemsPerPage(); i++) {
VBox element = new VBox();
Hyperlink link = new Hyperlink("Item " + (i+1));
link.setVisited(true);
Label text = new Label("Search results\nfor "+ link.getText());
element.getChildren().addAll(link, text);
box.getChildren().add(element);
}
return box;
}
@Override
public void start(final Stage stage) throws Exception {
pagination = new Pagination(28, 0);
pagination.setStyle("-fx-border-color:red;");
pagination.setPageFactory(new Callback<Integer, Node>() {
@Override
public Node call(Integer pageIndex) {
return createPage(pageIndex);
}
});
AnchorPane anchor = new AnchorPane();
AnchorPane.setTopAnchor(pagination, 10.0);
AnchorPane.setRightAnchor(pagination, 10.0);
AnchorPane.setBottomAnchor(pagination, 10.0);
AnchorPane.setLeftAnchor(pagination, 10.0);
anchor.getChildren().addAll(pagination);
Scene scene = new Scene(anchor);
stage.setScene(scene);
stage.setTitle("PaginationSample");
stage.show();
}
}
页面数和所选页面是在Pagination
类的构造函数中定义的。或者,您可以Pagination
使用setPageCount
和setCurrentPageIndex
方法创建控件并随后设置页数和所选页面的索引。
Pagination
控件的内容在createPage
用作页面工厂的方法中声明,并由setPageFactory
方法调用。该createPage
方法创建超链接对和相应的标签,并垂直排列,在元素之间设置五个像素的间隔。
编译并运行例25-2时,应该看到如图25-4所示的输出。
图25-4使用分页控件预览搜索结果
Pagination
如果页数超过10 ,则控件的当前实现显示10个页面指示符。要为显示的页面指示符设置替代值,请使用类的setMaxPageIndicatorCount
方法Pagination
。例如,将以下行添加到示例25-2以显示七个页面指示符:pagination.setMaxPageIndicatorCount(7);
。图25-5显示了应用更改后的PaginationSample应用程序。
图25-5更改页面指示符的数量
例25-3显示了分页控件的另一种用法。应用程序呈现文本片段,每页一个。片段的数量为5,并且分页控件的声明页数为28.要避免某种ArrayIndexOutOfBoundsException
情况,请添加页面索引检查(在示例25-3中以粗体突出显示)并使回调方法在返回null
时返回页数超过五。
示例25-3将文本片段添加到分页控件
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.Node;
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class PaginationSample extends Application {
private Pagination pagination;
final String[] textPages = new String[]{
"The apple is the pomaceous fruit of the apple tree, species Malus "
+ "domestica in the rose family (Rosaceae). It is one of the most "
+ "widely cultivated tree fruits, and the most widely known of "
+ "the many members of genus Malus that are used by humans. "
+ "The tree originated in Western Asia, where its wild ancestor, "
+ "the Alma, is still found today.",
"The hawthorn is a large genus of shrubs and trees in the rose family,"
+ "Rosaceae, native to temperate regions of the Northern Hemisphere "
+ "in Europe, Asia and North America. The name hawthorn was "
+ "originally applied to the species native to northern Europe, "
+ "especially the Common Hawthorn C. monogyna, and the unmodified "
+ "name is often so used in Britain and Ireland.",
"The ivy is a flowering plant in the grape family (Vitaceae) native to "
+ " eastern Asia in Japan, Korea, and northern and eastern China. "
+ "It is a deciduous woody vine growing to 30 m tall or more given "
+ "suitable support, attaching itself by means of numerous small "
+ "branched tendrils tipped with sticky disks.",
"The quince is the sole member of the genus Cydonia and is native to "
+ "warm-temperate southwest Asia in the Caucasus region. The "
+ "immature fruit is green with dense grey-white pubescence, most "
+ "of which rubs off before maturity in late autumn when the fruit "
+ "changes color to yellow with hard, strongly perfumed flesh.",
"Aster (syn. Diplopappus Cass.) is a genus of flowering plants "
+ "in the family Asteraceae. The genus once contained nearly 600 "
+ "species in Eurasia and North America, but after morphologic "
+ "and molecular research on the genus during the 1990s, it was "
+ "decided that the North American species are better treated in a "
+ "series of other related genera. After this split there are "
+ "roughly 180 species within the genus, all but one being confined "
+ "to Eurasia."
};
public static void main(String[] args) throws Exception {
launch(args);
}
public int itemsPerPage() {
return 1;
}
public VBox createPage(int pageIndex) {
VBox box = new VBox(5);
int page = pageIndex * itemsPerPage();
for (int i = page; i < page + itemsPerPage(); i++) {
TextArea text = new TextArea(textPages[i]);
text.setWrapText(true);
box.getChildren().add(text);
}
return box;
}
@Override
public void start(final Stage stage) throws Exception {
pagination = new Pagination(28, 0);
pagination.setStyle("-fx-border-color:red;");
pagination.setPageFactory(new Callback<Integer, Node>() {
@Override
public Node call(Integer pageIndex) {
if (pageIndex >= textPages.length) {
return null;
} else {
return createPage(pageIndex);
}
}
});
AnchorPane anchor = new AnchorPane();
AnchorPane.setTopAnchor(pagination, 10.0);
AnchorPane.setRightAnchor(pagination, 10.0);
AnchorPane.setBottomAnchor(pagination, 10.0);
AnchorPane.setLeftAnchor(pagination, 10.0);
anchor.getChildren().addAll(pagination);
Scene scene = new Scene(anchor, 400, 250);
stage.setScene(scene);
stage.setTitle("PaginationSample");
stage.show();
}
}
编译并运行例25-3时,您将看到如图25-6所示的输出。
图25-6在分页控件中渲染文本片段
在某些情况下,您无法设置要呈现的确切项目数,因此也无法设置分页控件中的页数。在这种情况下,您可以包含一行代码,用于计算Pagination
对象构造函数中的页数。例25-4输出系统字体列表,并计算页数作为字体数组的长度除以每页的项数。
示例25-4添加未确定大小的内容
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
public class PaginationSample extends Application {
private Pagination pagination;
String[] fonts = new String[]{};
public static void main(String[] args) throws Exception {
launch(args);
}
public int itemsPerPage() {
return 15;
}
public VBox createPage(int pageIndex) {
VBox box = new VBox(5);
int page = pageIndex * itemsPerPage();
for (int i = page; i < page + itemsPerPage(); i++) {
Label font = new Label(fonts[i]);
box.getChildren().add(font);
}
return box;
}
@Override
public void start(final Stage stage) throws Exception {
fonts = Font.getFamilies().toArray(fonts);
pagination = new Pagination(fonts.length/itemsPerPage(), 0);
pagination.setStyle("-fx-border-color:red;");
pagination.setPageFactory(new Callback<Integer, Node>() {
@Override
public Node call(Integer pageIndex) {
return createPage(pageIndex);
}
});
AnchorPane anchor = new AnchorPane();
AnchorPane.setTopAnchor(pagination, 10.0);
AnchorPane.setRightAnchor(pagination, 10.0);
AnchorPane.setBottomAnchor(pagination, 10.0);
AnchorPane.setLeftAnchor(pagination, 10.0);
anchor.getChildren().addAll(pagination);
Scene scene = new Scene(anchor, 400, 450);
stage.setScene(scene);
stage.setTitle("PaginationSample");
stage.show();
}
}
编译并运行此示例时,它将生成如图25-7所示的应用程序窗口。
图25-7使用分页控件渲染系统字体
设计分页控制
您可以通过设置样式类来自定义分页控件以显示项目符号页面指示符而不是数字页面指示符STYLE_CLASS_BULLET
。此外,您可以在caspian
样式表中修改默认的分页样式。
例25-5给出了例25-4中分页控件的可视元素的一些替代样式。
例25-5分页控制的修改样式
.pagination {
-fx-border-color: #0E5D79;
}
.pagination .page {
-fx-background-color: #DDF1F8;
}
.pagination .pagination-control {
-fx-background-color: #C8C6C6;
}
.pagination .pagination-control .bullet-button {
-fx-background-color: transparent, #DDF1F8, #0E5D79, white, white;
}
.pagination .pagination-control .bullet-button:selected {
-fx-background-color: transparent, #DDF1F8, #0E5D79, white, #0E5D79;
}
.pagination .pagination-control .left-arrow, .right-arrow{
-fx-background-color: #DDF1F8, #0E5D79;
}
例25-6将这些样式应用于分页控件,并为页面指示器设置项目符号样式。
例25-6在PaginationSample应用程序中启用修改的分页控制样式
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
public class PaginationSample extends Application {
private Pagination pagination;
String[] fonts = new String[]{};
public static void main(String[] args) throws Exception {
launch(args);
}
public int itemsPerPage() {
return 15;
}
public VBox createPage(int pageIndex) {
VBox box = new VBox(5);
int page = pageIndex * itemsPerPage();
for (int i = page; i < page + itemsPerPage(); i++) {
Label font = new Label(fonts[i]);
box.getChildren().add(font);
}
return box;
}
@Override
public void start(final Stage stage) throws Exception {
fonts = Font.getFamilies().toArray(fonts);
pagination = new Pagination(fonts.length/itemsPerPage(), 0);
pagination.getStyleClass().add(Pagination.STYLE_CLASS_BULLET);
pagination.setPageFactory(new Callback<Integer, Node>() {
@Override
public Node call(Integer pageIndex) {
return createPage(pageIndex);
}
});
AnchorPane anchor = new AnchorPane();
AnchorPane.setTopAnchor(pagination, 10.0);
AnchorPane.setRightAnchor(pagination, 10.0);
AnchorPane.setBottomAnchor(pagination, 10.0);
AnchorPane.setLeftAnchor(pagination, 10.0);
anchor.getChildren().addAll(pagination);
Scene scene = new Scene(anchor, 400, 450);
stage.setScene(scene);
stage.setTitle("PaginationSample");
scene.getStylesheets().add("paginationsample/ControlStyle.css");
stage.show();
}
}
将新定义的样式应用于PaginationSample应用程序并编译并运行它时,您将看到如图25-8所示的应用程序窗口。
图25-8带子弹页面指示符的PaginationSample和应用的新CSS样式
除了应用的样式,您还可以考虑以下样式来更改应用程序中分页控件的外观:
-fx-max-page-indicator-count
- 设置页面指示符的最大数量。-fx-arrows-visible
-true
默认情况下,切换“下一个”和“上一个”按钮箭头的可见性。-fx-tooltip-visible
-true
默认情况下,切换页面指示器工具提示的可见性。-fx-page-information-visible
-true
默认情况下,切换页面信息的可见性。-fx-page-information-alignment
- 设置页面信息的对齐方式。
相关的API文档