相比JList,JTable显然要复杂很多。JTabel同样继承了java一贯的设计风格,将数据模型与表格的绘制分离。即有默认的样式,也提供了很多接口。这不仅使Java的表格设计思路清晰,而且几乎所有的个性化需要也可以得到满足。
缺点是:Java库中封装了过多的方法,为了使其尽可能通俗易懂,方法名和常量名非常长,这让Java代码看起来十分啰嗦,并不优美。但这在强大的IDE中可以用代码提示功能解决。
1.根据构造方法创建JTabel;可以传表的内容(二位数组),和表头(一维数组)
下面是我校的小图丁志愿者录取工作的名单表,名字瞎掰的。
class JTabelFrame extends JFrame
{
private String[] libVol= {
"姓名","学号","联系方式","志愿楼层","时间段"};
private Object[][] text= {
//名字纯属瞎掰
{
"楚寒冰", "07190221" ,"18602511184", "二东,二西,七西,七东" ,"周六1,周六3,周日1,周三3"},
{
"云天明", "12180243","18602511185","二东,二西,七东,七西","周二3,周四3,周日3"},
{
"陈欣"," 05181343"," 18602511211"," 五东、五西、四东、四西、三东、三西 ","周一1、周二3、周四3"},
{
"郑语嫣"," 25190133"," 18602511228"," 二东,二西,七东,七西"," 周二2、周五2"}
{
"何碧","010223","18952249826","二东,七西","周二3,周六2"}
};
public JTabelFrame(String title)
{
super(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//应用JTable的构造方法JTabel(Object[][],Object[]);
*
JTable table=new JTable(text,libVol);
//设置列排列器,点击列头可对列排序
tabel.setAutoCreateRowSorter(true);
JPanel panel=new JPanel();
panel.add(new JScrollPane(table));
add(panel,BorderLayout.CENTER);
pack();
}
}
2.定制数据模型,单元格渲染器
与JList一样,Java支持自定义单元格渲染器和数据模型。在数据模型中可对单元格是否可编辑进行重写,如
public boolean isCellEditable(int r,int c)
{
return c==0||c==1||c==2||c==3;
}
单元格渲染器和JList过程一至,实现getTableCellRendererComponent方法后返回Component对象,用paintComponent方法绘制单元格,这里用到常用的字符串测量技术把字符串放在合适的位置
另外,用单元格编辑器还可以对单元格进行更深层次的操作,比如添加组合框,事件等,这比较复杂,可以参考API文档和《Java核心技术》。
给一个例子:
package JTable;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.sql.Date;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
public class IdolTabel {
public static void main(String[] args)
{
EventQueue.invokeLater(()->{
IdolTableFrame frame=new IdolTableFrame("idol");
frame.setVisible(true);
});
}
}
class IdolTableFrame extends JFrame
{
private static final int DEFDAULT_WIDTH=700;
private static final int DEFDAULT_HEIGHT=500;
private JTable table;
public IdolTableFrame(String title)
{
super(title);
setSize(DEFDAULT_WIDTH, DEFDAULT_HEIGHT);
TableModel model=new IdolModel();
//添加数据模型
table=new JTable(model);
//设置默认排序器,点击表头可排序
table.setAutoCreateRowSorter(true);
table.setRowHeight(240);
table.setRowSelectionAllowed(false);
//添加单元格渲染器,对String类单元格渲染
table.setDefaultRenderer(String.class, new MyRenderer());
//对图片框单独设置
JComboBox<Integer> comb=new JComboBox<>();
for(int i=1;i<=40;i++)
comb.addItem(i);
table.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(comb));
table.getColumnModel().getColumn(4).setMinWidth(150);
table.getColumnModel().getColumn(4).setMinWidth(200);
add(new JScrollPane(table),BorderLayout.CENTER);
}
}
class MyRenderer extends JPanel implements TableCellRenderer
{
private static Color background;
private static String text;
private Font font=new Font(Font.SANS_SERIF,Font.PLAIN,17);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
this.text=(String) value;
background=isSelected?new Color(64, 0, 64):column%2==1?new Color(255, 255, 225):Color.WHITE;
if(hasFocus)
{
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
}else setBorder(null);
return this;
}
public void paintComponent(Graphics g)
{
g.setColor(background);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(new Color(165, 107, 77));
g.drawRect(0, 0, getWidth(), getHeight());
FontMetrics fm=g.getFontMetrics(font);
g.setColor(Color.BLACK);
g.drawString(text, (getWidth()-fm.stringWidth(text))/2, (getHeight()-fm.getHeight())/2);
}
}
class IdolModel extends AbstractTableModel
{
private String[] colnumNames= {
"姓名","国籍","年龄","出生日期","照片"};
private Object[][] cells= {
{
"白石麻衣","日本","22","1998.8.10",new ImageIcon(getClass().getResource("bsmy.jpg"))},
{
"Emma Watson","英国","30","1990.4.15",new ImageIcon(getClass().getResource("emma.jfif"))},
{
"文彩元","韩国","33","1986.11.13",new ImageIcon(getClass().getResource("wcy.jfif"))}
};
@Override
public int getRowCount() {
return cells.length;
}
@Override
public int getColumnCount() {
return cells[0].length;
}
public String getColumnName(int c)
{
return colnumNames[c];
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return cells[rowIndex][columnIndex];
}
public Class<?> getColumnClass(int c)
{
return cells[0][c].getClass();
}
public boolean isCellEditable(int r,int c)
{
return c==0||c==1||c==2||c==3;
}
}
图片如下:
Java的Swing组件功能十分强大,而且设计起来并不复杂,完成定制只需实现相应接口。