JavaFX列表示例
这是使用JavaFX构建的示例列表应用程序。 该应用程序是待办事项列表。 此应用程序具有添加,更新和删除列表中项目的功能。 列表数据存储在HSQLDB关系数据库中。 该应用程序使用JDBC(Java数据库连接)API访问数据库。 该应用程序打包为可执行JAR文件。
JavaFX 2.2,Java SE 7和HSQLDB 2.3.2用于构建应用程序。
本文详细介绍了构建应用程序。 本文件内容:
1.安装HSQL数据库
关于HSQLDB
HSQL关系数据库用于存储待办事项数据。 在本节中–获取并安装数据库。
HSQLDB(HyperSQL数据库)是用Java编写的SQL关系数据库软件,可在JVM中运行。 它是一个小型,快速的多线程事务型数据库引擎,具有基于内存和基于磁盘的表,并支持嵌入式和服务器模式。 这包括JDBC驱动程序。
下载资料库
从网站http://hsqldb.org/上的下载链接下载数据库软件。 在这种情况下,将下载HSQLDB版本2.3.2。 下载的文件是一个ZIP文件。 将ZIP文件解压缩到您选择的任何目录中。 将ZIP文件解压缩到文件夹hsqldb-2.3.2\hsqldb
。 这是主(或安装)目录。
这样就完成了安装。 已安装的数据库具有用户文档,JDBC驱动程序,数据库可执行文件和实用程序。 安装目录具有/doc
和/lib
目录(以及其他目录)。
/doc
目录包含用户指南。
/lib
目录具有以下常用的JAR文件:
-
hsqldb.jar
:它具有数据库引擎,JDBC驱动程序和GUI数据库访问工具。 -
sqltool.jar
:这有一个SQL命令行数据库访问工具。
2.创建应用数据库和表
创建待办事项数据库
GUI数据库访问工具用于创建和访问数据库。 从DOS命令提示符运行此命令:
> java -cp "X:\JCG\articles\A JavaFX List Example\hsqldb-2.3.2\hsqldb\lib\hsqldb.jar" org.hsqldb.util.DatabaseManagerSwing
注意: hsqldb.jar
文件位于类路径中。
这将打开一个Connect GUI对话框,如下所示。
在对话框中输入以下信息:
- 最近的设置:<现在不选择任何内容。 下次连接数据库时,选择现在创建的设置。
- 设置名称:<输入名称>待办数据库设置
- 类型:<select> HSQL数据库引擎独立
- 驱动程序:<select> hsqldb.jdbcDriver
- URL:<输入数据库文件路径> jdbc:hsqldb:file:<<文件路径–有关指定路径的更多详细信息,请参见下面的注释>>
- 用户:<留空>
- 密码:<留空>
关于URL的文件路径的注意事项:可以将文件路径指定为相对路径或绝对路径。 相对路径是相对于当前目录的。 例如,URL中的jdbc:hsqldb:file:db\TODOS_DB
将创建一个名为db
的目录,并在其中创建TODOS_DB数据库。 带有绝对路径的示例是jdbc:hsqldb:file:X:\JCG\articles\A JavaFX List Example\db\TODOS_DB
。
单击确定。
这将在指定目录中创建一个名为TODOS_DB的数据库。 这还将打开“ HSQLDatabase Manager”窗口。 该窗口具有显示数据库结构,SQL条目和结果详细信息的区域。 该窗口如下所示。
2.2创建待办事项表
待办事项表具有三列:id,名称和描述。
- id:这是数据库系统生成的唯一整数。 这被定义为IDENTITY列。
IDENTITY列是由数据库的序列生成器自动生成的INTEGER。 默认情况下,列值从1开始,并递增1。当在表中进行插入时,将自动用新的***填充id列值。 本文后面将显示用于插入和检索id列值的语法(请参阅第5章“创建数据库访问代码” )。
- 名称:定义为VARCHAR(50),并且不为null。
- 描述:这被定义为VARCHAR(500)。
在“ HSQLDatabase Manager”窗口中,输入以下SQL脚本并执行它。
CREATE TABLE TODO_TABLE ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, name VARCHAR(50) NOT NULL, description VARCHAR(500) );
这将创建待办事项表。 可以在数据库结构区域中查看新创建的表。
注意:此步骤需要完成,然后再继续。 该应用程序的代码假定已创建数据库和表。
3.申请
待办事项显示在列表中,其中每个待办事项都是一个列表项。 在列表中选择待办事项时,名称和描述分别显示在文本框和文本区域中。 该数据可以编辑。 有一些按钮可以创建待办事项,删除和保存。 状态消息显示最近执行的操作。
GUI显示在一个窗口中。 可从todo数据库访问列表和文本框/区域中显示的数据。 该数据库在应用程序启动时打开,在关闭应用程序时关闭。
下面显示了完成的应用程序的GUI。
应用类别
该应用程序包含三个Java类。
- Todo.java:此类表示待办事项。
- TodoApp.java:此类是具有GUI和程序执行逻辑的主要应用程序。
- TodoDataAccess.java:此类具有访问todo数据库的功能。
3.1.1 Todo.java
一个Todo.java
由Todo.java
类表示。 待办事项具有名称和描述属性。 这还将维护一个唯一的id字段。
3.1.2 TodoDataAccess.java
此类具有访问todo数据库和数据的功能。 其功能是:
- 连接并关闭数据库
- 插入,更新,删除,查询和验证数据库中的数据
3.1.3 TodoApp.java
此类是主要的应用程序。 它具有启动应用程序,关闭应用程序,创建用户界面以及将GUI和应用程序连接到数据访问代码的功能。
4.构建GUI
在此步骤中,将构建没有按钮的数据库访问和动作事件处理程序的GUI。 仅将列表连接到列表选择更改侦听器。
该应用程序在列表中显示一些预定义的待办事项数据。 可以选择待办事项列表,相应的待办事项名称和说明将显示在它们各自的文本框/区域中。
下面显示了TodoApp.java类的代码及其说明。
4.1。守则
TodoApp.java:
import javafx.application.Application; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.layout.AnchorPane; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.scene.paint.Color; import javafx.scene.control.ListView; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.control.TextArea; import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane.ScrollBarPolicy; import javafx.scene.control.Button; import javafx.scene.control.Tooltip; import javafx.scene.text.Text; import javafx.geometry.Pos; import javafx.geometry.Insets; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import java.util.List; import java.util.ArrayList; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; public class TodoApp extends Application { private ListView<Todo> listView; private ObservableList<Todo> data; private TextField nametxt; private TextArea desctxt; private Text actionstatus; public static void main(String [] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Todo App - version 1"); // gridPane layout GridPane grid = new GridPane(); grid.setAlignment(Pos.CENTER); grid.setHgap(15); grid.setVgap(20); grid.setPadding(new Insets(25, 25, 25, 25)); // list view, listener and list data listView = new ListView<>(); listView.getSelectionModel().selectedIndexProperty().addListener( new ListSelectChangeListener()); data = getListData(); listView.setItems(data); grid.add(listView, 1, 1); // col = 1, row = 1 // todo name label and text fld - in a hbox Label namelbl = new Label("Todo Name:"); nametxt = new TextField(); nametxt.setMinHeight(30.0); nametxt.setPromptText("Enter todo name (required)."); nametxt.setPrefColumnCount(20); nametxt.setTooltip(new Tooltip( "Item name (5 to 50 chars length)")); HBox hbox = new HBox(); hbox.setSpacing(10); hbox.getChildren().addAll(namelbl, nametxt); // todo desc text area in a scrollpane desctxt = new TextArea(); desctxt.setPromptText("Enter description (optional)."); desctxt.setWrapText(true); ScrollPane sp = new ScrollPane(); sp.setContent(desctxt); sp.setFitToWidth(true); sp.setFitToHeight(true); sp.setPrefHeight(300); sp.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); sp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED); // todo hbox (label + text fld), scrollpane - in a vbox VBox vbox = new VBox(); vbox.setSpacing(10); vbox.getChildren().addAll(hbox, sp); grid.add(vbox, 2, 1); // col = 2, row = 1 // new and delete buttons Button newbtn = new Button("New"); Button delbtn = new Button("Delete"); HBox hbox2 = new HBox(10); hbox2.getChildren().addAll(newbtn, delbtn); grid.add(hbox2, 1, 2); // col = 1, row = 2 // save button to the right anchor pane and grid Button savebtn = new Button("Save"); AnchorPane anchor = new AnchorPane(); AnchorPane.setRightAnchor(savebtn, 0.0); anchor.getChildren().add(savebtn); grid.add(anchor, 2, 2); // col = 2, row = 2 // action message (status) text actionstatus = new Text(); actionstatus.setFill(Color.FIREBRICK); actionstatus.setText(""); grid.add(actionstatus, 1, 3); // col = 1, row = 3 // scene Scene scene = new Scene(grid, 750, 400); // width=750, height=400 primaryStage.setScene(scene); primaryStage.show(); // initial selection; statement does nothing if no data listView.getSelectionModel().selectFirst(); } // start() private class ListSelectChangeListener implements ChangeListener<Number> { @Override public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) { if ((new_val.intValue() < 0) || (new_val.intValue() >= data.size())) { return; // invalid data } // set name and desc fields for the selected todo Todo todo = data.get(new_val.intValue()); nametxt.setText(todo.getName()); desctxt.setText(todo.getDesc()); actionstatus.setText(todo.getName() + " - selected"); } } private ObservableList<Todo> getListData() { List<Todo> list = new ArrayList<>(); // initial list data list.add(new Todo("Work", "Work on JCG's example article.")); list.add(new Todo("Grocery", "Get apples, milk and bread.")); list.add(new Todo("Calls", "Call kid brother.")); list.add(new Todo("Read book", "Magnificent Obcession, by Lloyd C. Douglas.")); ObservableList<Todo> data = FXCollections.observableList(list); return data; } }
代码说明
4.2.1 JavaFX类
以下描述了用于构建GUI的JavaFX类:
-
Stage
类用于构建应用程序的主窗口。 -
GridPane
用于在行和列的网格中布局控件(按钮,文本字段等)。 -
HBox
和VBox
将其子控件布置在单个水平或垂直行中。 -
ListView
用于显示待办事项的垂直可滚动列表,用户可以从中进行选择。 -
Label
和Text
用于待办事项名称标签和文本字段。 -
TextArea
用于待办事项描述字段。 该字段放置在ScrollPane
,以便可以滚动文本。 -
Button
控件用于新建,保存和删除按钮。 -
Text
用于显示动作状态。
4.2.2控件布局
网格窗格布局具有3行和2列。 放置控件的单元格如下:
- 第1行第1行具有列表视图。
- Todo标签和文本字段位于hbox中。
- 第1行第2行在vbox中具有hbox和todo description文本区域。
- 第2行第1行在hbox中具有“新建”和“删除”按钮。
- 第2行第2列具有保存按钮。
- 第3行第1行具有状态文本。
4.2.3列表的更改侦听器
类型为ChangeListener<Number>
的列表选择更改侦听器已附加到列表视图:
listView.getSelectionModel().selectedIndexProperty().addListener(new changeListener());
选择列表项后,该项的待办事项名称和描述将显示在文本字段中。
4.2.4列表数据
列表视图中填充了来自ObservableList<Todo>
集合的数据–在应用程序的start()
方法中:
data = getListData(); listView.setItems(data);
在本节中,将在程序中创建列表的数据。 getListData()方法创建待办事项并将其作为ObservableList <Todo>集合返回。
4.3源代码
这是应用程序的版本1。 新创建了两个类。 这些类是:
- Todo.java
- TodoApp.java
注意:要编译代码并运行应用程序, jfxrt.jar
(JavaFX库)文件必须位于类路径中。 对于Java 7,可以在以下位置找到它: <JRE_HOME>/lib/jfxrt.jar
。
5.创建数据库访问代码
待办事项列表的数据是从数据库存储和访问的。 TODO_DB数据库中的TODO_TABLE存储待办事项详细信息。 数据库和表已在前面创建(请参阅2.创建应用程序数据库和表一节 )。 请注意,该应用假定访问数据库之前已创建该数据库。
本节介绍数据库访问代码。 TodoDataAccess.java类具有代码。 此代码使用JDBC(Java数据库连接)API来访问TODO_DB数据库。
注意:应用程序的GUI在下一节( 6.使用数据库访问连接GUI )中将其连接到数据库访问。
此类具有以下方法:
- 连接到todo数据库
- 关闭待办事项数据库
- 将所有待办事项表行读入List集合
- 在待办事项表中插入一行
- 检查待办事项表中是否存在待办事项名称
- 从待办事项表中删除一行
- 更新待办事项表中的一行
下面显示了TodoDataAccess.java
类的代码和详细信息。
5.1获取连接
构造函数具有访问数据库并获取Connection
对象的代码。 此连接对象用于读取或更新数据库数据。 连接的属性设置为自动提交,即,事务在没有显式提交的情况下在插入,更新或删除时提交。 连接是可更新的类型。
DriverManager's getConnection()
静态方法使用URL连接到数据库。
public TodoDataAccess() throws SQLException, ClassNotFoundException { Class.forName("org.hsqldb.jdbc.JDBCDriver" ); conn = DriverManager.getConnection( "jdbc:hsqldb:file:db/TODOS_DB;ifexists=true;shutdown=true", "", ""); conn.setAutoCommit(true); conn.setReadOnly(false); }
5.2获取所有行
此方法从todo表中检索所有行,并返回Todo元素的List
集合。
public List<Todo> getAllRows() throws SQLException { String sql = "SELECT * FROM " + todoTable + " ORDER BY name"; PreparedStatement pstmnt = conn.prepareStatement(sql); ResultSet rs = pstmnt.executeQuery(); List<Todo> list = new ArrayList<>(); while (rs.next()) { int i = rs.getInt("id"); String s1 = rs.getString("name"); String s2 = rs.getString("desc"); list.add(new Todo(i, s1, s2)); } pstmnt.close(); // also closes related result set return list; }
5.3插入一行
此方法将一行插入todo表。 该方法返回新的待办事项行的ID。
id值是数据库系统生成的***。 这是一个IDENTITY列。 DEFAULT关键字(在INSERT语句中)用于IDENTITY列,这将为该列自动生成一个值。 请参阅第2.2节。 创建待办事项表以获取有关IDENTITY列创建的详细信息。
PreparedStatement's getGeneratedKeys()
方法使用新生成的标识列值检索ResultSet
。
public int insertRow(Todo todo) throws SQLException { String dml = "INSERT INTO " + todoTable + " VALUES (DEFAULT, ?, ?)"; PreparedStatement pstmnt = conn.prepareStatement(dml, PreparedStatement.RETURN_GENERATED_KEYS); pstmnt.setString(1, todo.getName()); pstmnt.setString(2, todo.getDesc()); pstmnt.executeUpdate(); // returns insert count // get identity column value ResultSet rs = pstmnt.getGeneratedKeys(); rs.next(); int id = rs.getInt(1); pstmnt.close(); return id; }
5.4检查Todo名称是否存在
此方法检查待办事项表中是否已存在待办事项名称。 请注意,该应用仅允许使用唯一的待办事项名称。
public boolean nameExists(Todo todo) throws SQLException { String sql = "SELECT COUNT(id) FROM " + todoTable + " WHERE name = ? AND id <> ?"; PreparedStatement pstmnt = conn.prepareStatement(sql); pstmnt.setString(1, todo.getName()); pstmnt.setInt(2, todo.getId()); ResultSet rs = pstmnt.executeQuery(); rs.next(); int count = rs.getInt(1); pstmnt.close(); if (count > 0) { return true; } return false; }
5.5删除一行
此方法从给定待办事项的待办事项表中删除一行(如果存在)。 请注意,如果没有行被删除,则不会引发异常。
public void deleteRow(Todo todo) throws SQLException { String dml = "DELETE FROM " + todoTable + " WHERE id = ?"; PreparedStatement pstmnt = conn.prepareStatement(dml); pstmnt.setInt(1, todo.getId()); pstmnt.executeUpdate(); // returns delete count (0 for none) pstmnt.close(); }
5.6更新行
此方法使用待办事项属性的任何更改来更新待办事项表中的现有行。
public void updateRow(Todo todo) throws SQLException { String dml = "UPDATE " + todoTable + " SET name = ?, desc = ? " + " WHERE id = ?"; PreparedStatement pstmnt = conn.prepareStatement(dml); pstmnt.setString(1, todo.getName()); pstmnt.setString(2, todo.getDesc()); pstmnt.setInt(3, todo.getId()); pstmnt.executeUpdate(); // returns update count pstmnt.close(); }
5.7关闭数据库
此方法关闭数据库连接并关闭数据库。
public void closeDb() throws SQLException { conn.close(); }
5.8源代码
这是应用程序的版本2。 新创建一个类– TodoDataAccess.java。 其他没有变化。 这些类是:
- Todo.java
- TodoDataAccess.java
注意:这些类已编译。 没有要运行的程序。
6.通过数据库访问连接GUI
这是完成的应用程序。
该应用程序的GUI已连接到数据库。 该应用程序已更新,具有以下功能:
将新的待办事项添加到列表中。
- 点击新按钮; 输入待办事项名称和说明字段。
- 点击保存按钮。 这会将新输入的待办事项插入数据库。 新的待办事项已添加到列表中。
- 该应用程序验证输入的待办事项名称具有5到50个字符的长度,并且在列表中是唯一的。
- 输入新的待办事项时,可以通过单击删除按钮来取消输入。
更新列表中的待办事项。
- 从列表中选择一个待办事项。 编辑名称和/或描述字段。
- 点击保存按钮。 验证后,这会将更新的待办事项保存在数据库中并更新列表。
删除列表中的待办事项。
- 从列表中选择一个待办事项。
- 单击删除按钮。 这将从数据库和列表中删除待办事项。
应用启动和关闭。
- 在应用程序启动时,数据库中的所有待办事项都将加载到列表中。
- 在应用程序关闭时,数据库已关闭。
6.1编码
在此部分中,应用程序已更新:
- 新的,保存和删除按钮连接到相应的事件处理程序。
- 处理程序的代码访问数据库。
- 应用程序的启动和关闭方法访问数据库。
数据库访问代码已在上一节( 5.创建数据库访问代码 )中构建。
6.1.1关于事件处理程序
类型为ActionEvent
的事件处理程序用作按钮的动作事件处理程序。 为此,实现了EventHandler
接口。 按钮的处理程序属性设置为button.setOnaction(someHandler)
。
这是此应用程序中的三个按钮的常见功能-新建,删除和保存。
6.2创建一个新的待办事项
当用户单击新按钮时,将在列表视图中创建一个新的待办事项,应用程序会提示用户输入新待办事项的名称和说明。
private class NewButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent e) { actionstatus.setText("New"); // creates a todo at first row with name NEW todo and // selects it Todo todo = new Todo(0, "NEW Todo", ""); // 0 = dummy id int ix = 0; data.add(ix, todo); listView.getSelectionModel().clearAndSelect(ix); nametxt.clear(); desctxt.clear(); nametxt.setText("NEW Todo"); nametxt.requestFocus(); } }
6.3保存待办事项
单击保存按钮后,该应用程序:
- 验证待办事项名称的长度(5至50个字符)
- 检查名称是否已经存在于数据库中
- 将待办事项插入数据库
请注意,此事件处理程序用于插入和更新功能。
private class SaveButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent ae) { int ix = listView.getSelectionModel().getSelectedIndex(); if (ix < 0) { // no data selected or no data return; } String s1 = nametxt.getText(); String s2 = desctxt.getText(); // validate name if ((s1.length() < 5) || (s1.length() > 50)) { actionstatus.setText( "Name must be 5 to 50 characters in length"); nametxt.requestFocus(); nametxt.selectAll(); return; } // check if name is unique Todo todo = data.get(ix); todo.setName(s1); todo.setDesc(s2); if (isNameAlreadyInDb(todo)) { actionstatus.setText("Name must be unique!"); nametxt.requestFocus(); return; } if (todo.getId() == 0) { // insert in db (new todo) int id = 0; try { id = dbaccess.insertRow(todo); } catch (Exception e) { displayException(e); } todo.setId(id); data.set(ix, todo); actionstatus.setText("Saved (inserted)"); } else { // db update (existing todo) try { dbaccess.updateRow(todo); } catch (Exception e) { displayException(e); } actionstatus.setText("Saved (updated)"); } // end-if, insert or update in db // update list view with todo name, and select it data.set(ix, null); // required for refresh data.set(ix, todo); listView.getSelectionModel().clearAndSelect(ix); listView.requestFocus(); } } private boolean isNameAlreadyInDb(Todo todo) { boolean bool = false; try { bool = dbaccess.nameExists(todo); } catch (Exception e) { displayException(e); } return bool; }
6.4删除或取消待办事项
删除按钮的操作具有两个功能:
- 取消正在输入但尚未保存的新待办事项。
- 从列表和数据库中删除选定的(现有)待办事项。
private class DeleteButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent ae) { int ix = listView.getSelectionModel().getSelectedIndex(); if (ix < 0) { // no data or none selected return; } Todo todo = data.remove(ix); try { dbaccess.deleteRow(todo); } catch (Exception e) { displayException(e); } actionstatus.setText("Deleted"); // set next todo item after delete if (data.size() == 0) { nametxt.clear(); desctxt.clear(); return; // no selection } ix = ix - 1; if (ix < 0) { ix = 0; } listView.getSelectionModel().clearAndSelect(ix); // selected ix data (not set by list listener); // requires this is set Todo itemSelected = data.get(ix); nametxt.setText(itemSelected.getName()); desctxt.setText(itemSelected.getDesc()); listView.requestFocus(); } }
6.5应用程序启动和关闭
JavaFX Application
类的init()
和stop()
方法用于应用程序的初始化和关闭。 这些在应用程序中被覆盖。 init方法具有在应用程序启动时访问数据库的代码。 stop方法具有在应用程序关闭时关闭数据库的代码。
同样,在应用程序启动之后,待办事项列表中会填充数据库数据(而不是早期版本1中在程序内创建的数据)。 这将替换版本1中的代码data = getListData()
方法的代码data = getListData()
替换为data = getDbData()
。
@Override public void init() { try { dbaccess = new TodoDataAccess(); } catch (Exception e) { displayException(e); } } @Override public void stop() { try { dbaccess.closeDb(); } catch (Exception e) { displayException(e); } } private ObservableList<Todo> getDbData() { List<Todo> list = null; try { list = dbaccess.getAllRows(); } catch (Exception e) { displayException(e); } ObservableList<Todo> dbData = FXCollections.observableList(list); return dbData; } @Override public void start(Stage primaryStage) { ... data = getDbData(); listView.setItems(data); ...
6.6源代码
这是应用程序的版本3,并且是最终版本。 一类TodoApp.java
被修改。 其他没有变化。 这些类是:
- Todo.java
- TodoDataAccess.java
- TodoApp.java
注意:
- 要编译该应用程序,
jfxrt.jar
必须位于类路径中。 - 要运行该应用程序,
jfxrt.jar
和hsqldb.jar
文件必须位于类路径中。
7.部署为JAR文件
7.1创建可执行的JAR文件:todoapp.jar
带有createjar
命令选项的javafxpackager
实用程序用于为应用创建可执行的JAR文件。
- 创建一个名为:
deploy
的目录 - 在
deploy
目录中创建两个子目录:src
和dest
- 将所有应用程序的
class
文件放在src
目录中 - 导航到
deploy
目录,从DOS提示符下运行以下命令:
> javafxpackager -createjar -appclass TodoApp -srcdir src -outdir dest -outfile todoapp -v -classpath hsqldb.jar
这将创建应用程序的可执行JAR文件。 验证是否在dest
目录中创建了文件todoapp.jar
。
7.2运行应用
将创建的todoapp.jar
文件复制到deploy
(或任何)目录中。 请注意,在运行应用程序之前,需要满足以下条件:
- 目录(或类路径)中的
hsqldb.jar file
- 该应用程序的数据库和表是预先创建的(请参阅创建应用程序数据库和表一节 )
通过以下方式之一运行应用程序:
(a)在DOS命令提示符下:
> java -jar todoapp.jar
(b)双击todoapp.jar
文件。
8.下载Java源代码
翻译自: https://www.javacodegeeks.com/2015/01/javafx-list-example.html