前面講了JTale表頭的基本屬性設(shè)置和表頭放置組件之后,表頭的顯示效果操作也就這么多了,更復(fù)雜的顯示則是表頭的合并,單行行合并、多行多列合并等.再說那個之前先看其余的一種情況:說是對表頭的修改吧,其實代碼中對JTable的表頭的代碼很少只有幾句,但是效果的確是體現(xiàn)在表頭上的.
先看圖,一個基本的JTable:
這是最簡單的JTable生成的,但是很多時候我們覺得列太多了,不想看到這么多,需要隱藏一部分,當(dāng)然通過在JTable的Header上的右鍵菜單彈出可以讓我們選擇那個顯示那個隱藏,然后通過,設(shè)置JtableHeader的寬度來實現(xiàn)隱藏顯示是可以的,但是可能有這個問題,萬一使用的人不知道右鍵呢?萬一覺得效果不好呢?所以這里實現(xiàn)另外一種方法,放置一個左右的按鈕在JtableHeader上,單擊可以增加減少列,比較直觀,效果如圖:
再減少幾列:
這個實現(xiàn)比較簡單,主要是Border問題和Layout的問題,技術(shù)問題很少:
工程目錄如下:
看看最終的圖,想到什么?JscrollPanel.下面是JscrollPanel的結(jié)構(gòu)樣式:
我們其實就是在corner位置放置我們的兩個左右遷移的按鈕就可以了,這樣我們首先使我們的JTable位于我們自定義的JscrollPanel上,這個ScrollPanel需要我們自己定制.
首先定制的是它的Layout, JscrollPanel使用的是ScrollPaneLayout,我們需要繼承這個Layout,使我們在corner位置可以容納下我們的遷移Button.
/**
*thelayoutthatScrollPanewithbuttoninit.
*/
publicclass MyScrollPaneLayout extends ScrollPaneLayout {
首先是重寫它的setVerticalScrollBarPolicy方法,保證Layout樣式一直存在.
@Override
publicvoid setVerticalScrollBarPolicy(int x) {
// Used to set the vertical
scroll bar policy
super.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
}
然后重寫layoutContainer方法,布置它的滾動窗格:
@Override
publicvoid
layoutContainer(Container parent) {
然后就是計算位置了,首先計算子級垂直滾動條的窗體,
Rectangle vsbR = new Rectangle(0, 0, 0, 0);
vsbR
= vsb.getBounds(vsbR);
接著計算子級列標(biāo)題的窗體:
Rectangle colHeadR = new Rectangle(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
*/
privateclass LimitedTableHeader
extends JTableHeader
{
這個類比較簡單,只是重寫了方法,保證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
publicvoid paintComponent(Graphics g) {
super.paintComponent(g);
columnButtonPane.repaint();
}
然后就是JscrollPanel左上角的組件了,說它之前是一個特別簡單的類,把它的圖片繪制出來:
/**
*paintthemenuitemimage.
*/
publicclass ArrowIcon implements Icon, SwingConstants {
方法都很簡單,實現(xiàn)Icon接口的方法,繪制一個箭頭圖片:
@Override
publicvoid paintIcon(Component c, Graphics g, int x, int y) {
iconRenderer = new
BasicArrowButton(direction);
iconRenderer.paintTriangle(g, x, y, size, direction, isEnabled);
}
然后是繪制圖片寬和高:
/**
*geticonWidth.
*/
@Override
publicint getIconWidth() {
switch (direction) {
caseNORTH:
caseSOUTH:
returniconSize;
caseEAST:
caseWEST:
returnsize;
}
returniconSize;
}
/**
*geticonheight.
*/
@Override
publicint getIconHeight() {
switch (direction) {
caseNORTH:
caseSOUTH:
returnsize;
caseEAST:
caseWEST:
returniconSize;
}
returnsize;
}
接著就是JscrollPane左上角組件的繪制了:
/**
*createthebuttonpanelthatintableheader.
*/
publicclass ColumnButtonPanel extends JPanel {
先看它的屬性:
/**thepaneintable.*/
private JTable table = null;
這個是需要出現(xiàn)隱藏列的JTable.
/**thetablecolumnmodel.*/
private TableColumnModel cm = null;
這個是它們的列的實例.
/**showbutton.*/
private JButton revealButton = null;
/**hidebutton.*/
private JButton hideButton = null;
這兩個是隱藏和顯示列的按鈕
/**savecolumnstack.*/
private
Stack<TableColumn> stack = null;
最后這個是存儲所有列的堆棧.
咱就是初始化了,它初始化了Layout和Border:
setLayout(new GridLayout(1, 2));
setBorder(new LinesBorder(SystemColor.controlShadow, new Insets(0, 1, 0,
0)));
然后初始化屬性:
stack = new Stack<TableColumn>();
table = header.getTable();
cm = table.getColumnModel();
創(chuàng)建兩個按鈕:
JButton button = new JButton();
// set icon.
button.setIcon(new ArrowIcon(iconHeight, direction, true));
button.setDisabledIcon(new ArrowIcon(iconHeight, direction, false));
設(shè)置按鈕的事件和可用:
revealButton.addActionListener(new ActionListener() {
publicvoid actionPerformed(ActionEvent e) {
TableColumn column = (TableColumn) stack.pop();
cm.addColumn(column);
if (stack.empty()) {
revealButton.setEnabled(false);
}
hideButton.setEnabled(true);
table.sizeColumnsToFit(-1);
}
});
if (1 < cm.getColumnCount())
{
hideButton.setEnabled(true);
}
JscrollPanel左上角的組件這樣就創(chuàng)建完成了.
其實還有一個類,主要是繪制左上角組件的邊框
/**
*Aclassthatimplementsanemptyborderwithnosize.
*/
publicclass LinesBorder extends AbstractBorder implements SwingConstants {
它重寫paintBorder方法、getBorderInsets、isBorderOpaque、getBorderInset
方法,通過邊框和偏移計算最終的Border,參考Border的那個專題就可以了.
最后就是我們的MyScrollPane了,它繼承JscrollPane.只要我們創(chuàng)立JTable時使用它,就可以使JTableHeader可以出現(xiàn)隱藏按鈕:
/**
*Providesascrollableviewofalightweightcomponent.
*/
publicclass MyScrollPane extends JScrollPane {
看它的構(gòu)造函數(shù):
public
MyScrollPane(JTable table) {
先創(chuàng)建自己的JTableHeader,替換JTable原有的Header:
// set new header.
LimitedTableHeader header = new LimitedTableHeader(cm);
table.setTableHeader(header);
創(chuàng)建左上角組件,放置:
columnButtonPane = new
ColumnButtonPanel(header);
setCorner(UPPER_RIGHT_CORNER, columnButtonPane);
setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
最后是設(shè)置Layout:
// set layout.
MyScrollPaneLayout layout = new MyScrollPaneLayout();
setLayout(layout);
layout.syncWithScrollPane(this);
到此位置,創(chuàng)建JTableHeader顯示隱藏按鈕的所有代碼就完成了,說是對JTableHeader的操作,倒不如說是在做JscrollPanel的重寫.使用也很簡單,當(dāng)我們創(chuàng)建JTable的Panel時,原本使用
JScrollPane pane
= new JScrollPane(table);
現(xiàn)在使用
MyScrollPane
pane = new MyScrollPane(table);
就可以了,其它的都不會變.