前面讲了JTale表头的基本属性设置和表头放置组件之后,表头的显示效果操作也就这么多了,更复杂的显示则是表头的合并,单行行合并、多行多列合并等.再说那个之前先看其余的一种情况:说是对表头的修改吧,其实代码中对JTable的表头的代码很少只有几句,但是效果的确是体现在表头上的.
先看图,一个基本的JTable:
这是最简单的JTable生成的,但是很多时候我们觉得列太多了,不想看到这么多,需要隐藏一部分,当然通过在JTable的Header上的右键菜单弹出可以让我们选择那个显示那个隐藏,然后通过,设置JtableHeader的宽度来实现隐藏显示是可以的,但是可能有这个问题,万一使用的人不知道右键呢?万一觉得效果不好呢?所以这里实现另外一种方法,放置一个左右的按钮在JtableHeader上,单击可以增加减少列,比较直观,效果如图:
再减少几列:
这个实现比较简单,主要是Border问题和Layout的问题,技术问题很少:
工程目录如下:
看看最终的图,想到什么?JscrollPanel.下面是JscrollPanel的结构样式:
我们其实就是在corner位置放置我们的两个左右迁移的按钮就可以了,这样我们首先使我们的JTable位于我们自定义的JscrollPanel上,这个ScrollPanel需要我们自己定制.
首先定制的是它的Layout, JscrollPanel使用的是ScrollPaneLayout,我们需要继承这个Layout,使我们在corner位置可以容纳下我们的迁移Button.
/**
*thelayoutthatScrollPanewithbuttoninit.
*/
publicclassMyScrollPaneLayoutextendsScrollPaneLayout {
首先是重写它的setVerticalScrollBarPolicy方法,保证Layout样式一直存在.
@Override
publicvoidsetVerticalScrollBarPolicy(intx) {
// Used to set the vertical
scroll bar policy
super.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
}
然后重写layoutContainer方法,布置它的滚动窗格:
@Override
publicvoidlayoutContainer(Container parent) {
然后就是计算位置了,首先计算子级垂直滚动条的窗体,
Rectangle vsbR =newRectangle(0, 0, 0, 0);
vsbR
=vsb.getBounds(vsbR);
接着计算子级列标题的窗体:
Rectangle colHeadR =newRectangle(0, 0, 0, 0);
colHeadR =colHead.getBounds(colHeadR);
colHeadR.width-= vsbR.width;
colHead.getBounds(colHeadR);
最后是计算右上角显示的组件的窗体:
Rectangle upperRightR =upperRight.getBounds();
upperRightR.x-= vsbR.width;
upperRightR.width+= vsbR.width+ 1;
upperRight.setBounds(upperRightR);
接下来的类是重写我们的JtableHeader
/**
*Thisistheobjectwhichmanagestheheaderoftable
*/
privateclassLimitedTableHeaderextendsJTableHeader
{
这个类比较简单,只是重写了方法,保证JtableHeader刷新时,左上角组件也刷新:
// actually, this is a not complete way. but easy one.
// you can see last column
painted wider, short time :)
// If you don't like this
kind cheap fake,
// you have to overwrite the
paint method in UI class.
@Override
publicvoidpaintComponent(Graphics g) {
super.paintComponent(g);
columnButtonPane.repaint();
}
然后就是JscrollPanel左上角的组件了,说它之前是一个特别简单的类,把它的图片绘制出来:
/**
*paintthemenuitemimage.
*/
publicclassArrowIconimplementsIcon, SwingConstants {
方法都很简单,实现Icon接口的方法,绘制一个箭头图片:
@Override
publicvoidpaintIcon(Component c, Graphics g,intx,inty) {
iconRenderer=newBasicArrowButton(direction);
iconRenderer.paintTriangle(g, x, y,size,direction,isEnabled);
}
然后是绘制图片宽和高:
/**
*geticonWidth.
*/
@Override
publicintgetIconWidth() {
switch(direction) {
caseNORTH:
caseSOUTH:
returniconSize;
caseEAST:
caseWEST:
returnsize;
}
returniconSize;
}
/**
*geticonheight.
*/
@Override
publicintgetIconHeight() {
switch(direction) {
caseNORTH:
caseSOUTH:
returnsize;
caseEAST:
caseWEST:
returniconSize;
}
returnsize;
}
接着就是JscrollPane左上角组件的绘制了:
/**
*createthebuttonpanelthatintableheader.
*/
publicclassColumnButtonPanelextendsJPanel {
先看它的属性:
/**thepaneintable.*/
privateJTabletable=null;
这个是需要出现隐藏列的JTable.
/**thetablecolumnmodel.*/
privateTableColumnModelcm=null;
这个是它们的列的实例.
/**showbutton.*/
privateJButtonrevealButton=null;
/**hidebutton.*/
privateJButtonhideButton=null;
这两个是隐藏和显示列的按钮
/**savecolumnstack.*/
privateStackstack=null;
最后这个是存储所有列的堆栈.
咱就是初始化了,它初始化了Layout和Border:
setLayout(newGridLayout(1, 2));
setBorder(newLinesBorder(SystemColor.controlShadow,newInsets(0, 1, 0,
0)));
然后初始化属性:
stack=newStack();
table= header.getTable();
cm=table.getColumnModel();
创建两个按钮:
JButton button =newJButton();
// set icon.
button.setIcon(newArrowIcon(iconHeight, direction,true));
button.setDisabledIcon(newArrowIcon(iconHeight, direction,false));
设置按钮的事件和可用:
revealButton.addActionListener(newActionListener() {
publicvoidactionPerformed(ActionEvent e) {
TableColumn column = (TableColumn)stack.pop();
cm.addColumn(column);
if(stack.empty()) {
revealButton.setEnabled(false);
}
hideButton.setEnabled(true);
table.sizeColumnsToFit(-1);
}
});
if(1
{
hideButton.setEnabled(true);
}
JscrollPanel左上角的组件这样就创建完成了.
其实还有一个类,主要是绘制左上角组件的边框
/**
*Aclassthatimplementsanemptyborderwithnosize.
*/
publicclassLinesBorderextendsAbstractBorderimplementsSwingConstants {
它重写paintBorder方法、getBorderInsets、isBorderOpaque、getBorderInset
方法,通过边框和偏移计算最终的Border,参考Border的那个专题就可以了.
最后就是我们的MyScrollPane了,它继承JscrollPane.只要我们创立JTable时使用它,就可以使JTableHeader可以出现隐藏按钮:
/**
*Providesascrollableviewofalightweightcomponent.
*/
publicclassMyScrollPaneextendsJScrollPane {
看它的构造函数:
publicMyScrollPane(JTable table) {
先创建自己的JTableHeader,替换JTable原有的Header:
// set new header.
LimitedTableHeader header =newLimitedTableHeader(cm);
table.setTableHeader(header);
创建左上角组件,放置:
columnButtonPane=newColumnButtonPanel(header);
setCorner(UPPER_RIGHT_CORNER,columnButtonPane);
setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
最后是设置Layout:
// set layout.
MyScrollPaneLayout layout =newMyScrollPaneLayout();
setLayout(layout);
layout.syncWithScrollPane(this);
到此位置,创建JTableHeader显示隐藏按钮的所有代码就完成了,说是对JTableHeader的操作,倒不如说是在做JscrollPanel的重写.使用也很简单,当我们创建JTable的Panel时,原本使用
JScrollPane pane
= new JScrollPane(table);
现在使用
MyScrollPane
pane =newMyScrollPane(table);就可以了,其它的都不会变.