在 Java 应用程序中绑定 Bean 和数据

This tutorial needs a review. You can open a JIRA issue, or edit it in GitHub following these contribution guidelines.

本指南介绍了 NetBeans IDE 对 Java 应用程序中 Bean 绑定和数据绑定的支持。

netbeans stamp 80 74 73
Figure 1. 此页上的内容适用于 NetBeans IDE 7.1、7.2、7.3、7.4 和 8.0

要学完本教程,您需要具备以下软件和资源。

软件或资源 要求的版本

NetBeans IDE

版本 7.1、7.2、7.3、7.4 或 8.0

Java 开发工具包 (JDK)

版本 6 或更高版本

简介:NetBeans IDE 中的 Bean 绑定

在发布 Bean 绑定库之前,将 UI 组件连接到数据库或将组件属性的值保持同步非常麻烦。例如,将标准数据库中的数据显示在 JTable 中需要手动创建实用程序类来处理数据库与 JTable 之间的连接。而且让不同 Bean 属性的值保持同步(如呈现可视 Bean 的 JTextField 值)需要手动编码监听程序和事件处理程序。

Bean 绑定库对所有这些操作进行了简化和标准化。只需编写几行代码确定哪些组件的哪些属性需要保持同步,Bean 绑定库就可以处理其余的操作。在 NetBeans IDE 中,Bean 绑定功能集成在 GUI 构建器中,因此,在建立可视设计之后可以快速获取已编码应用程序的行为。

本指南概述了 IDE 中 Bean 绑定的主要功能。

将属性绑定到其他属性

就最基本的用途而言,Bean 绑定是一种不使用事件监听和处理代码连接 Bean 属性的方法。

为了说明 Bean 绑定的概念以及 IDE 如何支持该绑定,我们将举一个简单的示例,其中用户可以调整滑块来更改文本字段中的数值。

设置示例:

  1. 在 IDE 中,选择 "File"(文件)> "New Project"(新建项目)。

  2. 选择 "Java" 类别,然后选择 "Java Application"(Java 应用程序)模板。单击 "Next"(下一步)。

  3. 在向导的 "Name and Location"(名称和位置)页中,执行以下操作:

    • 键入 NumberSlider 作为项目名称。

    • 将 "Use Dedicated Folder for Storing Libraries"(使用专用文件夹存储库)复选框保留为取消选中状态。

numberslider small

  • 清除 "Create Main Class"(创建主类)复选框。

    1. 单击 "Finish"(完成)退出向导并设置项目。

    2. 在 "Projects"(项目)窗口中,右键单击 NumberSlider 项目节点并选择 "New"(新建)> "JFrame Form"(JFrame 窗体)。

(如果 "JFrame Form"(JFrame 窗体)在 "New"(新建)菜单中不可用,则选择 "Other"(其他)。然后在新建文件向导中,选择 "Swing GUI Forms"(Swing GUI 窗体)类别,然后选择 "JFrame Form"(JFrame 窗体)模板。)

  1. 在向导的 "Name and Location"(名称和位置)页中,执行以下操作:

    • 为类名键入 NumberSliderFrame

    • 为包名键入 numberslider

numberslider2 small
  1. 单击 "Finish"(完成)退出向导并创建窗体。

    ``NumberSliderFrame.java``  应以设计模式在编辑区域中打开。
  2. 从组件面板的 "Swing Controls"(Swing 控件)部分,将一个滑块组件拖至设计区域。(如果 "Palette"(组件面板)窗口未打开,请选择 "Window"(窗口)> "Palette"(组件面板)。)

  3. 从组件面板中,将一个文本字段组件拖至设计区域。

生成的窗体可能类似于下面的屏幕快照。不过,对于本示例而言,定位并不重要。

slider textfield small

源和目标

现在我们已经设置了该示例,下面可以创建绑定了。不过,我们首先需要确定哪个组件作为绑定的_源_,哪个组件作为绑定的_目标_。绑定源组件表示绑定属性值的来源。

在 GUI 编辑器中进行绑定时,开始先进行目标绑定,然后在 "Bind"(绑定)对话框中声明绑定源。

在本例中,由于 JSlider 附带一个默认值范围,因此我们将使用它作为源。

*注:*绑定可以是双向的(读/写),这样,在目标中所做的更改可以自动地反映在源中。但是,初始绑定方向始终从源到目标。请参见高级绑定配置一节中有关“更新模式”的信息。

将滑块绑定到文本字段:

  1. 右键单击文本字段组件,并选择 "Bind"(绑定)> "text"(文本)以打开 "Bind"(绑定)对话框。

  2. 从 "Binding Source"(绑定源)组合框中,选择 jSlider1

  3. 从 "Binding Expression"(绑定表达式)组合框中,选择 value int ,如下图所示。

bind dialog small
  1. 单击 "OK"(确定)。

刚才将滑块的 value Bean 属性绑定到了文本字段的 text 值。

在设计区域,文本字段应显示值 50 。此值说明滑块处于中间位置,并且滑块的默认值范围为 0 到 100。

现在可以运行该应用程序并查看工作中的绑定。

选择 "Run"(运行)> "Run File"(运行文件)以运行文件。

应用程序应在单独的窗口中启动。在运行的应用程序中调整滑块,并查看文本字段中值的更改。

run numberslider

绑定定制 Bean

在上一节中,您绑定了从组件面板添加到窗体的两个标准 Swing 组件的属性。还可以绑定其他 Bean 的属性。不过,要执行此操作,您需要执行一些步骤,让 IDE 用于生成绑定代码的功能使该 Bean 可用。可以采取以下任一方法使 IDE 的绑定功能可用于 Bean:

  • 将 Bean 添加到组件面板,以便可以像添加标准 Swing 组件那样将其添加到窗体。

  • 将 Bean 类添加到您的项目并编译该 Bean。

将 Bean 添加到“组件面板”窗口:

  1. 确保编译了 Bean。

  2. 选择“工具”>“组件面板”>“Swing/AWT 组件”。

  3. 如果要为 Bean 创建新的组件面板类别,请在添加 Bean 之前单击“新建类别”,然后输入所需的名称。

  4. 单击“从 JAR 添加”、“从库添加”或“从项目添加”,完成添加 Bean 的向导操作。

从项目添加 Bean:

  1. 在“项目”窗口中,右键单击 Bean 的节点并选择“编译文件”。

  2. 将 Bean 拖至窗体。

然后您应在“检查器”窗口中看到此 Bean。接着可以为该 Bean 的任何属性调用“绑定”对话框。

高级绑定配置

本教程第一节中的示例介绍了与某些默认行为的简单绑定。但是,有时您可能希望或需要以不同方式配置绑定。如果是这种情况,则可以使用“绑定”对话框的“高级”标签。

该对话框的“高级”标签中包含以下字段:

  • 名称。可用于创建绑定的名称,这可以让您更为灵活地管理绑定。该名称将添加到绑定的构造函数中,可使用绑定的 getName() 方法来引用它。

  • 更新模式。指定保持属性同步的方式。可能的值为:

  • 始终同步 (读/写)。不论何时对源或目标之一进行了更改,另一个也将更新。

  • 只能从源中读取 (只读)。仅在首次设置源值时更新目标。将在目标中更新对源所做的更改。不会在源中更新对目标所做的更改。

  • 从源中读取一次 (读取一次)。仅在初始绑定目标和源时才更新目标。

  • 更新源的时间(仅在绑定 JTextField 和 JTextArea 组件的 text 属性时才出现此选项)。用于选择同步属性的频率。

  • 忽略调整(仅在绑定 JSlider 的 value 属性、JTable 和 JList 的 selectedElement 属性以及 JTable 和 JList 的 selectedElements 属性时才出现此选项)。如果选中此复选框,则只有在用户完成更改后,才会将某一属性的任意更改应用到另一个属性中。例如,当应用程序用户拖动滑块时,只有在用户松开鼠标按钮后,才会更新滑块的 value 属性所绑定的属性值。

  • 转换器。如果绑定涉及到具有不同数据类型的属性,则可以指定在类型之间转换值的代码。Bean 绑定库可处理很多常用转换,但对于其他属性类型的组合,则可能需要提供您自己的转换器。此类转换器需要扩展 org.jdesktop.beansbinding.Converter 类。

“转换器”下拉列表中填充了已作为 Bean 添加到窗体中的任何转换器。还可以使用以下方法直接添加转换代码:单击省略号 (…​) 按钮,然后从“使用以下内容选择转换器属性”下拉列表中选择“定制代码”。

下面列出了不需要提供转换器的转换:

  • 将 BigDecimal 转换为字符串型,将字符串型转换为 BigDecimal

  • 将 BigInteger 转换为字符串型,将字符串型转换为 BigInteger

  • 将布尔型转换为字符串型,将字符串型转换为布尔型

  • 将字节型转换为字符串型,将字符串型转换为字节型

  • 将字符型转换为字符串型,将字符串型转换为字符型

  • 将双精度型转换为字符串型,将字符串型转换为双精度型

  • 将浮点型转换为字符串型,将字符串型转换为浮点型

  • 将整型转换为字符串型,将字符串型转换为整型

  • 将长整型转换为字符串型,将字符串型转换为 BigDecimal

  • 将短整型转换为字符串型,将字符串型转换为短整型

  • 将整型转换为布尔型,将布尔型转换为整型

  • 验证器。可用于指定代码以验证在目标属性值中的更改,然后再将该更改传播回源属性。例如,您可以使用验证器确保整型属性值在指定的范围内。

验证器需要扩展 org.jdesktop.beansbinding.Validator 类。 “验证器”下拉列表中填充了已作为 Bean 添加到窗体中的任何验证器。还可以使用以下方法直接添加验证代码:单击省略号 (…​) 按钮,然后从“使用以下内容选择验证器属性”下拉列表中选择“定制代码”。

  • 空值源值。可用于在尝试绑定时源属性具有 值的情况下指定使用其他值。该字段与 org.jdesktop.beansbinding.Binding 类的 setSourceNullValue() 方法相对应。

  • 不可读源值。可用于在尝试绑定时无法解析绑定表达式的情况下指定使用其他值。该字段与 org.jdesktop.beansbinding.Binding 类的 setSourceUnreadableValue() 方法相对应。

*注:*为了更好地了解上面提到的类和方法,可以从 IDE 中直接访问 Bean 绑定 Javadoc 文档。选择“帮助”>“Javadoc 参考”>“Bean 绑定”。在打开的浏览器窗口中,单击 org.jdesktop.beansbinding 链接以访问这些类的文档。

将数据绑定到组件

除了同步可视 Swing 组件和其他定制 Bean 的属性之外,还可以使用 Bean 绑定帮助您使用可视组件与数据库交互。在创建新的 Java 窗体并在窗体中添加组件后,您可以生成代码,以便将这些组件绑定到数据上。本节介绍如何将数据绑定到 Swing JTable、JList 和 JComboBox 组件。

在将组件绑定到数据库中的数据之前,您需要完成以下操作:

  • 在 IDE 中连接到数据库。

  • 创建一些类,用于表示要绑定的数据库表。下面介绍了创建实体类以便将数据绑定到组件的步骤。

创建实体类

创建实体类以表示要绑定到 JTable 的数据库:

  1. 在 "Projects"(项目)窗口中,右键单击项目并选择 "New"(新建)> "Other"(其他),选择 "Persistence"(持久性)类别,然后选择 "Entity Classes from Database"(通过数据库生成实体类)模板。

  2. 在向导的 "Database Tables"(数据库表)页中,选择数据库连接。

  3. 在 "Available Tables"(可用表)列被填充后,选择要在应用程序中使用的表,然后单击 "Add"(添加),以便将表移到 "Available Tables"(选定的表)列中。单击 "Next"(下一步)。

entity wizard1 small
  1. 在该向导的 "Entity Classes"(实体类)页中,确保选中了 "Generate Named Query Annotations for Persistent Fields"(为持久性字段生成已命名的查询标注)和 "Create Persistence Unit"(创建持久性单元)复选框。

entity wizard2 small
  1. 对生成类的名称及其位置进行任何所需的定制。

  2. 单击 "Finish"(完成)。

在 "Projects"(项目)窗口中,您会看到实体类的节点。

将组件绑定到表示数据的 Bean

本节介绍如何将数据绑定到 JTable、JList 和 JComboBox 组件。

将一个数据库表添加到窗体,并自动生成 JTable 以显示数据库表的内容:

  1. 打开 "Services"(服务)窗口。

  2. 连接到包含您要添加到窗体的表的数据库。(可以通过右键单击用于数据库连接的节点并选择 "Connect"(连接)以连接到数据库。)

*注:*本教程使用 sample [app on App] 数据库,通过选择 "Services"(服务)窗口,展开 "Databases"(数据库)节点,右键单击数据库连接节点 ( jdbc:derby://localhost:1527/sample[app on APP] ),然后从上下文菜单中选择 "Connect"(连接),可连接到该数据库。 如果系统提示您提供用户 ID 和口令,请指定 app 作为用户 ID,并指定 app 作为口令。

  1. 展开用于连接的节点,并展开其表节点。

  2. 将表节点拖到窗体并在拖至表时按住 Ctrl 键。

这将创建 JTable,并将其列绑定到数据库表中的列。

将数据库表绑定到现有的 JTable 组件:

  1. 在 GUI 构建器中右键单击该组件,然后选择 "Bind"(绑定)> "elements"(元素)。

bind dialog table small
  1. 单击 "Import Data to Form"(将数据导入窗体)。在 "Import Data to Form"(将数据导入窗体)对话框中,选择要将组件绑定到的数据库表。单击 "OK"(确定)。

  2. 在 "Binding Source"(绑定源)组合框中,选择表示实体类结果列表的项。例如,如果调用实体类 Customer.java ,则列表对象将生成为 customerList

source selected small
  1. 将绑定表达式的值保留为 空值

  2. 如果不想在 JTable 中显示某些数据库列,请在 "Selected"(选定)列表中选择这些列,然后将它们移到 "Available"(可用)列表中。

  3. 选择 "Advanced"(高级)标签进一步配置绑定内容。例如,您可以指定验证器或转换器,或者指定绑定源为空值或不可读时的行为。

  4. 单击 "OK"(确定)。

将数据绑定到 JList 组件:

  1. 在 GUI 构建器中右键单击该组件,然后选择 "Bind"(绑定)> "elements"(元素)。

  2. 单击 "Import Data to Form"(将数据导入窗体)。在 "Import Data to Form"(将数据导入窗体)对话框中,选择要将组件绑定到的数据库表。单击 "OK"(确定)。

  3. 在 "Binding Source"(绑定源)组合框中,选择表示实体类结果列表的项。例如,如果调用实体类 Customer.java ,则列表对象将生成为 customerList

jlist binding small
  1. 将绑定表达式的值保留为 空值

  2. 在 "Display Expression"(显示表达式)下拉列表中,选择表示数据库列的属性,该列包含了要在列表中显示的值。

  3. 选择 "Advanced"(高级)标签进一步配置绑定内容。

  4. 单击 "OK"(确定)。

将数据绑定到 JComboBox 组件:

  1. 右键单击组合框,然后选择 "Bind"(绑定)> "elements"(元素)。

  2. 单击 "Import Data to Form"(将数据导入窗体)。在 "Import Data to Form"(将数据导入窗体)对话框中,选择要将组件绑定到的数据库表。单击 "OK"(确定)。

  3. 在 "Binding Source"(绑定源)组合框中,选择表示实体类结果列表的项。例如,如果调用实体类 Customer.java ,则列表对象将生成为 customerList

combo binding small
  1. 将绑定表达式值保留为 空值 ,然后单击 "OK"(确定)。

  2. 再次右键单击组合框,然后选择 "Bind"(绑定)> "selectedItem"。

  3. 绑定到您希望受用户选择影响的属性。

combo item
  1. 单击 "OK"(确定)保存所做的编辑。

Bean 绑定库(从版本 1.2.1 起)没有 DetailBinding 类,该类用于指定如何为 JComboBox 派生 display 值。因此,您需要编写一些定制代码。一种方法是编写定制单元格呈现器,如下所示。

要正确呈现组合框,请执行以下操作:

  1. 选择组合框。

  2. 在 "Properties"(属性)窗口的 "Properties"(属性)标签中,选择呈现属性。

  3. 单击省略号 (…​) 按钮。

  4. 在属性编辑器顶部的组合框中,选择 "Custom Code"(定制代码)。

  5. 在文本区域中,输入类似以下内容的代码,其中 jComboBox1 是 JComboBox 实例的名称,MyEntityClass 是实体类,getPropertyFromMyEntityClass() 是实体类中要绑定的属性的 getter。

jComboBox1.setRenderer(new DefaultListCellRenderer() {
           @Override
           public Component getListCellRendererComponent(
                   JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
               super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
               if (value instanceof MyEntityClass) {
                   MyEntityClass mec = (MyEntityClass)value;
                   setText(mec.getPropertyFromMyEntityClass());
               }
               return this;
           }
            })
custom small

*注:*您还可以在其自身的源文件中创建定制呈现器,编译文件,将呈现器拖至窗体,然后设置组合框的呈现器属性以使用此 Bean。

特殊绑定属性

根据需要,Bean 绑定库可为某些 Swing 组件提供特殊合成属性(这些组件本身没有这些属性)。这些属性表示用于绑定到其他属性的内容,如选定的表行。

下面列出了 Bean 绑定库添加的一组合成属性:

组件 属性 描述

AbstractButton

selected

按钮的选定状态。

JComboBox

selectedItem

JComboBox 的选定项。

JSlider

value

JSlider 值;通知所有更改。

value_IGNORE_ADJUSTING

与 "value" 基本相同,但在滑块调整值时不通知更改。

JList

selectedElement

JList 的选定元素;通知所有更改。如果在 JListBinding 中将 JList 作为目标,则会将单个选定元素报告为绑定源列表中的元素。否则,将该选定元素报告为列表模型中的对象。如果未选择任何内容,则该属性的值为 空值

selectedElements

JList 的多个选定元素的列表;通知所有更改。如果在 JListBinding 中将 JList 作为目标,则会将多个选定元素报告为绑定源列表中的元素。否则,将这些选定元素报告为列表模型中的对象。如果未选择任何内容,则该属性的值为空列表。

selectedElement_IGNORE_ADJUSTING

与 "selectedElement" 基本相同,但在更新列表选定内容时不通知更改。

selectedElements_IGNORE_ADJUSTING

与 "selectedElements" 基本相同,但在更新列表选定内容时不通知更改。

JTable

selectedElement

JTable 的选定元素;通知所有更改。如果在 JTableBinding 中将 JTable 作为目标,则会将选定元素报告为绑定源列表中的元素。否则,将选定元素报告为一个映射,其中,键由字符串 "column" 和列索引组成;值为该列的模型值。例如:{column0=column0value,column1=column1value,…​} 如果未选择任何内容,则该属性的值为 空值

selectedElements

JTable 的选定元素的列表;通知所有更改。如果在 JTableBinding 中将 JTable 作为目标,则会将多个选定元素报告为绑定源列表中的元素。否则,将每个选定元素报告为一个映射,其中,键由字符串 "column" 和列索引组成;值为该列的模型值。例如:{column0=column0value, column1=column1value, …​} 如果未选择任何内容,则该属性的值为空列表。

selectedElement_IGNORE_ADJUSTING

与 "selectedElement" 基本相同,但在更新表选定内容时通知更改。

selectedElements_IGNORE_ADJUSTING

与 "selectedElements" 基本相同,但在更新表选定内容时不通知更改。

JTextComponent(包括其子类 JTextField、JTextArea 和 JEditorPane)

text

JTextComponent 的 text 属性;通知所有更改(包括键入内容)。

text_ON_FOCUS_LOST

JTextComponent 的 text 属性;仅在组件不处于焦点状态时通知更改。

text_ON_ACTION_OR_FOCUS_LOST

JTextComponent 的 text 属性;仅在组件通知 actionPerformed 或组件不处于焦点状态时通知更改。

另请参见