提示框
package sample; import javafx.application.Application; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class demo1 extends Application{ @Override public void start(Stage primaryStage) throws Exception { BorderPane root = new BorderPane(); Button b1 = new Button("点我"); b1.setOnMouseClicked(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { Alert alert = new Alert(Alert.AlertType.WARNING); alert.setHeaderText("弹窗"); alert.setContentText("你好呀"); alert.show(); } }); root.setCenter(b1); primaryStage.setTitle("鼠标操作"); primaryStage.setScene(new Scene(root,500,50)); primaryStage.show(); } }
登录案例
package sample; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.PasswordField; import javafx.scene.control.TextField; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.sql.*; public class DemoAlert extends Application { @Override public void start(Stage primaryStage) throws Exception { // 文本框和密码框 TextField user = new TextField(); PasswordField pwd = new PasswordField(); Button login = new Button("登录"); // 创建布局 BorderPane root = new BorderPane(); VBox vBox = new VBox(); vBox.getChildren().addAll(user,pwd,login); // 容器边距 vBox.setSpacing(10); // 子父容器间距 vBox.setPadding(new Insets(80)); root.setCenter(vBox); login.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { String username = user.getText(); String pass = pwd.getText(); Alert warn = new Alert(Alert.AlertType.WARNING); // 获取当前数据库链接 try { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql:///db4", "root", "root"); Statement stmt = conn.createStatement(); String sql = "select * from user where username ='"+username+"' and passwd = '"+pass+"' "; System.out.println(sql); ResultSet rs = stmt.executeQuery(sql); if (rs.next()){ warn.setHeaderText("正在登录 请稍等"); warn.setContentText("登录成功"); warn.show(); } else { warn.setHeaderText("正在查询 请稍等"); warn.setContentText("账号或密码错误,禁止登陆"); warn.show(); } stmt.close(); conn.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }); primaryStage.setTitle("提示框"); primaryStage.setScene(new Scene(root,400,300)); primaryStage.show(); }
仔细观察上面代码 sql哪里 没做过滤和判断 所以存在sql注入漏洞
如下
自定义对话框
Dialog:用于显示一个自定义的对话框 Dialog --> DialogPane --> (node + button) Dialog 里要设置一个DialogPane Dialog.setDialogPane() DialogPane里要设置根节点和按钮 DialogPane.setContent() DialogPane.getButtonTypes().add() package sample.Dailog; public class Student { public int id = 0; public String name; public String phone; public Student(){} public Student(int id, String name, String phone) { this.id = id; this.name = name; this.phone = phone; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } } package sample.Dailog; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableCell; import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableView; import javafx.util.Callback; import java.util.List; public class StudentPane extends TreeTableView<Student> { // 根节点 TreeItem rootItem = new TreeItem(new Student()); // 设置3列 TreeTableColumn<Student, Student> columns[] = new TreeTableColumn[3]; public StudentPane(){ // 初始化设置 initColumns(); // 扁平化显示 不显示根节点 setRoot( rootItem); setShowRoot(false); } // 清空 public void clear(){ rootItem.getChildren().clear(); } // 添加 public void add(List<Student> datalist){ for (Student fi : datalist) { TreeItem item = new TreeItem(fi); rootItem.getChildren().add(item); } } public void add(Student data) { TreeItem item = new TreeItem(data); rootItem.getChildren().add(item); } @Override protected void layoutChildren() { super.layoutChildren(); // 动态设置列宽 double w = this.getWidth(); double w0 = w * 0.3; double w1 = w * 0.4; double w2 = w - w0 - w1- 20; columns[0].setPrefWidth(w0); columns[1].setPrefWidth(w1); columns[2].setPrefWidth(w2); } private void initColumns() { // 添加多个列 columns[0] = new TreeTableColumn("学号"); columns[1] = new TreeTableColumn("姓名"); columns[2] = new TreeTableColumn("手机号"); this.getColumns().addAll(columns); // 设置 CellValueFactory (此段写法固定) Callback cellValueFactory = new Callback() { @Override public Object call(Object param) { TreeTableColumn.CellDataFeatures p = (TreeTableColumn.CellDataFeatures)param; return p.getValue().valueProperty(); } }; for(int i=0; i<columns.length; i++) { columns[i].setCellValueFactory(cellValueFactory); } // 设置CellFactory,定义每一列的单元格的显示 // 这里使用了lambda表达式,否则写起来太长了! columns[0].setCellFactory((param)->{ return new MyTreeTableCell("c0"); }); columns[1].setCellFactory((param)->{ return new MyTreeTableCell("c1"); }); columns[2].setCellFactory((param)->{ return new MyTreeTableCell("c2"); }); } // 单元格的显示 static class MyTreeTableCell extends TreeTableCell<Student,Student> { String columnID; public MyTreeTableCell(String columnID) { this.columnID = columnID; } @Override protected void updateItem(Student item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); } else { setGraphic(null); if(columnID.equals("c0")) { setText(String.valueOf(item.id)); } else if(columnID.equals("c1")) { setText(String.valueOf(item.name)); } else if(columnID.equals("c2")) { setText(String.valueOf(item.phone)); } } } } } package sample.Dailog; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Button; import javafx.scene.control.Dialog; import javafx.scene.control.DialogPane; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; public class AddStudentDailog extends Dialog<Boolean> { // 添加信息面板 TextField id = new TextField(); TextField name = new TextField(); TextField phone = new TextField(); public AddStudentDailog(){ VBox vBox = new VBox(); id.setPromptText("学号"); name.setPromptText("姓名"); phone.setPromptText("手机号"); // 添加到vbox vBox.getChildren().addAll(id,name,phone); // 创建dialogpane DialogPane dialogPane = new DialogPane(); dialogPane.setContent(vBox); // 创建按钮 Button ok = new Button("确定"); vBox.getChildren().add(ok); ok.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { // 设置结果 关闭对话框 setResult(true); } }); // 创建对话框 setDialogPane(dialogPane); setTitle("添加学生信息"); } private boolean checkValid(){ return true; } public Student getValue(){ Student v = new Student(); v.id = Integer.valueOf( id.getText() ); v.name = name.getText(); v. phone = phone.getText(); return v; } } package sample.Dailog; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; import java.util.Optional; public class Main extends Application{ public StudentPane studentPane; @Override public void start(Stage primaryStage) throws Exception { studentPane =new StudentPane(); BorderPane root = new BorderPane(); root.setCenter(studentPane); primaryStage.setScene(new Scene(root, 500, 400)); primaryStage.setTitle("学生管理系统"); primaryStage.show(); Button add = new Button("添加"); root.setTop(add); add.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { onAdd(); } }); } private void onAdd() { AddStudentDailog dlg = new AddStudentDailog(); Optional<Boolean> result = dlg.showAndWait(); if( result.isPresent() && result.get() == true) { Student s = dlg.getValue(); // getValue()是自己添加的方法 studentPane.add(s); } } }
先设计一个主程序 点击某个按钮 弹出一个小程序用来处理事件
这个就是自定义对话框
案例文本编辑器
package sample.FileChoose; import java.io.*; public class TextUtils { public static String read(File f, String charset) throws IOException { // 文件读取 FileInputStream fis = new FileInputStream(f); int filesize = (int)f.length(); byte[] bytes = new byte[filesize]; fis.read(bytes); fis.close(); return new String(bytes,charset); } // 文件写入 public static void write(File f,String text,String charset) throws IOException { FileOutputStream fos = new FileOutputStream(f); fos.write(text.getBytes( charset)); fos.close(); } } package sample.FileChoose; import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.web.HTMLEditor; import javafx.stage.FileChooser; import javafx.stage.Stage; import java.io.File; import java.io.IOException; public class Main extends Application { // 创建编辑器 HTMLEditor editor = new HTMLEditor(); BorderPane root = new BorderPane(); @Override public void start(Stage primaryStage) throws Exception { Button btnOpen = new Button("打开"); Button btnSave = new Button("保存"); HBox toolbar = new HBox(); toolbar.getChildren().addAll(btnOpen, btnSave); toolbar.setPadding(new Insets(4)); toolbar.setSpacing(4); root.setTop(toolbar); root.setCenter(editor); primaryStage.setTitle("文本编辑"); primaryStage.setScene(new Scene(root, 640, 500)); primaryStage.show(); btnOpen.setOnAction(event -> { // 选择一个文件控制器 FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("打开文件"); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text Files", "*.txt")); // 可以从任意控件 Node 获取到 Window 对象,传给showOpenDialog() // Node.getScene().getWindow() File selectedFile = fileChooser.showOpenDialog(root.getScene().getWindow()); if(selectedFile == null) { return; // 用户没有选中文件, 已经取消操作 } try { String text = TextUtils.read(selectedFile,"GBK"); editor.setHtmlText(text); } catch (IOException e) { e.printStackTrace(); } }); btnSave.setOnAction(event -> { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("保存文件"); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text Files", "*.txt")); // 选择文件 File selectedFile = fileChooser.showSaveDialog(root.getScene().getWindow()); if(selectedFile == null) { return; // 用户没有选中文件, 已经取消操作 } try { // 获取编辑器内容 String text = editor.getHtmlText(); // 写内容 TextUtils.write(selectedFile, text, "GBK"); }catch(Exception e) { e.printStackTrace(); } }); }
菜单栏
package sample.FileChoose; import java.io.*; public class TextUtils { public static String read(File f, String charset) throws IOException { // 文件读取 FileInputStream fis = new FileInputStream(f); int filesize = (int)f.length(); byte[] bytes = new byte[filesize]; fis.read(bytes); fis.close(); return new String(bytes,charset); } // 文件写入 public static void write(File f,String text,String charset) throws IOException { FileOutputStream fos = new FileOutputStream(f); fos.write(text.getBytes( charset)); fos.close(); } } package sample.FileChoose; import javafx.application.Application; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.scene.Scene; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.layout.BorderPane; import javafx.scene.web.HTMLEditor; import javafx.stage.FileChooser; import javafx.stage.Stage; import java.io.File; public class DemoMeme extends Application { Stage primaryStage;// 主窗口 MenuBar menuBar = new MenuBar(); HTMLEditor editor = new HTMLEditor(); @Override public void start(Stage primaryStage) { this.primaryStage = primaryStage; initMenu(); BorderPane root = new BorderPane(); root.setTop(menuBar); root.setCenter(editor); primaryStage.setScene(new Scene(root, 600, 400)); primaryStage.show(); } private void initMenu() { Menu menuFile = new Menu("文件"); Menu menuHelp = new Menu("帮助"); menuBar.getMenus().addAll(menuFile, menuHelp); MenuItem menuItemOpen = new MenuItem("打开"); MenuItem menuItemSave = new MenuItem("保存"); SeparatorMenuItem separator = new SeparatorMenuItem(); MenuItem menuItemExit = new MenuItem("退出程序"); menuFile.getItems().addAll(menuItemOpen, menuItemSave, separator, menuItemExit); // 简写为 lambda 表达式 menuItemOpen.setOnAction((ActionEvent e)->{ onOpen(); }); menuItemSave.setOnAction((ActionEvent e)->{ onSave(); }); menuItemExit.setOnAction((ActionEvent e)->{ Platform.exit(); }); } // 打开一个 *.txt 文件 private void onOpen(){ FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("打开文件"); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text Files", "*.txt")); File selectedFile = fileChooser.showOpenDialog(primaryStage); if(selectedFile == null) return; // 用户没有选中文件, 已经取消操作 try { String text = TextUtils.read(selectedFile, "GBK"); editor.setHtmlText(text); }catch(Exception e) { e.printStackTrace(); } } // 保存到文件 private void onSave() { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("保存文件"); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text Files", "*.txt")); File selectedFile = fileChooser.showSaveDialog(primaryStage); if(selectedFile == null) return; // 用户没有选中文件, 已经取消操作 try { String text = editor.getHtmlText(); TextUtils.write(selectedFile, text, "GBK"); }catch(Exception e) { e.printStackTrace(); } } }
上下文菜单
package memu; import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.stage.Stage; import javafx.util.Callback; import javafx.scene.Scene; import javafx.scene.control.ContextMenu; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.MenuItem; import javafx.scene.layout.BorderPane; public class Main extends Application { // 创建ListView,指定数据项类型 ListView<Student> listView = new ListView<Student>(); // 数据源 ObservableList<Student> listData = FXCollections.observableArrayList(); // ListView的上下文菜单 ContextMenu listContextMenu = new ContextMenu(); @Override public void start(Stage primaryStage) { // 准备数据 listData.add(new Student(1, "张三", true)); listData.add(new Student(2, "李四", true)); listData.add(new Student(3, "王五", false)); // 设置数据源 listView.setItems(listData); // 设置单元格生成器 (工厂) listView.setCellFactory(new Callback<ListView<Student>, ListCell<Student>>() { @Override public ListCell<Student> call(ListView<Student> param) { return new MyListCell(); } }); initContextMenu(); BorderPane root = new BorderPane(); root.setCenter(listView); Scene scene = new Scene(root, 400, 400); primaryStage.setScene(scene); primaryStage.show(); } // 初始化上下文菜单 private void initContextMenu() { MenuItem menuItemRemove = new MenuItem("删除"); menuItemRemove.setOnAction((ActionEvent e) -> { removeItem(); }); // 添加菜单项 listContextMenu.getItems().add(menuItemRemove); // 给ListView设置上下文菜单 listView.setContextMenu(listContextMenu); } // 删除当前选中的项 private void removeItem() { int index = listView.getSelectionModel().getSelectedIndex(); if(index >= 0) { listData.remove(index); } } // 负责单元格Cell的显示 static class MyListCell extends ListCell<Student> { @Override public void updateItem(Student item, boolean empty) { // FX框架要求必须先调用 super.updateItem() super.updateItem(item, empty); // 自己的代码 if (item == null) { this.setText(""); // 清空显示 } else { this.setText(item.name); // 显示该项的值 } } } // 数据项 static class Student { public int id; public String name; public boolean sex; public Student() {} public Student(int id, String name, boolean sex){ this.id = id; this.name = name; this.sex = sex; } } }
案例 学生管理系统
package memu; import javafx.scene.control.ButtonType; import javafx.scene.control.Dialog; import javafx.scene.control.DialogEvent; import javafx.scene.control.DialogPane; import javafx.scene.control.TextField; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.ButtonBar.ButtonData; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.layout.VBox; import javafx.util.Callback; // Dialog<Boolean> : showAndWait() 将返回Boolean值 public class AddStudentDialog extends Dialog<Boolean> { TextField id = new TextField(); TextField name = new TextField(); TextField phone = new TextField(); public AddStudentDialog() { // 对话框内容 VBox content = new VBox(); id.setPromptText("学号"); name.setPromptText("姓名"); phone.setPromptText("手机号"); content.setSpacing(10); content.getChildren().addAll(id, name, phone); // Dialog -> DialogPane -> Root Node DialogPane dialogPane = new DialogPane(); dialogPane.setContent(content); // 添加按钮 ButtonType ok = new ButtonType("确定", ButtonData.OK_DONE); dialogPane.getButtonTypes().add(ok); ButtonType cancel = new ButtonType("取消", ButtonData.CANCEL_CLOSE); dialogPane.getButtonTypes().add(cancel); this.setResultConverter(new Callback<ButtonType,Boolean>(){ @Override public Boolean call(ButtonType b) { if(b.getButtonData() == ButtonData.OK_DONE) return true; return false; } }); // 创建对话框 this.setDialogPane(dialogPane); this.setTitle("添加学生信息"); } private boolean checkValid() { int n = 0; try { n = Integer.valueOf( id.getText().trim() ); }catch(Exception e) { } if(n <=0) { Alert warning = new Alert(AlertType.WARNING); warning.setHeaderText(null); warning.setContentText("学号输入错误!请输入整数!"); warning.showAndWait(); return false; } return true; } // 获取用户输入的值 public Student getValue() { try { Student v = new Student(); v.id = Integer.valueOf( id.getText() ); v.name = name.getText(); v. phone = phone.getText(); return v; }catch(Exception e) { e.printStackTrace(); return null; } } } package memu; public class Student { public int id = 0; public String name; public String phone; public Student(){} public Student(int id, String name, String phone) { this.id = id; this.name = name; this.phone = phone; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } } package memu; import java.util.ArrayList; import java.util.List; import javafx.collections.ObservableList; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableCell; import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableView; import javafx.scene.control.TreeTableColumn.CellDataFeatures; import javafx.util.Callback; public class StudentPane extends TreeTableView<Student> { // 根节点 TreeItem rootItem = new TreeItem(new Student()); // 列 TreeTableColumn<Student, Student> columns[] = new TreeTableColumn[3]; public StudentPane() { // 初始化列的设置 initColumns(); // 扁平化显示, 不显示根节点, 但必须要有根节点 this.setRoot(rootItem); this.setShowRoot(false); } // 清空 public void clear() { rootItem.getChildren().clear(); } // 添加 public void add(List<Student> datalist) { for (Student fi : datalist) { TreeItem item = new TreeItem(fi); rootItem.getChildren().add(item); } } public void add(Student data) { TreeItem item = new TreeItem(data); rootItem.getChildren().add(item); } public void remove(int index) { rootItem.getChildren().remove(index); } public List<Student> get() { ArrayList<Student> results = new ArrayList<Student>(); ObservableList<TreeItem<Student>> items = rootItem.getChildren(); for (int i = 0; i < items.size(); i++) { TreeItem<Student> item = items.get(i); Student value = item.getValue(); results.add(value); } return results; } @Override protected void layoutChildren() { super.layoutChildren(); // 动态设置列宽 double w = this.getWidth(); double w0 = w * 0.3; double w1 = w * 0.4; double w2 = w - w0 - w1 - 20; columns[0].setPrefWidth(w0); columns[1].setPrefWidth(w1); columns[2].setPrefWidth(w2); } private void initColumns() { // 添加多个列 columns[0] = new TreeTableColumn("学号"); columns[1] = new TreeTableColumn("姓名"); columns[2] = new TreeTableColumn("手机号"); this.getColumns().addAll(columns); // 重写layoutChildren() 动态调整个列的列宽 // 设置 CellValueFactory (此段写法固定) Callback cellValueFactory = new Callback() { @Override public Object call(Object param) { CellDataFeatures p = (CellDataFeatures) param; return p.getValue().valueProperty(); } }; for (int i = 0; i < columns.length; i++) { columns[i].setCellValueFactory(cellValueFactory); } // 设置CellFactory,定义每一列的单元格的显示 // 这里使用了lambda表达式,否则写起来太长了! columns[0].setCellFactory((param) -> { return new MyTreeTableCell("c0"); }); columns[1].setCellFactory((param) -> { return new MyTreeTableCell("c1"); }); columns[2].setCellFactory((param) -> { return new MyTreeTableCell("c2"); }); } // 单元格的显示 static class MyTreeTableCell extends TreeTableCell<Student, Student> { String columnID; public MyTreeTableCell(String columnID) { this.columnID = columnID; } @Override protected void updateItem(Student item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); } else { setGraphic(null); if (columnID.equals("c0")) { setText(String.valueOf(item.id)); } else if (columnID.equals("c1")) { setText(String.valueOf(item.name)); } else if (columnID.equals("c2")) { setText(String.valueOf(item.phone)); } } } } } package memu; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class TextUtils { public static String read(File f, String charset) throws IOException { // 文件读取 FileInputStream fis = new FileInputStream(f); int filesize = (int)f.length(); byte[] bytes = new byte[filesize]; fis.read(bytes); fis.close(); return new String(bytes,charset); } // 文件写入 public static void write(File f,String text,String charset) throws IOException { FileOutputStream fos = new FileOutputStream(f); fos.write(text.getBytes( charset)); fos.close(); } } package memu; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.json.JSONArray; import org.json.JSONObject; import javafx.application.Application; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.stage.FileChooser.ExtensionFilter; import javafx.scene.Scene; import javafx.scene.control.ContextMenu; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.layout.BorderPane; public class Main extends Application { Stage primaryStage;// 主窗口 MenuBar menuBar = new MenuBar(); StudentPane studentPane = new StudentPane(); // 上下文菜单 ContextMenu contextMenu = new ContextMenu(); @Override public void start(Stage primaryStage) { initMenuBar(); // 初始化菜单栏 initContextMenu(); // 初始化右键菜单 BorderPane root = new BorderPane(); root.setTop(menuBar); root.setCenter(studentPane); primaryStage.setScene(new Scene(root, 400, 400)); primaryStage.show(); } private void initMenuBar() { Menu menuFile = new Menu("文件"); Menu menuHelp = new Menu("帮助"); menuBar.getMenus().addAll(menuFile, menuHelp); MenuItem menuItemOpen = new MenuItem("打开"); MenuItem menuItemSave = new MenuItem("保存"); SeparatorMenuItem separator = new SeparatorMenuItem(); MenuItem menuItemExit = new MenuItem("退出程序"); menuFile.getItems().addAll(menuItemOpen, menuItemSave, separator, menuItemExit); // 简写为 lambda 表达式 menuItemOpen.setOnAction((ActionEvent e)->{ try { onOpen(); } catch (IOException ex) { ex.printStackTrace(); } }); menuItemSave.setOnAction((ActionEvent e)->{ try { onSave(); } catch (IOException ex) { ex.printStackTrace(); } }); menuItemExit.setOnAction((ActionEvent e)->{ Platform.exit(); }); } // 打开一个文件 private void onOpen() throws IOException { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("打开文件"); fileChooser.getExtensionFilters().add(new ExtensionFilter("学生数据文件", "*.data")); File selectedFile = fileChooser.showOpenDialog(primaryStage); if(selectedFile == null) return; // 用户没有选中文件, 已经取消操作 String text = TextUtils.read(selectedFile, "GBK"); JSONArray jarray = new JSONArray(text); List<Student> sss = new ArrayList<Student>(); for(int i = 0;i<jarray.length(); i++) { JSONObject jobj = jarray.getJSONObject(i); Student s = new Student(); s.id = jobj.getInt("id"); s.name = jobj.getString("name"); s.phone = jobj.getString("phone"); sss.add( s ); } studentPane.clear(); studentPane.add(sss); } // 保存到文件 private void onSave() throws IOException { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("保存文件"); fileChooser.getExtensionFilters().add(new ExtensionFilter("学生数据文件", "*.data")); File selectedFile = fileChooser.showSaveDialog(primaryStage); if(selectedFile == null) return; // 用户没有选中文件, 已经取消操作 List<Student> sss = studentPane.get(); JSONArray jarray = new JSONArray(sss); String text = jarray.toString(2); TextUtils.write(selectedFile, text, "GBK"); } // 初始化上下文菜单 private void initContextMenu() { MenuItem menuItemAdd = new MenuItem("添加"); menuItemAdd.setOnAction((ActionEvent e) -> { addItem(); }); MenuItem menuItemRemove = new MenuItem("删除"); menuItemRemove.setOnAction((ActionEvent e) -> { removeItem(); }); // 添加菜单项 contextMenu.getItems().addAll(menuItemAdd, menuItemRemove); // 给ListView设置上下文菜单 studentPane.setContextMenu(contextMenu); } // 点菜单项 '添加' private void addItem() { AddStudentDialog dlg = new AddStudentDialog(); Optional<Boolean> result = dlg.showAndWait(); if( result.isPresent() && result.get() == true) { Student s = dlg.getValue(); // getValue()是自己添加的方法 studentPane.add(s ); } } // 点菜单项 '删除' private void removeItem() { int index = studentPane.getSelectionModel().getSelectedIndex(); if(index >= 0){ studentPane.remove(index); } } }