期待新書出版,以下是我借用caterpillar林信良所著之Java SE 8 技術手冊所改編的封面,書商不見得會使用,但自得其樂。

© Chia-Hui Huang

private final class TextFieldCellCallback
extends TreeTableCell<Department, String> {
TextField textfield;
// 建構函式
public TextFieldCellCallback() {
// 設定欄位內容為置中對齊
setAlignment(Pos.CENTER);
}
...
}
...
在TextFieldCellCallback類別中,分別覆寫TreeTableCell類別的startEdit()、cancelEdit()與updateItem()方法以處理開始編輯、取消編輯與更新樹狀表格單元等。// 覆寫TreeTableCell類別的startEdit()方法
@Override public void startEdit() {
super.startEdit();
if (textfield == null) {
textfield = new TextField(getItem() == null ? "" : getItem());
textfield.setMinWidth(this.getWidth()-this.getGraphicTextGap()*2);
textfield.setOnKeyReleased((KeyEvent e) -> {
if (e.getCode() == KeyCode.ENTER) {
// 完成編輯樹狀表格單元
commitEdit(textfield.getText());
}
else if (e.getCode() == KeyCode.ESCAPE) {
// 取消編輯樹狀表格單元
cancelEdit();
}
});
}
setText(null);
// 將樹狀表格單元設定為文字欄位
setGraphic(textfield);
textfield.selectAll();
}
...
須注意的是,由於需要編輯樹狀表格單元,因此須以TreeTableView類別的setEditable()方法設定Tree Table View為可編輯狀態,並以TreeTableView類別的setCellFactory()方法以下列方式設定Cell Factory的回呼函式:TreeTableView<Department> treeTableView = null;
treeTableView = new TreeTableView<>();
// 設定Tree Table View為可編輯狀態
treeTableView.setEditable(true);
// 建立直行
TreeTableColumn<Department, String> treeTableColumn1 =
new TreeTableColumn<>("Faculty");
// 設定Cell Factory的回呼函式
treeTableColumn1.setCellFactory(
(TreeTableColumn<Department, String> value) ->
new TextFieldCellCallback());
...
【執行結果】// 建立直行
TreeTableColumn<Department, Boolean> treeTableColumn5 =
new TreeTableColumn<>("Check");
// 設定直行最小寬度
treeTableColumn5.setPrefWidth(60);
// 設定直行標題的圖像
treeTableColumn5.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/checkbox.gif"))));
// 設定Cell Factory
treeTableColumn5.setCellFactory(
CheckBoxTreeTableCell.forTreeTableColumn(treeTableColumn5));
treeTableColumn5.setEditable(true);
...
【執行結果】// 建立直行
TreeTableColumn<Department, String> treeTableColumn5 =
new TreeTableColumn<>("Phone");
// 設定直行最小寬度
treeTableColumn5.setPrefWidth(60);
// 設定直行標題的圖像
treeTableColumn5.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/choicebox.gif"))));
// 設定選項方塊的選項項目
ObservableList phonelists = FXCollections.observableArrayList(
"4059", "4330", "5390",
"5600", "5720", "6399",
"6400", "6401", "6506");
// 設定Cell Factory
treeTableColumn5.setCellFactory(
ChoiceBoxTreeTableCell.forTreeTableColumn(phonelists));
treeTableColumn5.setEditable(true);
...
【執行結果】// 建立直行
TreeTableColumn<Department, String> treeTableColumn5 =
new TreeTableColumn<>("Phone");
// 設定直行最小寬度
treeTableColumn5.setPrefWidth(60);
// 設定直行標題的圖像
treeTableColumn5.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/combobox.gif"))));
// 設定選項方塊的選項項目
ObservableList phonelists = FXCollections.observableArrayList(
"4059", "4330", "5390",
"5600", "5720", "6399",
"6400", "6401", "6506");
// 設定Cell Factory
treeTableColumn5.setCellFactory(
ComboBoxTreeTableCell.forTreeTableColumn(phonelists));
treeTableColumn5.setEditable(true);
...
【執行結果】// 建立直行
TreeTableColumn<Department, String> treeTableColumn1 =
new TreeTableColumn<>("Faculty");
// 設定直行最小寬度
treeTableColumn1.setPrefWidth(80);
// 設定直行標題的圖像
treeTableColumn1.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/faculty.gif"))));
// 設定直行對應於資料陣列的順序
treeTableColumn1.setCellValueFactory(
(TreeTableColumn.CellDataFeatures<Department, String> param) ->
new ReadOnlyStringWrapper(param.getValue().getValue().getFaculty())
);
// 設定Cell Factory
treeTableColumn1.setCellFactory(
TextFieldTreeTableCell.forTreeTableColumn());
treeTableColumn1.setEditable(true);
...
【執行結果】private final class TextFieldCellCallback extends TableCell<> {
TextField textfield;
ContextMenu contextmenu = new ContextMenu();
// 建構函式
public TextFieldCellCallback() {
// 設定欄位內容為置中對齊
setAlignment(Pos.CENTER);
// 建立快顯選單
MenuItem menuitem = new MenuItem("Add New Row");
menuitem.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/row.gif"))));
menuitem.setOnAction((ActionEvent e) -> {
// 新增一表格橫列
data.add(new Product("", "", "", "", ""));
});
contextmenu.getItems().add(menuitem);
}
...
}
...
在TextFieldCellCallback類別中,分別覆寫TableCell類別的startEdit()、cancelEdit()與updateItem()方法以處理開始編輯、取消編輯與更新表格單元等。// 覆寫TableCell類別的startEdit()方法
@Override public void startEdit() {
super.startEdit();
if (textfield == null) {
textfield = new TextField(getItem() == null ? "" : getItem());
textfield.setMinWidth(this.getWidth()-this.getGraphicTextGap()*2);
textfield.setOnKeyReleased((KeyEvent e) -> {
if (e.getCode() == KeyCode.ENTER) {
// 完成編輯表格單元
commitEdit(textfield.getText());
}
else if (e.getCode() == KeyCode.ESCAPE) {
// 取消編輯表格單元
cancelEdit();
}
});
}
setText(null);
// 將表格單元設定為文字欄位
setGraphic(textfield);
textfield.selectAll();
}
...
須注意的是,由於需要編輯表格單元,因此須以TableView類別的setEditable()方法設定Table View為可編輯狀態,並以TableView類別的setCellFactory()方法以下列方式設定Cell Factory的回呼函式:TableView<Product> tableView = new TableView<>();
// 設定Table View為可編輯狀態
tableView.setEditable(true);
TableColumn column[] = new TableColumn[title.length];
column[i].setCellFactory(new Callback<TableColumn<Product, String>,
TableCell<Product, String>>() {
@Override public TableCell<Product, String> call(
TableColumn<Product, String> value) {
return new TextFieldCellCallback();
}
});
...
【執行結果】 TableColumn column[] = new TableColumn[title.length];
for (int i=0; i<title.length; i++) {
column[i] = new TableColumn(title[i]);
column[i].setMinWidth(width[i]);
// 設定直行標題的圖像
column[i].setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/icon" + (i+1) + ".gif"))));
if (i!=4) {
// 設定直行對應於資料陣列的順序
column[i].setCellValueFactory(
new PropertyValueFactory<>(cellValue[i]));
}
else { // CheckBoxTableCell
// 設定直行對應於資料陣列的順序
column[i].setCellValueFactory(
new PropertyValueFactory<>(cellValue[i]));
// 設定Cell Factory
column[i].setCellFactory(
CheckBoxTableCell.forTableColumn(column[i]));
column[i].setEditable(true);
}
}
...
【執行結果】 TableColumn column[] = new TableColumn[title.length]; ... // 設定選項方塊的選項項目 ObservableList<String> items = FXCollections.observableArrayList( "JX001", "JX002", "JX003", "JX004", "JX005", "JX006", "JX007", "JX008", "JX009", "JX010"); column[i] = new TableColumn(title[i]); // 設定直行對應於資料陣列的順序 column[i].setCellValueFactory( new PropertyValueFactory<>(cellValue[i])); // 設定Cell Factory column[i].setCellFactory( ChoiceBoxTableCell.forTableColumn(items)); column[i].setEditable(true); ...【執行結果】
TableColumn column[] = new TableColumn[title.length]; ... // 設定選項方塊的選項項目 ObservableList<String> items = FXCollections.observableArrayList( "JX001", "JX002", "JX003", "JX004", "JX005", "JX006", "JX007", "JX008", "JX009", "JX010"); column[i] = new TableColumn(title[i]); // 設定直行對應於資料陣列的順序 column[i].setCellValueFactory( new PropertyValueFactory<>(cellValue[i])); // 設定Cell Factory column[i].setCellFactory( ComboBoxTableCell.forTableColumn(items)); column[i].setEditable(true); ...【執行結果】
private final class ProgressBarTask extends Task<Void> {
int waiting;
int pausing;
ProgressBarTask(int _waiting, int _pausing) {
this.waiting = _waiting;
this.pausing = _pausing;
}
@Override protected Void call() throws Exception {
this.updateProgress(ProgressIndicator.INDETERMINATE_PROGRESS, 1);
this.updateMessage("Waiting...");
Thread.sleep(waiting);
this.updateMessage("Running...");
for (int i=0; i<500; i++) {
updateProgress((1.0*i)/500, 1);
Thread.sleep(pausing);
}
this.updateMessage("Done");
this.updateProgress(1, 1);
return null;
}
}
...
接著以TableColumn類別的setCellFactory()方法設定Cell Factory為ProgressBarTableCell,並以其forTableColumn()方法以進度列取代原表格單元:Random randomv = new Random();
for (int i=0; i<10; i++) {
tableView.getItems().add(new ProgressBarTask(
randomv.nextInt(5000)+1000, randomv.nextInt(50)+10));
}
TableColumn<ProgressBarTask, Double> column1 =
new TableColumn("Progress");
column1.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/icon1.gif"))));
// 設定直行對應於資料陣列的順序
column1.setCellValueFactory(new PropertyValueFactory<>("progress"));
// 設定Cell Factory
column1.setCellFactory(
ProgressBarTableCell.<ProgressBarTask>forTableColumn());
TableColumn<ProgressBarTask, String> column2 =
new TableColumn("Status");
column2.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/icon2.gif"))));
// 設定直行對應於資料陣列的順序
column2.setCellValueFactory(new PropertyValueFactory<>("message"));
column2.setPrefWidth(80);
...
【執行結果】 TableColumn column[] = new TableColumn[title.length]; ... column[i] = new TableColumn(title[i]); column[i].setMinWidth(width[i]); // 設定直行對應於資料陣列的順序 column[i].setCellValueFactory( new PropertyValueFactory<>(cellValue[i])); // 設定Cell Factory column[i].setCellFactory(TextFieldTableCell.forTableColumn()); column[i].setEditable(true); ...【執行結果】
private final class TreeCellCallback extends TreeCell<String> {
TextField textfield;
ContextMenu contextmenu = new ContextMenu();
// 建構函式
public TreeCellCallback() {
MenuItem menuitem = new MenuItem("Add Tree Node");
menuitem.setGraphic(new ImageView(new Image(
getClass().getResourceAsStream("images/node.gif"))));
menuitem.setOnAction((ActionEvent e) -> {
TreeItem treeitem = new TreeItem<>("New Tree Node...",
new ImageView(imgFile));
getTreeItem().getChildren().add(treeitem);
});
contextmenu.getItems().add(menuitem);
}
@Override public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
}
else {
setText(getItem() == null ? "" : getItem());
setGraphic(getTreeItem().getGraphic());
if (!getTreeItem().isLeaf() && getTreeItem().getParent()!= null){
setContextMenu(contextmenu);
}
}
}
}
...
待完成自定類別之後,須以TreeView類別的setCellFactory()方法以下列方式設定Cell Factory的回呼函式:treeView.setCellFactory(
new Callback<TreeView<String>, TreeCell<String>>(){
@Override public TreeCell<String> call(TreeView<String> value) {
return new TreeCellCallback();
}
}
);
...
【執行結果】 // 覆寫TreeCell類別的startEdit()方法
@Override public void startEdit() {
super.startEdit();
if (textfield == null) {
textfield = new TextField(getItem() == null ? "" : getItem());
textfield.setOnKeyReleased((KeyEvent e) -> {
if (e.getCode() == KeyCode.ENTER){
// 完成編輯樹狀單元
commitEdit(textfield.getText());
}
else if (e.getCode() == KeyCode.ESCAPE) {
// 取消編輯樹狀單元
cancelEdit();
}
});
}
setText(null);
// 將節點設定為文字欄位
setGraphic(textfield);
textfield.selectAll();
}
...
以取消編輯為例,在覆寫cancelEdit()方法中,由於取消編輯並未改變樹狀單元的內容,因此分別以setText()與setGraphic()方法設定為原標題文字與圖像,以恢復節點為原來的內容:// 覆寫TreeCell類別的cancelEdit()方法
@Override public void cancelEdit() {
super.cancelEdit();
// 設定為原標題文字
setText((String) getItem());
// 將節點設定為原圖像
setGraphic(getTreeItem().getGraphic());
}
...
須注意的是,由於需要編輯節點,因此須以TreeView類別的setEditable()方法設定Tree View為可編輯狀態,並以TreeView類別的setCellFactory()方法以下列方式設定Cell Factory的回呼函式:treeView.setEditable(true);
treeView.setCellFactory(
new Callback<TreeView<String>, TreeCell<String>>(){
@Override public TreeCell<String> call(TreeView<String> value) {
return new TreeCellCallback();
}
}
);
...
【執行結果】 // 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定Cell Factory treeView.setCellFactory(CheckBoxTreeCell.<String>forTreeView()); ...【執行結果】
// 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定選項方塊的選項項目 ObservableList<String> items = FXCollections.observableArrayList( "Profile", "Course", "Publication", "Book", "Project"); // 設定Cell Factory treeView.setCellFactory(ChoiceBoxTreeCell.forTreeView(items)); ...【執行結果】
// 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定複合方塊的選項項目 ObservableList<String> items = FXCollections.observableArrayList( "Profile", "Course", "Publication", "Book", "Project"); // 設定Cell Factory treeView.setCellFactory(ComboBoxTreeCell.forTreeView(items)); ...【執行結果】
// 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定Cell Factory treeView.setCellFactory(TextFieldTreeCell.forTreeView()); ...【執行結果】
String title[] = new String[10];
for (int i=0; i < 10; i++)
title[i] = "Item " + i;
final ComboBox combobox1 = new ComboBox();
combobox1.setItems(FXCollections.observableArrayList(title));
combobox1.setValue("Item 0");
combobox1.setPromptText("Editable");
combobox1.setVisibleRowCount(5);
combobox1.setEditable(true);
// Cell Factory
combobox1.setCellFactory(
new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> param) {
return new ListCell<String>()
{
{
super.setPrefWidth(60);
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item);
if (item.contains("Item 0"))
setTextFill(Color.RED);
else if (item.contains("Item 1"))
setTextFill(Color.GREEN);
else if (item.contains("Item 2"))
setTextFill(Color.BLUE);
else if (item.contains("Item 3"))
setTextFill(Color.AQUA);
else if (item.contains("Item 4"))
setTextFill(Color.BLUEVIOLET);
else if (item.contains("Item 5"))
setTextFill(Color.CHOCOLATE);
else if (item.contains("Item 6"))
setTextFill(Color.DIMGRAY);
else if (item.contains("Item 7"))
setTextFill(Color.FORESTGREEN);
else if (item.contains("Item 8"))
setTextFill(Color.GREENYELLOW);
else if (item.contains("Item 9"))
setTextFill(Color.INDIGO);
}
else {
setText(null);
}
}
};
}
});
...
【執行結果】 final ComboBox<Color> combobox2 = new ComboBox<>();;
combobox2.getItems().addAll(
Color.RED, Color.GREEN, Color.BLUE, Color.AQUA,
Color.BLUEVIOLET, Color.CHOCOLATE, Color.DIMGRAY,
Color.FORESTGREEN, Color.GREENYELLOW, Color.INDIGO);
// select the last element
combobox2.getSelectionModel().select(3);
combobox2.setVisibleRowCount(5);
combobox2.setEditable(false);
// Cell Factory
combobox2.setCellFactory(
new Callback<ListView<Color>, ListCell<Color>>() {
@Override
public ListCell<Color> call(ListView<Color> param) {
return new ListCell<Color>()
{
{
super.setPrefWidth(60);
}
private final Rectangle rectangle;
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
rectangle = new Rectangle(70, 15);
}
@Override
protected void updateItem(Color item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
}
else {
rectangle.setFill(item);
setGraphic(rectangle);
}
}
};
}
});
...
【執行結果】 ObservableList<String> data = FXCollections.observableArrayList( "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); // ListView with TextFieldListCell final ListView<String> listview1 = new ListView<>(); // 設定單選模式 listview1.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); listview1.setItems(data); listview1.setPrefWidth(150); listview1.setPrefHeight(100); listview1.setOrientation(Orientation.VERTICAL); listview1.setEditable(true); listview1.setCellFactory(TextFieldListCell.forListView()); ... ObservableList<String> data = FXCollections.observableArrayList( "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); // ListView with ComboBoxListCell final ListView<String> listview2 = new ListView<>(); // 設定複選模式 Listview2.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); listview2.setItems(data); listview2.setPrefWidth(150); listview2.setPrefHeight(100); listview2.setOrientation(Orientation.VERTICAL); listview2.setEditable(true); listview2.setCellFactory(ComboBoxListCell.forListView(data)); ...【執行結果】
// 建立根節點
TreeItem<String> treeRoot = new TreeItem<>("Root node");
// 設定節點的展開狀態
treeRoot.setExpanded(true);
...
接著以TreeItem類別建立子節點,並以TreeItem類別的getChildren().add()或getChildren().addAll()方法依序將子節點加入至根節點之中:// 建立子節點
TreeItem<String> treeItem1 = new TreeItem<>("Profile");
TreeItem<String> treeItem2 = new TreeItem<>("Course");
TreeItem<String> treeItem3 = new TreeItem<>("Publication");
TreeItem<String> treeItem4 = new TreeItem<>("Book");
TreeItem<String> treeItem5 = new TreeItem<>("Project");
// 依序將子節點加入至根節點之中
treeRoot.getChildren().addAll(
treeItem1, treeItem2, treeItem3, treeItem4, treeItem5);
...
待建立樹狀物件之後,則以TreeTableColumn類別設定直行的相關屬性如直行標題,本範例僅設定一直行:// 設定直行標題
TreeTableColumn<String,String> treeTableColumn =
new TreeTableColumn<>("Vita");
// 設定直行屬性
treeTableColumn.setCellValueFactory(
(CellDataFeatures<String,String> p) ->
new ReadOnlyStringWrapper(p.getValue().getValue()));
...
最後以TreeTableView類別的getColumns().add()或getColumns().addAll()方法依序將直行加入至樹狀表格之中:// 建立TreeTableView物件 TreeTableView<String> treeTableView = null; treeTableView = new TreeTableView<>(treeRoot); // 依序將直行加入至樹狀表格之中 treeTableView.getColumns().add(treeTableColumn); // 設定是否顯示根節點 treeTableView.setShowRoot(true); // 設定是否可以選擇樹狀表格單元 treeTableView.getSelectionModel().setCellSelectionEnabled(false); // 設定複選模式 treeTableView.getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE); // 設定直行的調整原則 treeTableView.setColumnResizePolicy( TreeTableView.CONSTRAINED_RESIZE_POLICY); // 設定是否顯示樹狀表格選單按鈕 treeTableView.setTableMenuButtonVisible(true); ...【執行結果】
// 自定Department類別
public class Department {
private SimpleStringProperty faculty;
private SimpleStringProperty position;
private SimpleStringProperty email;
private SimpleStringProperty office;
private SimpleStringProperty phone;
public Department(String _faculty, String _position,
String _email, String _office, String _phone) {
this.faculty = new SimpleStringProperty(_faculty);
this.position = new SimpleStringProperty(_position);
this.email = new SimpleStringProperty(_email);
this.office = new SimpleStringProperty(_office);
this.phone = new SimpleStringProperty(_phone);
}
public SimpleStringProperty facultyProperty() {
if (faculty == null) {
faculty = new SimpleStringProperty(this, "faculty");
}
return faculty;
}
...
public String getFaculty() {
return faculty.get();
}
public void setFaculty(String _faculty) {
faculty.set(_faculty);
}
...
}
...
以此自定的Department類別建立節點陣列:// 建立節點陣列
ObservableList<Department> department =
FXCollections.observableArrayList(
new Department("Athena", "Associate Professor", "athena@edu.tw",
"725", "6400"),
new Department("Leo", "Associate Professor", "leo@edu.tw",
"813", "6506"),
new Department("Teresa", "Professor", "teresa@edu.tw",
"825", "4059"),
...);
...
【執行結果】final DatePicker datepicker = new DatePicker();
datepicker.setOnAction(event -> {
// 取得所選擇的日期
LocalDate date = datepicker.getValue();
System.out.println("選擇的日期為: " + date);
});
...
【執行結果】ToggleGroup togglegroup = new ToggleGroup();
RadioMenuItem radiomenuitem1 = new RadioMenuItem("Hijrah");
radiomenuitem1.setSelected(false);
radiomenuitem1.setToggleGroup(togglegroup);
radiomenuitem1.setOnAction((ActionEvent e) -> {
// 設定伊斯蘭年曆系統
datepicker.setChronology(HijrahChronology.INSTANCE);
});
RadioMenuItem radiomenuitem2 = new RadioMenuItem("ISO-8601");
radiomenuitem2.setSelected(true);
radiomenuitem2.setToggleGroup(togglegroup);
radiomenuitem2.setOnAction((ActionEvent e) -> {
// 設定ISO-8601年曆系統
datepicker.setChronology(IsoChronology.INSTANCE);
});
RadioMenuItem radiomenuitem3 = new RadioMenuItem("Japanese");
radiomenuitem3.setSelected(false);
radiomenuitem3.setToggleGroup(togglegroup);
radiomenuitem3.setOnAction((ActionEvent e) -> {
// 設定日本年曆系統
datepicker.setChronology(JapaneseChronology.INSTANCE);
});
RadioMenuItem radiomenuitem4 = new RadioMenuItem("R.O.C.");
radiomenuitem4.setSelected(false);
radiomenuitem4.setToggleGroup(togglegroup);
radiomenuitem4.setOnAction((ActionEvent e) -> {
// 設定中華民國年曆系統
datepicker.setChronology(MinguoChronology.INSTANCE);
});
RadioMenuItem radiomenuitem5 = new RadioMenuItem("Thai Buddhist");
radiomenuitem5.setSelected(false);
radiomenuitem5.setToggleGroup(togglegroup);
radiomenuitem5.setOnAction((ActionEvent e) -> {
// 設定泰國佛歷年曆系統
datepicker.setChronology(ThaiBuddhistChronology.INSTANCE);
});
...
【執行結果】// 設定日期格式
String pattern = "MMM-dd-yyyy";
StringConverter converter = new StringConverter<localdate>() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
@Override public String toString(LocalDate date) {
if (date != null) {
return formatter.format(date);
}
else {
return "";
}
}
@Override public LocalDate fromString(String string) {
if (string != null && !string.isEmpty()) {
return LocalDate.parse(string, formatter);
}
else {
return null;
}
}
};
datepicker = new DatePicker();
// 設定日期格式的型別轉換器
datepicker.setConverter(converter);
...
【執行結果】// 設定日期選擇器的Cell Factory
datepicker.setDayCellFactory(new Callback<DatePicker, DateCell>() {
@Override public DateCell call(final DatePicker datePicker) {
return new DateCell() {
@Override public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);
if (item.isBefore(today)) {
setDisable(true);
// 設定背景顏色
setStyle("-fx-background-color: #93d1f0;");
}
else if (item.equals(today)) {
// 設定提示說明
setTooltip(new Tooltip("Today is " + today));
}
else if (item.equals(tomorrow)) {
// 設定提示說明
setTooltip(new Tooltip("Tomorrow is " + tomorrow));
}
// 設定提示說明
else if (item.isAfter(tomorrow)) {
setTooltip(new Tooltip("Day after " + tomorrow));
}
}
};
}
});
...
【執行結果】