当前位置:网站首页 > Java教程 > 正文

java swing 表格教程



使用类可以显示数据表,还可以选择允许用户编辑数据。 不包含或缓存数据;它只是你的数据的一个视图。下面是一个在滚动窗格中显示的典型表的图片:

TableDemo的快照,显示了一个典型的表。

本节的其余部分将向您展示如何完成一些常见的与表格相关的任务。以下是本节涵盖的主题:

  • 创建一个简单的表格
  • 将表格添加到容器中
  • 设置和更改列宽
  • 用户选择
  • 创建表模型
  • 监听数据变化
  • 触发数据变化事件
  • 概念:编辑器和渲染器
  • 使用自定义渲染器
  • 为单元格指定工具提示
  • 为列标题指定工具提示
  • 排序和过滤
  • 使用下拉框作为编辑器
  • 使用其他编辑器
  • 使用编辑器验证用户输入的文本
  • 打印
  • 使用表格的示例

在中的表格声明了一个字符串数组作为列名:

数据被初始化并存储在一个二维对象数组中:

然后使用这些数据和列名构建表格:

有两个构造函数可以直接接受数据(使用第一个):

这些构造函数的优点是它们使用起来很容易。然而,这些构造函数也有缺点:

  • 它们自动使每个单元格可编辑。
  • 它们将所有数据类型都视为相同的字符串。例如,如果表格列具有数据,表格可以以复选框的形式显示数据。但是,如果使用前面列出的任何一个构造函数,数据将以字符串形式显示。你可以在前面的图中的列中看到这个区别。
  • 它们要求你将所有的表格数据放入一个数组或向量中,这对于某些数据可能不合适。例如,如果你正在从数据库中实例化一组对象,你可能希望直接查询对象的值,而不是将所有值都复制到数组或向量中。

如果你想避开这些限制,你需要自己实现一个表格模型,详见创建表格模型。

下面是创建滚动窗格作为表格容器的典型代码:

这个代码片段中的两行代码分别执行以下操作:

  • 使用引用到表对象的参数调用构造函数。这将创建一个滚动窗格作为表的容器;表会自动添加到容器中。
  • 调用设置属性。当此属性为时,即使表没有足够的行来使用整个垂直空间,表也会使用容器的整个高度。这使得将表用作拖放目标更容易。

滚动窗格会自动将表头放置在视口的顶部。当滚动表数据时,列名仍然保持在视区的顶部可见。

如果您使用的是没有滚动窗格的表,则必须获取表头组件并自行放置。例如:

默认情况下,表中的所有列都具有相等的宽度,并且列自动填充整个表的宽度。当表变得更宽或更窄时(当用户调整包含表的窗口大小时可能会发生),所有列的宽度会相应地改变。

当用户通过拖动列的右边界调整列大小时,要么其他列必须改变大小,要么表的大小必须改变。默认情况下,表的大小保持不变,右边界拖动点左侧的列的宽度增加或减少的空间会被分配给右边的所有列。

要自定义初始列宽度,可以在表的每个列上调用。这将设置列的首选宽度和其大致相对宽度。例如,将以下代码添加到将使其第三列比其他列更宽:

如上述代码所示,表中的每个列由一个对象表示。提供了用于列的最小、首选和最大宽度的getter和setter方法,以及用于获取当前宽度的方法。有关根据绘制单元格内容所需空间的近似值设置单元格宽度的示例,请参阅中的方法。

当用户显式调整列大小时,列的首选宽度被设置为用户指定的大小,成为列的新当前宽度。然而,当表本身被调整大小时(通常是因为窗口被调整大小),列的首选宽度不会改变。相反,现有的首选宽度被用来计算新的列宽以填充可用空间。

您可以通过调用来改变表的调整大小行为。

在默认配置下,表支持由一个或多个行组成的选择。用户可以选择一系列连续的行或任意一组行。用户最后指示的单元格会有一个特殊的标记;在Metal外观中,该单元格被勾勒出来。这个单元格被称为主导选择;有时也称为“焦点单元格”或“当前单元格”。

用户使用鼠标和/或键盘进行选择,如下表所述:

操作 鼠标操作 键盘操作 选择单行。 点击。 向上箭头或向下箭头。 扩展连续选择。 Shift-点击或拖动行。 Shift-向上箭头或Shift-向下箭头。 将行添加到选择/切换行选择。 Control-点击 使用Control-向上箭头或Control-向下箭头移动主导选择,然后使用空格键添加到选择或使用Control-空格键切换行选择。

要查看选择的工作原理,请点击“启动”按钮以运行使用(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参考示例索引。

启动TableSelectionDemo示例

此示例程序展示了熟悉的表,并允许用户操作某些JTable选项。还有一个文本窗格用于记录选择事件。

在下面的屏幕截图中,用户运行了该程序,点击了第一行,然后使用Ctrl键点击了第三行。请注意最后点击的单元格周围的轮廓;这是Metal外观如何突出显示主导选择。

TableSelectionDemo with a non-contiguous row selection.

在“选择模式”下有一组单选按钮。点击标有“单选”标签的按钮。现在你只能一次选择一行。如果点击“单区间选择”单选按钮,则可以选择一组必须连续的行。

“选择模式”下的所有单选按钮都调用了 方法。此方法接受一个参数,该参数必须是 中定义的以下常量之一:、 和 。

回到 ,注意“选择选项”下的三个复选框。每个复选框控制着 定义的一个 类型的绑定变量的状态:

  • “行选择”控制着 ,该变量具有 setter 方法 和 getter 方法 。当该绑定属性为 (且 属性为 )时,用户可以按行选择。
  • “列选择”控制着 ,该变量具有 setter 方法 和 getter 方法 。当该绑定属性为 (且 绑定属性为 )时,用户可以按列选择。
  • “单元格选择”控制着 ,该变量具有 setter 方法 和 getter 方法 。当该绑定属性为 时,用户可以选择单个单元格或矩形区域的单元格。

如果清除所有三个复选框(将所有三个绑定属性设置为 ),则没有选择;只有主选择会显示。

你可能会注意到,在多区间选择模式下,“单元格选择”复选框是被禁用的。这是因为在演示中不支持此模式下的单元格选择。你可以在多区间选择模式下指定单元格选择,但结果是一个无法产生有用选择的表格。

你可能还会注意到,更改任何三个选择选项可能会影响其他选项。这是因为允许行选择和列选择的同时,也等同于启用了单元格选择。 会自动根据需要更新这三个绑定变量,以保持它们的一致性。

要获取当前选择的内容,使用方法获取行索引数组,使用方法获取列索引数组。要获取主要选择的坐标,可以参考表格本身和表格的列模型的选择模型。以下代码格式化一个包含主要选择行和列的字符串:

用户选择会触发多个事件。有关这些事件的信息,请参考课程中的。

每个表格对象都使用一个表格模型对象来管理实际的表格数据。表格模型对象必须实现接口。如果程序员没有提供表格模型对象,会自动创建一个的实例。下面是这种关系的示例:

表格、表格对象、模型对象之间的关系

使用的构造函数使用以下代码创建其表格模型:

正如上述代码所示,实现表格模型可以很简单。通常情况下,您会在类的子类中实现您的表格模型。

您的模型可以将数据存储在数组、向量或哈希映射中,或者它可以从外部源(如数据库)获取数据。它甚至可以在执行时生成数据。

此表格与表格有以下不同之处:

  • 的自定义表格模型虽然简单,但可以轻松确定数据的类型,从而帮助以**格式显示数据。另一方面,的自动生成的表格模型不知道# of Years列包含数字(通常应该右对齐并具有特定格式)。它还不知道列包含布尔值,可以用复选框表示。
  • 中实现的自定义表格模型不允许编辑名称列;但是,它允许您编辑其他列。在中,所有单元格都是可编辑的。

下面是从中提取的代码,与不同。粗体字表示此表格的模型与为自动定义的表格模型不同的代码。

表格模型可以有一组监听器,每当表格数据发生变化时,它们都会收到通知。监听器是 的实例。在下面的示例代码中, 被扩展以包含这样的监听器。新代码用粗体表示。

为了触发数据变化事件,表格模型必须知道如何构造一个 对象。这可能是一个复杂的过程,但已经在 中实现了。您可以允许 使用其默认的 实例,或者创建自己的自定义 的子类。

如果不适合作为自定义表格模型类的基类,请考虑子类化。该类实现了一个简单的框架来构造对象。您的自定义类只需在每次表格数据由外部源更改时调用以下方法之一。

方法 变更 更新指定单元格。 更新指定行。 更新整个表格(仅数据)。 插入新行。 删除现有行。    使整个表格无效,包括数据和结构。

在继续下面的任务之前,您需要了解表格如何绘制其单元格。您可能期望表格中的每个单元格都是一个组件。然而,出于性能原因,Swing表格实现方式不同。

相反,通常使用一个单一的单元格渲染器来绘制包含相同类型数据的所有单元格。您可以将渲染器视为一个可配置的印章,表格使用它将格式正确的数据印到每个单元格上。当用户开始编辑单元格的数据时,单元格编辑器接管单元格,控制单元格的编辑行为。

例如,中年数列中的每个单元格都包含数据 - 具体而言,是一个对象。默认情况下,包含的列的单元格渲染器使用一个右对齐的实例在列的单元格上绘制适当的数字。如果用户开始编辑其中一个单元格,则默认的单元格编辑器使用一个右对齐的来控制单元格的编辑。

为了选择在列中显示单元格的渲染器,表格首先确定您是否为该特定列指定了渲染器。如果没有指定,表格会调用表格模型的方法,该方法获取列的单元格的数据类型。接下来,表格将列的数据类型与已注册的单元格渲染器的数据类型列表进行比较。此列表由表格进行初始化,但您可以添加或更改它。目前,表格将以下类型的数据放入列表中:

  • — 用复选框呈现。
  • — 用右对齐的标签呈现。
  • 、 — 与相同,但对象到文本的转换由一个实例执行(使用当前区域设置的默认数字格式)。
  • — 由标签呈现,对象到文本的转换由一个实例执行(使用日期和时间的短格式)。
  • 、 — 由居中的标签呈现。
  • — 由显示对象字符串值的标签呈现。

使用类似的算法选择单元格编辑器。

请记住,如果您让表格创建自己的模型,它将使用作为每一列的类型。要指定更精确的列类型,表格模型必须适当地定义方法,就像中所演示的那样。

请记住,尽管渲染器决定每个单元格或列标题的外观并可以指定其工具提示文本,但渲染器不处理事件。如果您需要捕获发生在表格内的事件,您所使用的技术取决于您感兴趣的事件类型:

情况 如何获取事件 要检测正在编辑的单元格的事件... 使用单元格编辑器(或在单元格编辑器上注册侦听器)。 要检测行/列/单元格的选择和取消选择的事件... 使用选择侦听器,如检测用户选择中所述。 要检测列标题上的鼠标事件... 在表格的对象上注册适当类型的。(有关示例,请参见。) 要检测其他事件... 在对象上注册适当的侦听器。

接下来的几个部分将告诉您如何通过指定渲染器和编辑器来自定义显示和编辑。您可以按列或按数据类型指定单元格渲染器和编辑器。

本节将告诉您如何创建和指定单元格渲染器。您可以使用方法设置特定类型的单元格渲染器。要指定特定列中的单元格使用渲染器,可以使用方法。您甚至可以通过创建子类来指定特定单元格的渲染器。

很容易自定义默认渲染器的文本或图像。只需创建一个子类,并实现方法,使其调用适当的字符串或图像的或。例如,下面是默认日期渲染器的实现:

如果扩展不足够,可以使用另一个超类构建渲染器。最简单的方法是创建一个现有组件的子类,使您的子类实现接口。 只需要一个方法:。您实现此方法应该设置渲染组件以反映传入的状态,然后返回该组件。

在的快照中,用于Favorite Color单元格的渲染器是的子类。以下是的摘录,显示了其实现方式。

这是来自的代码,它将实例注册为所有数据的默认渲染器:

要指定单元格特定的渲染器,您需要定义一个覆盖方法的子类。例如,以下代码使表格的第一列的第一个单元格使用自定义渲染器:

默认情况下,表格单元格的工具提示文本由单元格的渲染器确定。然而,有时候通过覆盖的方法来指定工具提示文本会更简单。本节将向您展示如何同时使用这两种技术。

要使用渲染器为单元格添加工具提示,您首先需要获取或创建单元格渲染器。然后,在确保渲染组件是的情况下,调用其上的方法。

在中有设置单元格工具提示的示例。点击“启动”按钮以使用运行它(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参考示例索引。

启动TableRenderDemo示例

源代码位于。它使用以下代码为Sport列的单元格添加工具提示:

尽管前面示例中的工具提示文本是静态的,但您也可以实现根据单元格或程序状态而变化的工具提示。以下是几种实现方式:

  • 在渲染器的方法的实现中添加一些代码。
  • 重写的方法。

在中添加代码到单元格渲染器的示例。单击“启动”按钮使用运行它(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参阅示例索引。

启动TableDialogEditDemo示例

使用在中实现的颜色渲染器,使用下面代码中的粗体代码设置工具提示文本:

下面是工具提示的示例:

TableDialogEditDemo显示鼠标悬停的单元格的RGB值的工具提示

您可以通过重写的方法来指定工具提示文本。程序展示了如何实现。单击“启动”按钮使用运行它(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参阅示例索引。

启动TableToolTipsDemo示例

具有工具提示的单元格位于SportVegetarian列中。以下是工具提示的图片:

TableToolTipsDemo中Sport列中单元格的工具提示

以下是实现SportVegetarian列单元格工具提示的代码:

代码非常简单,除了调用可能有些不太清楚。这个调用是必要的,因为如果用户移动了列,视图的索引与模型的索引将不匹配。例如,用户可能会拖动Vegetarian列(模型认为它在索引4处),以便它显示为第一列-在视图索引0处。由于提供了视图索引,您需要将视图索引转换为模型索引,以确保选择了预期的列。

您可以通过设置表格的的工具提示文本来为列标题添加工具提示。通常,不同的列标题需要不同的工具提示文本。您可以通过重写表头的方法来更改文本。或者,您可以调用为表头提供自定义渲染器。

在中有一个使用相同工具提示文本的示例。以下是它如何设置工具提示文本:

演示了按列实现变化的列标题工具提示的示例。如果使用(下载JDK 7或更高版本)运行(单击启动按钮)。或者,要编译和运行示例,请参阅示例索引。

启动TableToolTipsDemo示例

当您将鼠标悬停在除前两个之外的任何列标题上时,您将看到工具提示。由于名称列似乎不言自明,因此没有提供工具提示。以下是列标题工具提示的示例图片:

具有列标题工具提示的TableToolTipsDemo

以下代码实现了工具提示。基本上,它创建了的子类,重写了方法,以返回当前列的文本。为了将修改后的表头与表格关联起来,重写了方法,使其返回子类的实例。

表格的排序和筛选由一个排序器对象管理。最简单的方法是将绑定属性设置为:

这个操作会定义一个排序器对象,它是的实例。当用户点击表格列头时,它会进行一个简单的区域特定排序。这在中有示例,如下图所示:

点击“姓”后的TableSortDemo

如果想要更多对排序的控制,可以构造一个的实例,并将其设置为表格的排序器对象。

使用对象来对行进行排序。实现了这个接口的类必须提供一个名为的方法,用于定义两个对象在排序时如何进行比较。例如,下面的代码创建了一个按每个字符串中的最后一个单词排序的:

这个例子非常简单;更典型的情况是, 的实现是 的子类。你可以定义自己的子类,使用 中的工厂方法获取特定区域设置的 ,或者使用 。

为了确定在列上使用哪个 , 依次尝试应用以下规则。规则按照下面列出的顺序进行;第一个为排序器提供 的规则将被使用,而其他规则将被忽略。

  1. 如果通过调用 指定了比较器,使用该比较器。
  2. 如果表模型报告该列数据包含字符串( 返回 ),使用根据当前区域设置对字符串进行排序的比较器。
  3. 如果由 返回的列类实现了 ,使用根据 返回值对字符串进行排序的比较器。
  4. 如果通过调用 为表指定了字符串转换器,使用根据当前区域设置对结果字符串表示进行排序的比较器。
  5. 如果前面的规则都不适用,使用在列数据上调用 并根据当前区域设置对结果字符串进行排序的比较器。

对于更复杂的排序方式,可以创建 或其父类 的子类。

要指定列的排序顺序和排序优先级,请调用 。下面是一个示例,对示例中使用的表格按照前两列进行排序。排序中列的优先级由排序键列表中的排序键的顺序表示。在这个例子中,第二列有第一个排序键,所以行首先按照名字排序,然后按照姓氏排序。

除了重新排序结果,表格排序器还可以指定显示哪些行,这被称为过滤。 使用 对象来实现过滤。 实现了几个工厂方法,用于创建常见类型的过滤器。例如, 返回一个基于的 。

在下面的示例代码中,您明确创建了一个排序器对象,以便以后可以使用它来指定过滤器:

然后,您可以根据文本字段的当前值进行过滤:

在后续示例中,每次文本字段更改时都会调用。当用户输入复杂的正则表达式时, 会阻止语法异常干扰输入。

当表格使用排序器时,用户看到的数据可能与数据模型指定的顺序不同,并且可能不包括数据模型指定的所有行。用户实际看到的数据称为视图,并具有其自己的坐标系。 提供了一些方法,用于将模型坐标转换为视图坐标 - 和 ,以及将视图坐标转换为模型坐标 - 和 。

下面的示例将本节讨论的思想汇集在一起。 对 进行了少量的更改。其中包括本节前面提到的代码片段,为主表提供了一个排序器,并使用文本字段提供过滤正则表达式。下面的屏幕截图显示了在进行任何排序或过滤之前的 。请注意,模型中的第3行仍然与视图中的第3行相同:

未排序的 TableFilterDemo

如果用户在第二列上点击两次,第四行将成为第一行——但仅在视图中如此:

第二列逆向排序的 TableFilterDemo

正如前面所提到的,用户在“Filter Text”文本字段中输入的文本定义了确定显示哪些行的过滤器。与排序一样,过滤也会导致视图坐标与模型坐标不一致:

进行过滤的 TableFilterDemo

以下是更新状态字段以反映当前选择的代码:

将下拉框设置为编辑器很简单,如下面的示例所示。粗体代码行设置了下拉框作为特定列的编辑器。

这里是使用组合框编辑器的示例图片:

使用组合框编辑器

上述代码来自。您可以运行(点击“Launch”按钮)使用(下载 JDK 7 或更高版本)。或者,如果您想要自己编译和运行示例,请参考示例索引。

启动 TableRenderDemo 示例

无论是为单个单元格列设置编辑器(使用的方法),还是为特定类型的数据设置编辑器(使用的方法),您都需要使用符合接口的参数来指定编辑器。幸运的是,类实现了这个接口,并提供了构造函数,让您可以指定一个作为编辑组件的、或。通常情况下,您不需要明确指定复选框作为编辑器,因为具有数据的列会自动使用复选框渲染器和编辑器。

如果您想要指定除文本字段、复选框或组合框以外的编辑器怎么办?由于不支持其他类型的组件,您需要做更多的工作。您需要创建一个实现接口的类。可以使用类作为一个很好的超类,它实现了的超接口,省去了为单元格编辑器实现必要的事件触发代码的麻烦。

您的单元格编辑器类需要至少定义两个方法——和。由要求的方法返回单元格的当前值。由要求的方法应该配置并返回您想要用作编辑器的组件。

这是一个带有对话框的表格图片,间接地作为单元格编辑器。当用户开始编辑“最喜欢的颜色”列中的单元格时,会出现一个按钮(真正的单元格编辑器),并弹出对话框,用户可以在对话框中选择不同的颜色。

单元格编辑器弹出对话框

您可以运行(点击“Launch”按钮)使用(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参考示例索引。

启动TableDialogEditDemo示例

这是从中提取的代码,实现了单元格编辑器。

如你所见,代码非常简单。唯一有点棘手的部分是在编辑器按钮的操作处理程序的末尾调用。如果没有这个调用,即使模态对话框不再可见,编辑器仍然保持活动状态。调用让表格知道它可以停用编辑器,让单元格再次由渲染器处理。

如果一个单元格的默认编辑器允许文本输入,如果单元格的类型指定为除或之外的其他类型,您将免费获得一些错误检查。错误检查是将输入的文本转换为正确类型的对象的副作用。

自动检查用户输入的字符串发生在默认编辑器尝试创建与单元格列关联的类的新实例时。默认编辑器使用以为参数的构造函数创建此实例。例如,在单元格类型为的列中,当用户输入"123"时,默认编辑器使用等效于的代码创建相应的。如果构造函数抛出异常,单元格的轮廓变为红色,并且拒绝让焦点移出单元格。如果您实现了一个用作列数据类型的类,如果您的类提供了一个以类型的单个参数作为参数的构造函数,您可以使用默认编辑器。

如果您喜欢将文本字段作为单元格的编辑器,但希望自定义它 - 例如更严格地检查用户输入的文本或在文本无效时以不同方式进行反应 - 您可以更改单元格编辑器以使用格式化文本字段。格式化文本字段可以在用户输入时连续检查值,或在用户指示输入结束后(例如按下Enter键)进行检查。

下面的代码摘自一个名为的演示,它设置了一个格式化文本字段作为编辑器,将所有整数值限制在0和100之间。您可以运行(点击Launch按钮),使用Java™ Web Start(下载JDK 7或更高版本)。或者,要编译和运行示例,请参阅示例索引。

启动TableFTFEditDemo示例

以下代码将格式化文本字段设置为包含类型数据的所有列的编辑器。

类是的子类,它使用而不是支持的。它通过首先设置格式化文本字段以使用整数格式并具有指定的最小和最大值来实现,使用如何使用格式化文本字段中描述的API。然后,它重写了的、和方法,添加了格式化文本字段所需的操作。

的重写在编辑器显示之前设置格式化文本字段的value属性(而不仅仅是它从继承的text属性)。的重写将单元格值保持为,而不是格式化文本字段的解析器往往返回的值。最后,重写允许您检查文本是否有效,可能阻止编辑器被关闭。如果文本无效,的实现会弹出一个对话框,让用户选择继续编辑或恢复到上一个好的值。源代码有点太长了,无法在此处包含,但您可以在中找到它。

为打印表格提供了简单的API。打印表格的最简单方法是调用没有参数的:

在普通的Swing应用程序上调用会弹出一个标准的打印对话框。(在无头应用程序上,表格将被简单打印。)返回值表示用户是否继续进行打印作业或取消了。 可能会抛出,这是一个;这就是为什么上面的示例使用了的原因。

提供了几个带有不同选项的方法重载。下面的代码来自

,演示了如何定义页面头部:

对于更复杂的打印应用程序,使用来获取一个用于表格的对象。有关的更多信息,请参阅课程,位于教程中。

此表列出了使用的示例以及这些示例的描述。

创建简单表格检测用户选择创建表格模型使用编辑器验证用户输入的文本使用下拉框作为编辑器

Sport

使用其他编辑器为单元格指定工具提示为列标题指定工具提示排序和筛选排序和过滤打印如何编写列表选择监听器

div border="1" summary="Information about examples">

  • 上一篇: 爬虫java 教程
  • 下一篇: java教程403
  • 版权声明


    相关文章:

  • 爬虫java 教程2025-03-16 11:50:03
  • java语句开发教程2025-03-16 11:50:03
  • java泛型教程2025-03-16 11:50:03
  • java完整教程2025-03-16 11:50:03
  • java425全套教程2025-03-16 11:50:03
  • java教程4032025-03-16 11:50:03
  • java词汇阅读教程2025-03-16 11:50:03
  • java高级学习教程2025-03-16 11:50:03
  • java switch教程2025-03-16 11:50:03
  • java拼图入门教程2025-03-16 11:50:03