表格是最常用的数据统计组件之一,是由多行和多列组成的二维表形式,在Swing中的JTable类实现表格。
javax.swing.JTable类创建的对象是一个表格,可以使用以下两种方式创建表格。(1)使用列名数组的数据数组创建表格,使用JTable类的构造方法可以根据指定的列名数组和数据数组创建表格,JTable(Object[][] rowData,Object[] columnNames)。(2)使用标题数组和数据数组创建表格,在JTable类中还提供了利用表格列名变量和表格数据向量创建表格的构造方法:JTable(Vector rowData,Vector columnNames)。
表格创建完成后,默认情况下通过双击表格中的单元格就可以对其进行编辑,如果不需要提供该功能,可以通过重写JTable类的isCellEditable(int row,int column)方法来实现。默认情况下该方法会返回boolean型值true,表示单元格可编辑,如果返回false则表示不可编辑。表格列的移动可以通过javax.swing.table.JTableHeader类setRecorderingAllowed(boolean recorderingAllowed)方法来实现,该方法设置表格是否支持重新排列功能,设置为false表示不支持重新排列功能,设置为true表示支持重新排列功能。通过JTable类getTableHeader()方法可以获得JTableHeader类的实例。
默认情况下单元格的内容靠左侧显示,如果需要单元格中的内容居中显示,可以通过重新JTable类的getDefaultRenderer(Class<?> columnClass)方法实现。DefaultTableCellRenderer类的setHorizontalAlignment(int alignment)方法的常用字段如表所示:
字段 | 说明 |
---|---|
DefaultTableCellRenderer.LEFT | 表格单元格内容左对齐显示 |
DefaultTableCellRenderer.CENTER | 表格单元格内容居中显示 |
DefaultTableCellRenderer.RIGHT | 表格单元格内容右对齐显示 |
方法 | 说明 |
---|---|
setRowHeight(int rowHeight) | 设置表格的行高,默认为16像素 |
setRowSelectionAllowed(boolean sa) | 设置是否允许选中表格行,默认为允许选中,设为false表示不允许选中 |
setSelectMode(int sum) | 设置表格行的选择模式 |
setSelectionBackground(Color bc) | 设置表格选中行的背景色 |
setSelectionForeground(Color fc) | 设置表格选中行的前景色(通常情况下为文字的颜色) |
setAutoResizeMode(int mode) | 设置表格自动调整模式 |
javax.swing.ListSelectionModel接口中用于设置选择模式的字段:
字段 | 说明 |
---|---|
SINGLE_SELECTION | 0:只允许选择一行 |
SINGLE_INTERVAL_SELECTION | 1:允许连续选择多行 |
MULTIPLE_INTERVAL_SELECTION | 2:可以随意选择多行 |
所谓表格的自自动调整模式,就是在调整表格某一列的宽度时,表格采用何种方式保持其总宽度不变。
字段 | 常量值 | 说明 |
---|---|---|
AUTO_RESIZE_OFF | 0 | 关闭自动调整功能,使用水平滚动条时的必要设置 |
AUTO_RESIZE_NEXT_COLUMN | 1 | 只调整其下一列的宽度 |
AUTO_RESIZE_SUBSEQUENT_COLUMNS | 2 | 按比例调整其后所有列的宽度,为默认设置 |
AUTO_RESIZE_LAST_COLUMN | 3 | 只调整最后一列的宽度 |
AUTO_RESIZE_ALL_COLUMNS | 4 | 按比例调整表格所有列的宽度 |
当调整表格所在窗体的宽度时,如果关闭了表格的自动调整功能,表格的总宽度仍保持不变;如果开启了表格的自动调整功能,表格按比例调整所有列的宽度至适合窗体的宽度。
用来创建表格的JTable类并不复杂存储表格中的数据,而是由表格模型负责存储,当利用JTable类直接创建表格时,只是将数据封装到了默认的表格模型中。
接口javax.swing.table.TableModel定义了一个表格模型,该模型提供了操作表格的方法。抽象类javax.swing.table.AbstractTableModel实现了TableModel接口的大部分方法,只有三个方法没有实现:public int getRowCount();public int getColumnCount();public Object getValueAt(int rowIndex,int columnIndex)。
通过集成AbstractTableModel类实现上面3个方法可以创建自己的表格模型类。javax.swing.table.DefaultTableModel类是由Swing提供的继承了AbstractTableModel类,并实现了上面3个抽象方法的表格模型类。
构造方法 | 说明 |
---|---|
DefaultTableModel() | 创建一个零行零列的表格模型 |
DefaultTableModel(int rowCount,int columnCount) | 创建一个rowCount行,columnCount列的表格模型 |
DefaultTableMode(Object[][] data,Object[] columnNames) | 按照数组中指定的数据和列名创建一个表格模型 |
DefaultTableModel(Vector data,Vector columnNames) | 按照向量中指定的数据和列名创建一个表格模型 |
表格模型创建完成之后,通过JTable类的构造方法JTable(TableModel dm)创建表格,并把表格模型设置为该构造方法的参数,就实现了利用表格模型创建表格。
通过JTable类的setRowSorter(RowSorter<? extends TableModel>sorter)方法可以为表格设置排序器。javax.swing.table.TableRowSorter类是Swing提供的一个排序器类,可以为表格设置排序器。为表格排序器设置表格模型可以通过两种方法来实现:一种方法是通过TableRowSorter类的构造方法TableRowSorter(TableModel model)创建排序器;另一种方法是通过TableRowSorter类的setModel(TableModel model)方法为排序器设置表格模型。
向表格模型中添加新的数据行有两种情况:一种情况是添加到表格模型的尾部,另一种情况是插入到表格模型的指定索引位置。
(1)添加到表格模型的尾部,可以通过addRow()方法完成,它的重载方法如下:addRow(Object[] rowData):将由数组封装的数据添加到表格模型的尾部;addRow(Vector rowData):将由向量封装的数据添加到表格模型的尾部。
(2)添加到表格模型的指定位置,可以通过insertRow()方法完成,它的重载方法为:insertRow(int row,Object[] rowData):将由数组封装的数据添加到表格模型的指定索引位置;insertRow(int row,Vector rowData):将由向量封装的数据添加到表格模型的指定索引位置。
表格模型的行索引和列索引都是从零开始的。
如果需要修改表格模型中某一单元格的数据,可以通过DefaultTableModel类的setValueAt(Object aValue,int row,int column)方法来完成,其中aValue为单元格修改后的值,row为单元格所在行的索引,column为单元格所在列的索引;可以通过DefaultTableModel类的getValue(int row,int column)方法获得表格模型中指定单元格的值,返回值类型为Object。
如果需要删除表格模型中的某一行数据,可以通过DefaultTableModel类的removeRow(int row)来完成。在删除表格模型中的数据时,每删除一行,其后所有行的索引值将相应减1,所以当连续删除多行时,需要注意对删除行的索引进行处理。
在处理与表格列有关的信息时,均需要在表格总列数的基础上减去固定列的数量。
为表格模型添加表格模型事件监听器,进行事件处理操作:void addTableModelListener(TableModelListener l);public void tableChanged(TableModelEvent e):TableModelEvent类提供的方法可以对表格事件进行处理。
方法 | 说明 |
---|---|
getColumn() | 返回表格模型中事件的列 |
getFirstRow() | 返回表格模型中第一个被更改的行 |
getLastRow() | 返回表格模型中最后一个被更改的行 |
getType() | 返回事件类型,该类型为INSERT、UPDATE和DELETE之一 |
字符 | 说明 |
---|---|
TableModelEvent.DELETE | 表示对表格模型中的行或列进行了删除操作 |
TableModelEvent.INSERT | 表示对表格模型中添加了新行或新列 |
TableModelEvent.UPDATE | 表示对表格模型中的现有数据进行了修改操作 |
除了数据模型发生变化会触发表格模型事件监听器以外,还可以通过AbstractTableModel类提供的方法来触发表格模型事件监听器。
方法 | 说明 |
---|---|
firstTableCellUpdated(int row,int column) | 通知所有监听器,已更新[row,column]处的单元格值 |
firstTableRowsDeleted(int firstRow,int lastRow) | 通知所有监听器,已删除范围在[firstRow,lastRow]的行 |
firstTableRowsInserted(int firstRow,int lastRow) | 通知所有监听器,已插入范围在[firstRow,lastRow]的行 |
firstTableRowsUpdateed(int firstRow,int lastRow) | 通知所有监听器,已更新范围在[firstRow,lastRow]的行 |
当使用AbstractTableModel类的方法触发表格模型事件监听器时,并不是真的对表格模型进行了添加、修改和删除等操作,只是通过这些方法来通知表格模型的所有监听器,并对事件进行响应处理,在事件响应代码中可对事件类型进行判断,使个事件类型分别实现不同的功能。
使用Swing中的javax.swing.JTree类可以创建树。
构造方法 | 说明 |
---|---|
JTree() | 创建一个默认的树 |
JTree(TreeNode root) | 根据指定根结点创建树 |
JTree(TreeModel newModel) | 根据指定树模型创建树 |
树组件不能显示滚动条,一般都与滚动面板一起使用。
javax.swing.tree.DefaultMutableTreeNode类实现了TreeNode接口,用来创建树的节点。一个树只能有一个父结点,可以有0个或多个子节点,默认情况下每个节点都允许有子节点,如果某个节点不需要有子节点,可以将其设置为不允许有子节点。
构造方法 | 说明 |
---|---|
DefaultMutableTreeNode() | 创建一个默认的节点,默认情况下允许有子节点 |
DefaultMultableTreeNode(Object userObject) | 创建一个具有指定标签的节点 |
DefaultMutableTreeNode(Object userObject,boolean allowsChildren) | 创建一个具有指定标签的节点,并且指定是否允许有子节点 |
利用DefaultMultableTreeNode类的add(MutableTreeNode newChild)方法可以为该结点添加子节点,该节点称为父结点,没有父结点的节点称为根节点。可以通过根节点利用JTree类的构造方法JTree(TreeNode root)直接创建树。
还可以使用JTree类和树模型创建树,javax.swing.tree.TreeModel接口定义了一个树模型,该模型提供了操作树的方法。在创建树时,可以先创建一个树模型TreeModel,然后再把树模型作为参数传递给树的构造方法JTree(TreeModel newModel)创建树。
javax.swing.tree.DefaultTreeModel类实现了TreeModel接口,该类仅提供了如下两个构造方法,所以在利用该类创建树模型时,必须指定树的根节点。(1)DefaultTreeModel(TreeNode root):创建一个采用默认方式判断节点是否为叶子结点的树模型。(2)DefaultTreeModel(TreeNode root,boolean asksAllowsChildren):创建一个采用指定方式判断节点是否为叶子结点的树模型。
由DefaultTreeModel类实现的树模型判断节点是否为叶子结点有两种方式:第一种方式:默认方式为如果节点不存在子节点则为叶子节点。第二种方式:根据节点是否允许有子节点进行判断只要不允许有子节点,则该结点就是叶子结点,如果允许有子节点,则不管该节点是否是有子节点,都是叶子节点,将第二个构造方法的入口参数asksAllowsChildren设置为true表示允许有子节点,设置为false表示不允许有子节点。
通过JTree类的构造方法JTree(TreeModel newModel)创建树,并把树模型设置为该构造方法的参数,就实现了利用树模型的创建树。
1.添加树节点:利用DefaultTreeModel类的insertNodeInto()方法。insertNodeInto(MutableTreeNode newChild,MutableTreeNode parent,int index).
2.修改树节点:DefaultTreeModel类的nodeChanged(TreeNode node)方法用来通知树模型某节点已经被修改,否则如果修改的是节点的用户对象,修改信息将不会同步到GUI界面,其中入口参数为被修改的节点对象。
3.删除树节点:DefaultTreeModel类的removeNodeFromParent(MutableTreeNode node)方法用来从树模型中删除指定节点node。树的根节点不允许删除。
使用JTree类创建树时,默认情况下显示树的根节点,但是不显示根节点手柄。如果希望在树的根节点前面也显示手柄,可以调用JTree类的setShowsRootHandles(boolean newValue)方法,并将入口参数设为true,这样树就会显示根节点手柄。可以调用JTree类的setRootVisible(boolean rootVisible)方法,并将入口参数设为false.
通过javax.swing.tree.DefaultTreeCellRenderer类的对象可以修改节点图标,通过JTree类的getCellRenderer()方法可以得到DefaulTreeCellRenderer类的对象,setLeafIcon(Icon newIcon)方法用来设置叶子节点的图标。setClosedIcon(Icon newIcon)用来设置节点处于折叠状态时采用的图标。setOpenIcon(Icon newIcon)用来设置节点处于展开状态时采用的图标。
创建树时,默认情况下会在树的节点之间绘制连接线。通过JTree类调用putClientProperty(Object key,Object value)方法可以设置连接线的绘制方式,此时需要将入口参数key设置为JTree.lineStyle。将入口参数value设置为None表示不绘制节点间的连接线,将入口参数value设置为Angled则表示绘制节点间的连接线。
通过JTree类调用putClientProperty(Object key,Object value)方法时,如果将入口参数key设置为JTree.lineStyle,将入口参数value设置为Horizontal表示绘制水平分栏线,绘制方式在仅在根节点和一级节点之间,或者是一级节点和一级节点之间。
默认情况下只有树的根节点是展开的,其他子节点均处于折叠状态。可以通过DefaultMutableTreeNode类的isLeaf()方法判断要展开的节点是否为叶子节点,如果不是叶子节点就可以通过DefaultMutableTreeNode类的getPath()方法获得根节点到此节点的路径,然后把路径作为javax.swing.tree.TreePath类构造方法TreePATH(Object[] path)的入口参数创建TreePath对象,并把该对象传递给JTree类的expandPath(TreePath path)方法实现节点的展开操作。
树的节点允许被选中和取消选中,通过捕获树节点的选择时间可以处理相应的操作。树的选择模式有3种,通过javax.swing.tree.TreeSelectionModel接口的对象可以设置树的选择模式,通过JTree类getSelectionModel()方法可以获得TreeSelectionModel接口的对象,然后通过TreeSelectionModel接口的setSelectionModel(int mode)方法设置选择模式。
静态常量 | 说明 |
---|---|
SINGLE_TREE_SELECTION | 1:只允许选中一个 |
CONTIGUOUS_TREE_SELECTION | 2:允许连续选中多个 |
DISCONTIGUOUS_TREE_SELECTION | 4:允许任意选中多个 |
当选中树节点和取消树节点的选中状态时,将发出TreeSelectionEvent事件,通过实现TreeSelectionListener接口可以捕获该事件。
TreePath类表示树节点的路径,即通过该类可以获得子节点所属的父结点,以及父结点所属的上级节点,直到树的根节点。
方法 | 说明 |
---|---|
getPath() | 以Object数组的形式返回该路径中所有节点的对象,在数组中的顺序按照从根节点到子节点的顺序 |
getLastPathComponent() | 获得路径中最后一个节点的对象 |
getPatentPath() | 获得路径中除了最后一个节点的路径 |
pathByAddingChild(Object child) | 获得向路径中添加指定节点后的路径 |
getPathCount() | 获得路径中包含节点的数量 |
getPathComponent(int element) | 获得路径中指定索引位置的节点对象 |
当展开和折叠树节点时,将发出TreeExpansionEvent事件,通过实现TreeWillExpangListener接口,可以在树节点展开和折叠之前捕获该事件。
Graphics类是所有图形上下文的抽象基类,它允许在应用程序在组件、图片对象上进行绘制。Graphics类封装了Java支持的基本绘图操作所需的状态信息。包括颜色、字体、画笔、文本、图像等。Graphics类提供了绘图常用的方法。可实现直线、矩形、多边形、椭圆、圆弧等形状和文本、图片的绘制操作,还可以设置绘图的颜色、字体等状态属性。
Graphics2D继承Graphics类,实现了功能更加强大的绘图操作的集合。Graphics绘图上下文在Java语言中负责组建、图像与图形的绘制,必须从目的地获取Graphics对象。方法为getGraphics()。
Swing的组件基本上都是使用Graphics2D类的实例对象进行界面绘制的。所以需要把获取的绘图上下文对象强制类型转换为Graphics2D类型。
使用Color类可以创建任何颜色的对象。绘图类可以使用setColor()方法设置当前颜色。设置绘图颜色之后,在进行绘图或者绘制文本,都会采用该颜色作为前景色。如果想绘制其他颜色的图形或文本,需要再次调用setColor()方法设置其他颜色。
在默认情况下,Graphics绘图类使用的画笔属性是粗细为1像素的正方形,而Java2D的Graphics2D类可以调用setStroke()方法设置笔画的属性。setStroke(Stroke stroke)方法必须接收一个Stroke接口的实现类作为参数,java.awt包中提供了BasicStroke类,它实现类Stroke接口,并且通过不同的构造方法创建不同笔画属性的对象。Java使用Font类封装了字体的大小、样式等属性。该类在java.awt包中定义,其构造方法可以指定字体的名称、大小和样式3个属性。设置绘图类的字体可以使用绘图类的setFont()方法。设置字体以后在图形的上下文中绘制的所有文字都使用该字体,除非再次设置其他字体。
Graphics2D类提供了drawString()方法,使用该方法可以实现图形上下文的文本绘制,从而实现绘制文字的功能。Font类的getStringBounds()方法可以获取字符串需要占据的边界大小。FontRenderContext类是正确测量文本所需的信息容器。
Java可以分别使用Graphics和Graphics2D绘制图形,Graphics类使用不同的方法实现不同图形的绘制,如drawLine()方法用于绘制直线、drawRect()方法用于绘制矩形,drawOval()方法用于绘制椭圆等。
要绘制指定形状的图形,需要先创建并初始化该图形类的对象,这些图形类必须是Shape接口的实现类。然后使用Graphics2D类的draw()方法绘制该图形对象或者使用fill()方法填充该图形对象。
使用drawInage()方法将图片资源显示到绘图上下文中,而且可以实现各种特效处理。drawImage()方法需要指定通知的图像观察者。
repaint()方法将调用paint()方法,实现组件或画板的重画功能。图像的旋转需要Graphics2D的rotate()方法,该方法将根据指定的弧度旋转图像。使用Graphics2D类提供的shear()方法可以设置绘图的倾斜方向,从而实现使图像倾斜的效果。