表格(表头放置组件)
本来今天想写JTable的单元格合并的,但是突然想到明天早上要赶飞机去参加大学同学的婚礼,可能时间会不够,所以写JTableHeader了,还简单点.
前面已经把JTable的单元格的操作已经讲的差不多了,现在说一下JTableHeader,其实JTableHeader和JTable的单元格很类似,也可以实现Renderer和Editor.但是JTableHeader的UI还是比较复杂的,设置也和JTable的单元格是不一样的,所以很多特殊效果是实现不了的,比如鼠标的进入和离开的渲染(有知道的可以教教我,这个效果我实验了好久,都不好用.)等,当然很多时候对于JTableHeader来说,根本不需要实现复杂的效果,这里我们只介绍简单的效果.
首先是JTableHeader的鼠标事件,然后是JTableHeader上面放置Java的组件,然后是JTableHeader的合并和拆分例子.当然对于JTableHeader来说还有tooltip提示以及排序过滤等,这些就不夹杂在这里讲了,单独开个专题:
先看最普通的JTableHeader的鼠标事件,如图:
实现很简单,增加JTableHeader的鼠标监听就可以了:
//add jtable header listener
table.getTableHeader().addMouseListener(new MouseListener() {
然后判断监听里触发事件的是不是JTableHeader:
@Override
publicvoid mouseClicked(MouseEvent e) {
if (e.getSource() instanceof JTableHeader) {
if (SwingUtilities.isRightMouseButton(e)
然后在下面写JTableHeader上的鼠标右键事件就可以了,还有就是一些基本属性,比如背景色、前景色、字体、宽度等,直接使用table.getTableHeader().setXXX就可以了.
接下里和JTable的单元格很类似,也是Renderer和Editor,就不全说了,参考JTable的单元格的例子就可以了,这儿先讲个最简单的Renderer:
实现效果如题,把JTableHeader换为JButton效果:
只需要实现TableCellRenderer接口就可以了:
publicclass MyHeaderButtonRenderer extends JButton implements
TableCellRenderer {
然后实现接口的方法:
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
设置JButton的属性:
Color fgColor = null;
Color bgColor = null;
if (hasFocus) {
fgColor = UIManager.getColor("TableHeader.focusCellForeground");
bgColor = UIManager.getColor("TableHeader.focusCellBackground");
}
if (fgColor == null) {
fgColor = header.getForeground();
}
if (bgColor == null) {
bgColor = header.getBackground();
}
setForeground(fgColor);
setBackground(bgColor);
button.setText((value == null) ? "" : value.toString());
然后比较重要的是设置JTableHeader高度的:
// set height.
if (headerHeight != 0) {
setPreferredSize(new Dimension(getWidth(), headerHeight));
} else {
setPreferredSize(new Dimension(getWidth(), getHeight()));
}
然后我们需要提供一个方法给外部来设置高度:
/**
*settableheaderheight.
*/
publicvoid setHeight(int headerheight) {
headerHeight = headerheight;
}
只需要注意这一点,但我们直接使用Java提供的JTableHeader的setSize来设置的时候,表面是没有问题的,但是当我们拖动ScrollBar的时候可能出现绘制重叠的问题,这就是因为我们设置的View和UI不同步造成的,我们需要在Rnederer里设置,它是最后加载和渲染的,就不会出现绘制重叠的问题了.
还有一个例子,当JTableHeader的列字数太多时,需要分行显示,在晚上见有人使用JtextArea来实现,这样既可以自动换行,但是存在一个简单问题就是编辑效果不好处理,这里我用另外一种方法实现,使用Jlist,可以实现多行了,当然由此也可以实现自定义的组件,比如一个JPanel,在它上面可以放置其它组件的集合.
先看看效果:
这个和JButton是一样的,继承JList实现TableCellRenderer就可以了,设置一些Jlist的属性:
publicclass MyHeaderListRenderer extends JList implements TableCellRenderer {
设置属性:
setForeground(UIManager.getColor("TableHeader.foreground"));
setBackground(UIManager.getColor("TableHeader.background"));
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
ListCellRenderer renderer = getCellRenderer();
((JLabel) renderer).setHorizontalAlignment(JLabel.CENTER);
setCellRenderer(renderer);
然后实现TableCellRenderer的方法:
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
在里面设置
setListData(vector);
就完成了,使用和前面一样:
TableCellRenderer renderer = new MyHeaderListRenderer();
Enumeration<?> enumTemp = table.getColumnModel().getColumns();
while (enumTemp.hasMoreElements()) {
((TableColumn) enumTemp.nextElement()).setHeaderRenderer(renderer);
}
本来不想写这个例子的,但是为了放置某些看到人以为JTableHeader只能反正单个的类似Jbutton、JLabel这样的组件,所以做了个JList上去,从简单到复杂甚至你放个JTable上去也可以的,当然要看你的需要了.
至于Editor的例子,和Rnederer的例子很相似,实现TableCellEditor接口,然后设置JTableHeader的setHeaderEditor就可以了,就不再写了,参考JTable的单元格的Editor就可以.
最后再写给Renderer和Editor混合的例子,和前面讲的JTable的单元格一样,也存在事件的问题和显示的问题,如果不但需要显示,还需要编辑的呈现,必须同时设置Renderer和Editor.
先看效果:
它实现简单的效果很简单,只需要实现JCombobox类型的Renderer和Editor.就可以了:
先看Renderer:
publicclass MyHeaderComboxRenderer extends JComboBox implements
TableCellRenderer, MouseListener {
需要继承JComboBox,实现TableCellRenderer接口,另外实现MouseListener接口的目的是我们鼠标点击时希望触发的是JCombobox的PopUp事件,而不是JTableHeader的编辑事件.
构造函数里我们添加JCombobox的Item:
public MyHeaderComboxRenderer(String[] items) {
for (int i = 0; i < items.length; i++) {
addItem(items[i]);
}
}
然后是实现TableCellRenderer的方法,设置属性,和前面JButton基本一致:
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setBorder(border);
combox.setSelectedItem((value == null) ? "" : value.toString());
其它的设置背景色和字体、高度的参考JButton那个Renderer就可以了.
最后是处理鼠标事件,如果不处理的话可能有这种情况出现,没有弹出JCombobox而进入了单元格的编辑状态:
这当然不是我们愿意见到的,所以自己处理一下鼠标点击:
/**
*Invokedwhenamousebuttonhasbeenpressedonacomponent.
*/
publicvoid mouseClicked(MouseEvent e) {
this.firePopupMenuWillBecomeVisible();
}
至于Editor我们使用Sun提供给我们的就可以了,
new DefaultCellEditor(combox)
最后就是使用了,
String[] items = { "首选项", "次选项", "末选项" };
TableCellRenderer renderer = new MyHeaderComboxRenderer(items);
table.getColumnModel().getColumn(1).setHeaderValue(combo.getItemAt(0));
table.getColumnModel().getColumn(1).setHeaderRenderer(renderer);
table.getColumnModel().getColumn(1).setHeaderEditor(new DefaultCellEditor(combo));
到这里,基本的JTableHeader就算完成了,当然实际应用中如果你只是这么简单的设置的话可
能会有绘制和刷新的问题,尤其是JTable频繁更新的时候,这时候你需要重写JTableHeader
的UI和JTableHeader,如下所示:
publicclass MyGroupTableHeaderUI extends BasicTableHeaderUI {
publicclass MyTableHeader extends JTableHeader implements CellEditorListener {
甚至需要的时候TableColumn也要重写:
publicclass MyTableColumn extends TableColumn {
这里就不详细介绍这个了,一是一般用不到,而是下个专题介绍JTableHeader的合并和拆分
的时候,这些类都会被重写,如果你真的需要重写这些类的时候,参考那个JTableHeader的合
并的例子就可以了.