JavaFX列表示例

这是一个使用JavaFX和HSQLDB构建的待办事项列表应用程序,具备添加、更新和删除待办事项功能。文章详细介绍了如何安装HSQLDB数据库,创建数据库和表,构建GUI,创建数据库访问代码,并最终将应用部署为JAR文件。应用的数据存储在HSQLDB的关系数据库中,使用JDBC进行数据库访问。
摘要由CSDN通过智能技术生成

这是使用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对话框,如下所示。

1个

在对话框中输入以下信息:

  • 最近的设置:<现在不选择任何内容。 下次连接数据库时,选择现在创建的设置。
  • 设置名称:<输入名称>待办数据库设置
  • 类型:<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.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。

3

应用类别

该应用程序包含三个Java类。

  • Todo.java:此类表示待办事项。
  • TodoApp.java:此类是具有GUI和程序执行逻辑的主要应用程序。
  • TodoDataAccess.java:此类具有访问todo数据库的功能。
3.1.1 Todo.java

一个Todo.javaTodo.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用于在行和列的网格中布局控件(按钮,文本字段等)。
  • HBoxVBox将其子控件布置在单个水平或垂直行中。
  • ListView用于显示待办事项的垂直可滚动列表,用户可以从中进行选择。
  • LabelText用于待办事项名称标签和文本字段。
  • 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.jarhsqldb.jar文件必须位于类路径中。

7.部署为JAR文件

7.1创建可执行的JAR文件:todoapp.jar

带有createjar命令选项的javafxpackager实用程序用于为应用创建可执行的JAR文件。

  • 创建一个名为: deploy的目录
  • deploy目录中创建两个子目录: srcdest
  • 将所有应用程序的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源代码

可以从此处下载源代码的所有三个版本: JavaFX List Example

翻译自: https://www.javacodegeeks.com/2015/01/javafx-list-example.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值