期待新書出版,以下是我借用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)); } } }; } }); ...【執行結果】