JavaFX8初階技術介紹 Grace 2015.04.14 1 Agenda 內容 1 2 3 JavaFX Json SQLite 2 JAVAFX 3 JavaFX 簡介、架構 開發工具 技術簡介 佈署 4 Java R.I.A. • R.I.A. : Rich Internet Application • Java R.I.A. – Java AWT : Heavyweight物件(取決於OS) – Java Swing : Lightweight物件(執行時改變外觀,JDK1.1) – Java FX Script • 2007.05 JavaOne發表 • MVC架構 : 使用繪圖軟體(illustrator,Photoshop)存成fx檔案, 再使用Java FX Script – JavaFX2.2 • 併入Java S.E. 7 Update 6 – JavaFX 8 • 併入Java S.E. 8 5 JavaFX 2 • 功能 – GUI類別及功能 – Builder類別 : 可精簡程式長度,JavaFX 8 移除 – CSS : 設定物件樣式 – JavaFX Scene Builder 1.1: 將View儲存成fxml檔 6 JavaFX 8 • 與JavaFX2差異 – 移除各物件對應的Builder類別 – Lambda Expression (JDK 8新增) – JavaFX Scene Builder 2.0 – 新增Modena主題、DatePicker & TreeTable、 Candle Stick圖表、錄音 & 錄影、支援3D、 Shaders for OpenGL and Direct3D、Java S.E. Embedded、Sensor、列印、Rich Text格式、 JavaScript、HTML5 7 JavaFX 未來規劃 JDK8(Q1 2014) - Lambda JVM Convergence JavaScript Interop JavaFX 8 JDK8u20(Q3 2014) JDK9 - - - App bundling enhancements 2014 NetBeans IDE 8 - JDK 8 support Scene Builder 2.0 Support Scene Builer 2.0 - Deterministic G1 Java Mission Control 6.0 Improved JRE installer JavaFX 8 Support Enhanced Java IDE Support JDK8u40 2015 JavaFX對於行動平台的 支援才剛開始發展,有 待後續持續觀注 Modularity – Jigsaw Interoperability Cloud Ease of Use JavaFX JSR Optimizations 預計JDK9將JavaFX納入 正式的規範(JSR,Java Specification Requests) 2016 NetBeans IDE 8 - JDK 9 support Scene Builder 3.0 Support Scene Builer 3.0 - JavaFX 9 Support 8 JavaFX 架構 • Write Once , Deploy Anywhere 繪圖 視窗管理 影音 9 JavaFX程式架構 • Application class – init() : 初始化JavaFX應用程式 – start() : JavaFX應用程式進入點,即 Java Applet – launch() : 啟動standalone的JavaFX應用程式 – stop() : JavaFX應用程式結束前會呼叫的方法 10 JavaFX MVC 程式架構(1/2) • MVC架構 Invoke (調用) Presenter (FXML Controller) View (FXML) Observe Notify Update Presentation Model Get data Return data Service 11 JavaFX MVC 程式架構(2/2) Model View Controller 12 Java Fx 簡介、架構 開發工具 技術簡介 佈署 App應用(含SQLite) 13 支援JavaFX8 Eclipse 套件 1/3 • http://download.eclipse.org/eclipse/downloa ds/ 14 支援JavaFX8 Eclipse 套件 2/3 • Help => Install New Software… => Location請 輸入http://download.eclipse.org/efxclipse/updates-released/1.0.0/site 15 支援JavaFX8 Eclipse 套件 3/3 16 JavaFX Scene Builder 1/3 • 下載並安裝javafx_scenebuilder-2_0windows.msi 17 JavaFX Scene Builder 2/3 18 JavaFX Scene Builder 3/3 19 Java Fx 簡介、架構 開發工具 技術簡介 佈署 20 技術簡介 Graphics User Interface Component 21 Shape3D - PreDefine public HBox addShape3D() { HBox hbox = new HBox(); PhongMaterial redMaterial = new PhongMaterial(); redMaterial.setSpecularColor(Color.ORANGE); redMaterial.setDiffuseColor(Color.RED); setSpecularColor 鏡面 setDiffuseColor 擴散 PhongMaterial blueMaterial = new PhongMaterial(); blueMaterial.setDiffuseColor(Color.BLUE); blueMaterial.setSpecularColor(Color.LIGHTBLUE); PhongMaterial greyMaterial = new PhongMaterial(); greyMaterial.setDiffuseColor(Color.DARKGREY); greyMaterial.setSpecularColor(Color.GREY); Box red = new Box(400, 400, 400); red.setMaterial(redMaterial); Sphere blue = new Sphere(200); blue.setMaterial(blueMaterial); Cylinder grey = new Cylinder(5, 100); grey.setMaterial(greyMaterial); hbox.getChildren().addAll(red,blue,grey); return hbox; } 22 Image @Override public void start(Stage primaryStage) { // Create Image and ImageView objects Image image = new Image("file:resources/images/javafxdocumentation.png"); ImageView imageView = new ImageView(); imageView.setImage(image); // Display image on screen StackPane root = new StackPane(); root.getChildren().add(imageView); Scene scene = new Scene(root, 300, 250); primaryStage.setTitle("Image Read Test"); primaryStage.setScene(scene); primaryStage.show(); } 24 Canvas @Override public void start(Stage primaryStage) { primaryStage.setTitle("Drawing Operations Test"); Group root = new Group(); Canvas canvas = new Canvas(300, 250); GraphicsContext gc = canvas.getGraphicsContext2D(); drawShapes(gc); root.getChildren().add(canvas); primaryStage.setScene(new Scene(root)); primaryStage.show(); } private void drawShapes(GraphicsContext gc) { gc.setFill(Color.GREEN); gc.setStroke(Color.BLUE); gc.setLineWidth(5); gc.strokeLine(40, 10, 10, 40); gc.fillOval(10, 60, 30, 30); gc.strokeOval(60, 60, 30, 30); gc.fillRoundRect(110, 60, 30, 30, 10, 10); gc.strokeRoundRect(160, 60, 30, 30, 10, 10); gc.fillArc(10, 110, 30, 30, 45, 240, ArcType.OPEN); gc.fillArc(60, 110, 30, 30, 45, 240, ArcType.CHORD); gc.fillArc(110, 110, 30, 30, 45, 240, ArcType.ROUND); gc.strokeArc(10, 160, 30, 30, 45, 240, ArcType.OPEN); gc.strokeArc(60, 160, 30, 30, 45, 240, ArcType.CHORD); gc.strokeArc(110, 160, 30, 30, 45, 240, ArcType.ROUND); gc.fillPolygon(new double[]{10, 40, 10, 40}, new double[]{210, 210, 240, 240}, 4); gc.strokePolygon(new double[]{60, 90, 60, 90}, new double[]{210, 210, 240, 240}, 4); gc.strokePolyline(new double[]{110, 140, 110, 140}, new double[]{210, 210, 240, 240}, 4); } 25 技術簡介 Graphics User Interface Component 26 1.LAYOUT 27 設定Root Layout Load View 取得Controller 28 Border Pane 29 AnchorPane 30 Split Pane 31 2.UI CONTROLS 32 Label 33 Button 1/2 @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); GridPane gridpane = new GridPane(); gridpane.setAlignment(Pos.CENTER); gridpane.setHgap(5); gridpane.setVgap(5); //Label Label Label = new Label("My Label"); gridpane.add(Label, 0, 0); //Button Button button1 = new Button(); gridpane.add(button1, 0, 1); Image imageDecline = new Image("file:resources/images/decline-button.png"); Button button3 = new Button("Decline", new ImageView(imageDecline)); gridpane.add(button3, 2, 1); Image imageAccept = new Image(getClass().getResourceAsStream("accept-button.png")); Button button4 = new Button("", new ImageView(imageAccept)); gridpane.add(button4, 3, 1); primaryStage.setScene(new Scene(gridpane)); primaryStage.show(); } Button button2 = new Button("Accept"); gridpane.add(button2, 1, 1); 34 Button 2/2 35 RadioButton @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); FlowPane flowpane = new FlowPane(); //RadioButton ToggleGroup group = new ToggleGroup(); RadioButton rb1 = new RadioButton("Home"); rb1.setToggleGroup(group); rb1.setSelected(true); RadioButton rb2 = new RadioButton("Calendar"); rb2.setToggleGroup(group); RadioButton rb3 = new RadioButton("Contacts"); rb3.setToggleGroup(group); flowpane.getChildren().addAll(rb1,rb2,rb3); primaryStage.setScene(new Scene(flowpane)); primaryStage.setWidth(300); primaryStage.setHeight(300); primaryStage.show(); } 36 ToggleButton @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); FlowPane flowpane = new FlowPane(); //ToggleButton final ToggleGroup group = new ToggleGroup(); ToggleButton tb1 = new ToggleButton("Minor"); tb1.setToggleGroup(group); tb1.setSelected(true); ToggleButton tb2 = new ToggleButton("Major"); tb2.setToggleGroup(group); rect.setStrokeWidth(2); rect.setArcHeight(10); rect.setArcWidth(10); //ChangeListener實作void changed(ObservableValue<? extends T> observable,T oldValue,T newValue) group.selectedToggleProperty().addListener( (ObservableValue<? extends Toggle> ov, Toggle toggle, Toggle new_toggle) -> { if (new_toggle == null) rect.setFill(Color.WHITE); else rect.setFill((Color) group.getSelectedToggle().getUserData()); }); ToggleButton tb3 = new ToggleButton("Critical"); tb3.setToggleGroup(group); flowpane.getChildren().addAll(tb1,tb2,tb3,rect); tb1.setUserData(Color.LIGHTGREEN); tb2.setUserData(Color.LIGHTBLUE); tb3.setUserData(Color.SALMON); rect.setWidth(280); rect.setHeight(230); group.selectToggle(tb2); Rectangle rect = new Rectangle(); rect.setHeight(50); rect.setFill(Color.WHITE); rect.setStroke(Color.DARKGRAY); primaryStage.setScene(new Scene(flowpane)); primaryStage.setWidth(300); primaryStage.setHeight(300); primaryStage.show(); } 37 Checkbox @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); FlowPane flowpane = new FlowPane(); //CheckBox final String[] names = new String[]{"Security", "Project", "Chart"}; final CheckBox[] cbs = new CheckBox[names.length]; for (int i = 0; i < names.length; i++) { final CheckBox cb = cbs[i] = new CheckBox(names[i]); cb.setSelected((i==0)? true : false); flowpane.getChildren().add(cb); } primaryStage.setScene(new Scene(flowpane)); primaryStage.setWidth(300); primaryStage.setHeight(300); primaryStage.show(); } 38 ChoiceBox @SuppressWarnings("unchecked") @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); FlowPane flowpane = new FlowPane(); //ChoiceBox @SuppressWarnings("rawtypes") ChoiceBox cb = new ChoiceBox(); cb.setItems(FXCollections.observableArrayList( "New Document", "Open ", new Separator(), "Save", "Save as") ); cb.getSelectionModel().selectFirst(); flowpane.getChildren().addAll(cb); primaryStage.setScene(new Scene(flowpane)); primaryStage.setWidth(300); primaryStage.setHeight(300); primaryStage.show(); } 39 TextField & PasswordField 1/2 @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); FlowPane flowpane = new FlowPane(); primaryStage.setScene(new Scene(flowpane)); primaryStage.setWidth(300); primaryStage.setHeight(300); primaryStage.show(); } //TextField Label label1 = new Label("Name:"); TextField textField = new TextField (); Button clearButton = new Button("Clear"); clearButton.setOnAction((ActionEvent e) -> { textField.clear(); }); //PasswordField PasswordField passwordField = new PasswordField(); passwordField.setPromptText("Your password:"); flowpane.getChildren().addAll(label1, textField, clearButton, passwordField); 40 TextField & PasswordField 2/2 41 ScrollBar @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); FlowPane flowpane = new FlowPane(); //ScrollBar ScrollBar sc = new ScrollBar(); sc.setMin(0); sc.setOrientation(Orientation.VERTICAL); sc.setPrefHeight(360); sc.setMax(360); flowpane.getChildren().addAll(sc); primaryStage.setScene(new Scene(flowpane)); primaryStage.setWidth(360); primaryStage.setHeight(400); primaryStage.show(); } 42 ScrollPane public class Main_UIControl8 extends Application { final ScrollPane sp = new ScrollPane(); final Image[] images = new Image[5]; final ImageView[] pics = new ImageView[5]; final VBox vb = new VBox(); final Label fileName = new Label(); final String [] imageNames = new String [] {"fw1.png", "fw2.png","fw3.png", "fw4.png", "fw5.png"}; @Override public void start(Stage primaryStage) { VBox box = new VBox(); Scene scene = new Scene(box, 180, 180); primaryStage.setScene(scene); primaryStage.setTitle("Scroll Pane"); box.getChildren().addAll(sp, fileName); VBox.setVgrow(sp, Priority.ALWAYS); fileName.setLayoutX(30); fileName.setLayoutY(160); for (int i = 0; i < 5; i++) { //images[i] = new Image(getClass().getResourceAsStream(imageNames[i])); images[i] = new Image("file:resources/images/" + imageNames[i]); pics[i] = new ImageView(images[i]); pics[i].setFitWidth(100); pics[i].setPreserveRatio(true); vb.getChildren().add(pics[i]); } sp.setVmax(440); sp.setPrefSize(115, 150); sp.setContent(vb); sp.vvalueProperty().addListener((ov, old_val, new_val) -> { fileName.setText(imageNames[(new_val.intValue() 1)/100]); }); primaryStage.show(); } 43 ListView @Override public void start(Stage primaryStage) { primaryStage.setTitle("UI Control"); FlowPane flowpane = new FlowPane(); //ListView ListView<String> list = new ListView<>(); ObservableList<String> items =FXCollections.observableArrayList ( "Single", "Double", "Suite", "Family App"); list.setItems(items); flowpane.getChildren().addAll(list); primaryStage.setScene(new Scene(flowpane)); primaryStage.setWidth(360); primaryStage.setHeight(400); primaryStage.show(); } 44 Table View 1/2 45 Table View 2/2 46 Table Column 1/3 47 Table Column 2/3 • Column Mapping Model Notify View 48 Table Column 3/3 • Data初始及重新查詢 49 TreeView List<Employee> employees = Arrays.<Employee>asList( new Employee("Jacob Smith", "Accounts Department"),…); TreeItem<String> rootNode = new TreeItem<>("MyCompany Human Resources", rootIcon); … public void start(Stage stage) { rootNode.setExpanded(true); for (Employee employee : employees) { TreeItem<String> empLeaf = new TreeItem<>(employee.getName()); boolean found = false; for (TreeItem<String> depNode : rootNode.getChildren()) { if (depNode.getValue().contentEquals(employee.getDepartment())){ depNode.getChildren().add(empLeaf); found = true; break; } } if (!found) { @SuppressWarnings("rawtypes") TreeItem depNode = new TreeItem(employee.getDepartment(), new ImageView(depIcon) ); rootNode.getChildren().add(depNode); depNode.getChildren().add(empLeaf); } } stage.setTitle("Tree View Sample"); VBox box = new VBox(); final Scene scene = new Scene(box, 400, 300); scene.setFill(Color.LIGHTGRAY); TreeView<String> treeView = new TreeView<>(rootNode); treeView.setEditable(true); treeView.setCellFactory((TreeView<String> p) -> new TextFieldTreeCellImpl()); box.getChildren().add(treeView); stage.setScene(scene); stage.show(); } 50 TreeTableView List<Employee> employees = Arrays.<Employee>asList( new Employee("Ethan Williams", "ethan.williams@example.com"),…)); private final ImageView depIcon = new ImageView ( new Image(getClass().getResourceAsStream("department.jpg"),30,30,false,fals e) ); final TreeItem<Employee> root = new TreeItem<>(new Employee("Sales Department", ""), depIcon); public static void main(String[] args) { Application.launch(TreeTableViewSample.class, args); } … public void start(Stage stage) { root.setExpanded(true); employees.stream().forEach((employee) -> { root.getChildren().add(new TreeItem<>(employee)); }); stage.setTitle("Tree Table View Sample"); final Scene scene = new Scene(new Group(), 400, 400); scene.setFill(Color.LIGHTGRAY); Group sceneRoot = (Group) scene.getRoot(); TreeTableColumn<Employee, String> empColumn = new TreeTableColumn<>("Employee"); empColumn.setPrefWidth(150); empColumn.setCellValueFactory( (TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(param.getValue().getValue().getName()) ); TreeTableColumn<Employee, String> emailColumn = new TreeTableColumn<>("Email"); emailColumn.setPrefWidth(190); emailColumn.setCellValueFactory( (TreeTableColumn.CellDataFeatures<Employee, String> param) -> new ReadOnlyStringWrapper(param.getValue().getValue().getEmail()) ); TreeTableView<Employee> treeTableView = new TreeTableView<>(root); treeTableView.getColumns().setAll(empColumn, emailColumn); sceneRoot.getChildren().add(treeTableView); stage.setScene(scene); stage.show(); } 51 ComboBox 1/2 52 ComboBox 2/2 • 初始值、各選項顯示、選取之顯示 53 Separator @Override public void start(Stage stage) { Group root = new Group(); Scene scene = new Scene(root,1000, 300); stage.setScene(scene); stage.setTitle("Separator Sample"); friday.setFont(Font.font("Verdana", 18)); GridPane.setConstraints(friday, 0, 2); GridPane.setColumnSpan(friday, 2); grid.getChildren().add(friday); final Separator sepVert1 = new Separator(); sepVert1.setOrientation(Orientation.VERTICAL); sepVert1.setValignment(VPos.CENTER); sepVert1.setPrefHeight(80); GridPane.setConstraints(sepVert1, 2, 2); GridPane.setRowSpan(sepVert1, 2); GridPane grid = new GridPane(); grid.setPadding(new Insets(10, 10, 10, 10)); grid.setVgap(2); grid.setHgap(5); grid.getChildren().add(sepVert1); scene.setRoot(grid); saturday.setFont(Font.font("Verdana", 18)); GridPane.setConstraints(saturday, 3, 2); GridPane.setColumnSpan(saturday, 2); grid.getChildren().add(saturday); Image cloudImage = new Image(getClass().getResourceAsStream("cloud.png")); Image sunImage = new Image(getClass().getResourceAsStream("sun.jpg")); caption.setFont(Font.font("Verdana", 20)); GridPane.setConstraints(caption, 0, 0); GridPane.setColumnSpan(caption, 8); grid.getChildren().add(caption); … stage.show(); } 在GridPane的第2欄第2列, span2列(垂直)繪一直線 final Separator sepHor = new Separator(); sepHor.setValignment(VPos.CENTER); GridPane.setConstraints(sepHor, 0, 1); GridPane.setColumnSpan(sepHor, 7); grid.getChildren().add(sepHor); 在GridPane的第0欄第1列, span7欄(平行)繪一直線 54 Slider final Slider opacityLevel = new Slider(0, 1, 1); final Slider sepiaTone = new Slider(0, 1, 1); final Slider scaling = new Slider (0.5, 1, 1); … scaling.valueProperty().addListener(( ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> { cappuccino.setScaleX(new_val.doubleValue()); cappuccino.setScaleY(new_val.doubleValue()); scalingValue.setText(String.format("%.2f", new_val)); }); GridPane.setConstraints(scaling, 1, 3); grid.getChildren().add(scaling); … 最小值,最大值,預設值 @Override public void start(Stage stage) { … opacityLevel.valueProperty().addListener(( ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> { cappuccino.setOpacity(new_val.doubleValue()); opacityValue.setText(String.format("%.2f", new_val)); }); scalingValue.setTextFill(textColor); GridPane.setConstraints(scalingValue, 2, 3); grid.getChildren().add(scalingValue); GridPane.setConstraints(opacityLevel, 1, 1); grid.getChildren().add(opacityLevel); … sepiaTone.valueProperty().addListener(( ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> { sepiaEffect.setLevel(new_val.doubleValue()); sepiaValue.setText(String.format("%.2f", new_val)); }); GridPane.setConstraints(sepiaTone, 1, 2); grid.getChildren().add(sepiaTone); stage.show(); } 55 Progress Bar and Progress Indicator @Override public void start(Stage stage) { Group root = new Group(); Scene scene = new Scene(root); stage.setScene(scene); stage.setTitle("Progress Controls"); final Slider slider = new Slider(); slider.setMin(0); slider.setMax(50); final ProgressBar pb = new ProgressBar(0); final ProgressIndicator pi = new ProgressIndicator(0); slider.valueProperty().addListener( (ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> { pb.setProgress(new_val.doubleValue()/50); pi.setProgress(new_val.doubleValue()/50); }); final HBox hb = new HBox(); hb.setSpacing(5); hb.setAlignment(Pos.CENTER); hb.getChildren().addAll(slider, pb, pi); scene.setRoot(hb); stage.show(); } 56 Hyperlink final static String[] imageFiles = new String[]{"feib.png"}; final static String[] captions = new String[]{"Feib"}; final static String[] urls = new String[]{"http://www.feib.com.tw/"}; … @Override public void start(Stage stage) { VBox vbox = new VBox(); Scene scene = new Scene(vbox); stage.setTitle("Hyperlink Sample"); stage.setWidth(800); stage.setHeight(600); for (int i = 0; i < captions.length; i++) { final Hyperlink hpl = hpls[i] = new Hyperlink(captions[i]); final Image image = images[i] = new Image(getClass().getResourceAsStream(imageFiles[i]),60,60,false,false); hpl.setGraphic(new ImageView (image)); hpl.setFont(Font.font("Arial", 14)); final String url = urls[i]; hpl.setOnAction((ActionEvent e) -> { webEngine.load(url); }); selectedImage.setLayoutX(100); selectedImage.setLayoutY(10); } final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); HBox hbox = new HBox(); hbox.setAlignment(Pos.BASELINE_CENTER); hbox.getChildren().addAll(hpls); vbox.getChildren().addAll(hbox, browser); Vbox.setVgrow(browser, Priority.ALWAYS); stage.setScene(scene); stage.show(); } 57 Tooltip @Override public void start(Stage stage) { … for (int i = 0; i < rooms.length; i++) { final CheckBox cb = cbs[i] = new CheckBox(rooms[i]); final Integer rate = rates[i]; final Tooltip tooltip = new Tooltip("$" + rates[i].toString()); tooltip.setFont(new Font("Arial", 16)); cb.setTooltip(tooltip); cb.selectedProperty().addListener( (ObservableValue<? extends Boolean> ov, Boolean old_val, Boolean new_val) -> { if (cb.isSelected()) { sum = sum + rate; } else { sum = sum - rate; } total.setText("Total: $" + sum.toString()); } ); } … } 58 HTML Editor @Override public void start(Stage stage) { stage.setTitle("HTMLEditor Sample"); stage.setWidth(650); stage.setHeight(500); Scene scene = new Scene(new Group()); Button showHTMLButton = new Button("Load Content in Browser"); root.setAlignment(Pos.CENTER); showHTMLButton.setOnAction((ActionEvent arg0) -> { webEngine.loadContent(htmlEditor.getHtmlText()); }); VBox root = new VBox(); root.setPadding(new Insets(8, 8, 8, 8)); root.setSpacing(5); root.setAlignment(Pos.BOTTOM_LEFT); root.getChildren().addAll(htmlEditor, showHTMLButton, scrollPane); scene.setRoot(root); final HTMLEditor htmlEditor = new HTMLEditor(); htmlEditor.setPrefHeight(245); htmlEditor.setHtmlText(INITIAL_TEXT); stage.setScene(scene); stage.show(); } final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); ScrollPane scrollPane = new ScrollPane(); scrollPane.getStyleClass().add("noborder-scroll-pane"); scrollPane.setStyle("-fx-background-color: white"); scrollPane.setContent(browser); scrollPane.setFitToWidth(true); scrollPane.setPrefHeight(180); 59 Titled Pane and Accordion 手風琴 final Accordion accordion = new Accordion (); for (int i = 0; i < imageNames.length; i++) { images[i] = new Image(getClass().getResourceAsStream(imageNames[i] + ".png")); pics[i] = new ImageView(images[i]); tps[i] = new TitledPane(imageNames[i],pics[i]); } accordion.getPanes().addAll(tps); accordion.expandedPaneProperty().addListener( (ObservableValue<? extends TitledPane> ov, TitledPane old_val, TitledPane new_val) -> { if (new_val != null) { label.setText(accordion.getExpandedPane().getText() + ".jpg"); } }); 60 Menu Bar 1/2 61 Menu Bar 2/2 62 Color Picker @Override public void start(Stage stage) { stage.setTitle("ColorPicker"); Scene scene = new Scene(new HBox(20), 400, 100); HBox box = (HBox) scene.getRoot(); box.setPadding(new Insets(5, 5, 5, 5)); final ColorPicker colorPicker = new ColorPicker(); colorPicker.setValue(Color.CORAL); final Text text = new Text("Try the color picker!"); text.setFont(Font.font ("Verdana", 20)); text.setFill(colorPicker.getValue()); colorPicker.setOnAction((ActionEvent t) -> { text.setFill(colorPicker.getValue()); }); box.getChildren().addAll(colorPicker, text); stage.setScene(scene); stage.show(); } 63 Date Picker private Stage stage; private DatePicker checkInDatePicker; … @Override public void start(Stage stage) { this.stage = stage; stage.setTitle("DatePickerSample "); initUI(); stage.show(); } private void initUI() { VBox vbox = new VBox(20); vbox.setStyle("-fx-padding: 10;"); Scene scene = new Scene(vbox, 400, 400); stage.setScene(scene); checkInDatePicker = new DatePicker(); GridPane gridPane = new GridPane(); gridPane.setHgap(10); gridPane.setVgap(10); Label checkInlabel = new Label("Check-In Date:"); gridPane.add(checkInlabel, 0, 0); GridPane.setHalignment(checkInlabel, HPos.LEFT); gridPane.add(checkInDatePicker, 0, 1); vbox.getChildren().add(gridPane); } 64 Pagination Control @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((Integer pageIndex) -> createPage(pageIndex)); 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; } 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("file:resources/Pagination.css"); stage.show(); } public int itemsPerPage() { return 15; } 65 File Chooser final FileChooser fileChooser = new FileChooser(); final Button openButton = new Button("Open a Picture..."); final Button openMultipleButton = new Button("Open Pictures..."); openButton.setOnAction( (final ActionEvent e) -> { File file = fileChooser.showOpenDialog(stage); if (file != null) { //openFile(file); } }); openMultipleButton.setOnAction( (final ActionEvent e) -> { List<File> list = fileChooser.showOpenMultipleDialog(stage); if (list != null) { list.stream().forEach((file) -> { //openFile(file); }); } }); 66 Dialog 67 Pie Chart Line Chart Area Chart Bubble Chart Scatter Chart Bar Chart 3.CHARTS 68 Pie Chart @Override public void start(Stage stage) { Scene scene = new Scene(new Group()); stage.setTitle("Imported Fruits"); stage.setWidth(500); stage.setHeight(500); ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList( new PieChart.Data("Grapefruit", 13), new PieChart.Data("Oranges", 25), new PieChart.Data("Plums", 10), new PieChart.Data("Pears", 22), new PieChart.Data("Apples", 30)); final PieChart chart = new PieChart(pieChartData); chart.setTitle("Imported Fruits"); ((Group) scene.getRoot()).getChildren().add(chart); stage.setScene(scene); stage.show(); } 69 Line Chart //defining the axes final NumberAxis xAxis = new NumberAxis(); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("Number of Month"); //creating the chart final LineChart<Number,Number> lineChart = new LineChart<Number,Number>(xAxis,yAxis); lineChart.setTitle("Stock Monitoring, 2010"); //defining a series XYChart.Series series = new XYChart.Series(); series.setName("My portfolio"); //populating the series with data series.getData().add(new XYChart.Data(1, 23)); series.getData().add(new XYChart.Data(2, 14)); … Scene scene = new Scene(lineChart,800,600); lineChart.getData().add(series); 70 Area Chart C)"); final NumberAxis xAxis = new NumberAxis(1, 31, 1); final NumberAxis yAxis = new NumberAxis(); final AreaChart<Number,Number> ac = new AreaChart<>(xAxis,yAxis); ac.setTitle("Temperature Monitoring (in Degrees XYChart.Series seriesApril= new XYChart.Series(); seriesApril.setName("April"); seriesApril.getData().add(new XYChart.Data(1, 4)); seriesApril.getData().add(new XYChart.Data(3, 10)); … XYChart.Series seriesMay = new XYChart.Series(); seriesMay.setName("May"); seriesMay.getData().add(new XYChart.Data(1, 20)); seriesMay.getData().add(new XYChart.Data(3, 15)); … Scene scene = new Scene(ac,800,600); ac.getData().addAll(seriesApril, seriesMay); 71 Bubble Chart final NumberAxis xAxis = new NumberAxis(1, 53, 4); final NumberAxis yAxis = new NumberAxis(0, 80, 10); final BubbleChart<Number,Number> blc = new BubbleChart<>(xAxis,yAxis); xAxis.setLabel("Week"); yAxis.setLabel("Product Budget"); blc.setTitle("Budget Monitoring"); XYChart.Series series1 = new XYChart.Series(); series1.setName("Product 1"); series1.getData().add(new XYChart.Data(3, 35)); …. XYChart.Series series2 = new XYChart.Series(); series2.setName("Product 2"); series2.getData().add(new XYChart.Data(8, 15)); … Scene scene = new Scene(blc); blc.getData().addAll(series1, series2); 72 Scatter Chart final NumberAxis xAxis = new NumberAxis(0, 10, 1); final NumberAxis yAxis = new NumberAxis(-100, 500, 100); final ScatterChart<Number,Number> sc = new ScatterChart<>(xAxis,yAxis); xAxis.setLabel("Age (years)"); yAxis.setLabel("Returns to date"); sc.setTitle("Investment Overview"); XYChart.Series series1 = new XYChart.Series(); series1.setName("Option 1"); series1.getData().add(new XYChart.Data(4.2, 193.2)); series1.getData().add(new XYChart.Data(2.8, 33.6)); … sc.setPrefSize(500, 400); sc.getData().addAll(series1); final Button add = new Button("Add Series"); final Button remove = new Button("Remove Series"); add.setOnAction((ActionEvent e) -> { if (sc.getData() == null) { sc.setData(FXCollections.<XYChart.Series<Number, Number>>observableArrayList()); } ScatterChart.Series<Number, Number> series = new ScatterChart.Series<>(); series.setName("Option " + (sc.getData().size() + 1)); for (int i = 0; i < 100; i++) { series.getData().add( new ScatterChart.Data<>(Math.random() * 100, Math.random() * 500)); } sc.getData().add(series); }); remove.setOnAction((ActionEvent e) -> { if (!sc.getData().isEmpty()) sc.getData().remove((int)( Math.random()*(sc.getData().size()-1))); }); 73 Bar Chart final static String austria = "Austria"; final static String brazil = "Brazil"; final static String france = "France"; final static String italy = "Italy"; final static String usa = "USA"; … final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); final BarChart<String,Number> bc = new BarChart<>(xAxis,yAxis); bc.setTitle("Country Summary"); xAxis.setLabel("Country"); yAxis.setLabel("Value"); XYChart.Series series1 = new XYChart.Series(); series1.setName("2003"); series1.getData().add(new XYChart.Data(austria, 25601.34)); series1.getData().add(new XYChart.Data(brazil, 20148.82)); series1.getData().add(new XYChart.Data(france, 10000)); series1.getData().add(new XYChart.Data(italy, 35407.15)); series1.getData().add(new XYChart.Data(usa, 12000)); XYChart.Series series2 = new XYChart.Series(); series2.setName("2004"); … XYChart.Series series3 = new XYChart.Series(); series3.setName("2005"); … Scene scene = new Scene(bc,800,600); bc.getData().addAll(series1, series2, series3); 74 4.HANDLE EVENT 75 Event Type Hierarchy 76 Event Dispatch Chain 77 Event Sample Mouse Event Keyboard Event 78 Event Filter Register Event Filter Remove Event Filter // Register an event filter for a single node and a specific event type node.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { public void handle(MouseEvent) { ... }; }); // Remove an event filter myNode1.removeEventFilter(MouseEvent.MOUSE_PRESSED, filter); // Define an event filter EventHandler filter = new EventHandler(<InputEvent>() { public void handle(InputEvent event) { System.out.println("Filtering out event " + event.getEventType()); event.consume(); } // Register the same filter for two different nodes myNode1.addEventFilter(MouseEvent.MOUSE_PRESSED, filter); myNode2.addEventFilter(MouseEvent.MOUSE_PRESSED, filter); // Register the filter for another event type myNode1.addEventFilter(KeyEvent.KEY_PRESSED, filter); 79 Event Handler Register Event Handler Remove Event Handler // Register an event handler for a single node and a specific event type node.addEventHandler(DragEvent.DRAG_ENTERED, new EventHandler<DragEvent>() { public void handle(DragEvent) { ... }; }); // Remove an event handler myNode1.removeEventHandler(DragEvent.DRAG_EXITED, handler); // Define an event handler EventHandler handler = new EventHandler(<InputEvent>() { public void handle(InputEvent event) { System.out.println("Handling event " + event.getEventType()); event.consume(); } // Register the same handler for two different nodes myNode1.addEventHandler(DragEvent.DRAG_EXITED, handler); myNode2.addEventHandler(DragEvent.DRAG_EXITED, handler); // Register the handler for another event type myNode1.addEventHandler(MouseEvent.MOUSE_DRAGGED, handler); 80 Gesture & Touch Events 旋轉 滾動 刷 放大 81 Java Fx 簡介、架構 開發工具 技術簡介 佈署 82 產生安裝檔 1/2 83 產生安裝檔 2/2 84 Deploy至tomcat 1/2 85 Deploy至tomcat 2/2 86 Window : 編譯成exe檔 • build.fxbuild 的 Packaging Format : 選取為exe 91 Window : 編譯成安裝檔(exe) • build.fxbuild 的 Packaging Format : 選取為exe – 需安裝 Inno Setup • http://www.jrsoftware.org/isdl.php 92 Window : 編譯成安裝檔(msi) • build.fxbuild 的 Packaging Format : 選取為msi – 需安裝Wix • https://wix.codeplex.com/releases/view/115492 93 Android 編譯成apk檔 • eclipse安裝 – Eclipse執行 • http://dist.springsource.com/release/TOOLS/gradle – Command line執行 : dalvik-sdk • https://blogs.oracle.com/jfxprg/entry/how_to_build_o pen_javafx 94 iOS : 編譯成dmg檔 • build.fxbuild 的 Packaging Format : 選取為 dmg – 無環境可驗證 95 JSON 96 JSON JSON基本格式 Java應用JSON ExtJS套件應用JSON JQuery應用JSON Chrome App應用JSON 97 JSON基本格式 1/2 • JSON Object – 以 { 開始,以 } 結尾 – 每個名稱後跟著一個 : 號 – 每對”名稱 : 值”之間用 , 號分隔 • JSON Array – 以 [ 開始,以 ] 結尾 – 值之間用 , 號 分隔 98 JSON基本格式 2/2 • JSON Value – 值可為String、Number、true、false、null、 Object、Array • JSON String – 由雙引號包圍的任意Unicode字元集合 – 可使用反斜線 \ 來轉義 • JSON Number – 與一般數值相同 99 JSON JSON基本格式 Java應用JSON ExtJS套件應用JSON JQuery應用JSON Chrome App應用JSON 100 Java處理JSON套件 • 以javax.json (javax.json-1.0.jar)為例 101 Java產生JSON字串 102 Java處理JSON字串 103 JSON JSON基本格式 Java應用JSON ExtJS套件應用JSON JQuery應用JSON Chrome App應用JSON 104 ExtJS套件 • http://www.sencha.com/products/extjs/ 105 ExtJS套件應用JSON 1/3 106 ExtJS套件應用JSON 2/3 107 ExtJS套件應用JSON 3/3 108 JSON JSON基本格式 Java應用JSON ExtJS套件應用JSON JQuery應用JSON Chrome App應用JSON 109 JQuery應用SON 110 JSON JSON基本格式 Java應用JSON ExtJS套件應用JSON JQuery應用JSON Chrome App應用JSON 111 Chrome App設定檔 : manifest.json 112 Chrome App啟動Demo 113 Chrome App : JSON Editor 114 SQLITE 115 SQLite JavaFX上存取SQLite Android App上存取 SQLite 116 JavaFX上存取SQLite 1/3 • 記錄本機登入成功資料 117 JavaFX上存取SQLite 2/3 • 登入記錄 118 JavaFX上存取SQLite 3/3 • 列出訊息 119 附件 JavaFX上存取SQLite Android App上存取 SQLite 120 Android App上存取SQLite 1/2 121 Android App上存取SQLite 2/2 122 Thank You ! 123