本來今天想寫JTable的單元格合并的,但是突然想到明天早上要趕飛機(jī)去參加大學(xué)同學(xué)的婚禮,可能時間會不夠,所以寫JTableHeader了,還簡單點.
前面已經(jīng)把JTable的單元格的操作已經(jīng)講的差不多了,現(xiàn)在說一下JTableHeader,其實JTableHeader和JTable的單元格很類似,也可以實現(xiàn)Renderer和Editor.但是JTableHeader的UI還是比較復(fù)雜的,設(shè)置也和JTable的單元格是不一樣的,所以很多特殊效果是實現(xiàn)不了的,比如鼠標(biāo)的進(jìn)入和離開的渲染(有知道的可以教教我,這個效果我實驗了好久,都不好用.)等,當(dāng)然很多時候?qū)τ?/span>JTableHeader來說,根本不需要實現(xiàn)復(fù)雜的效果,這里我們只介紹簡單的效果.
首先是JTableHeader的鼠標(biāo)事件,然后是JTableHeader上面放置Java的組件,然后是JTableHeader的合并和拆分例子.當(dāng)然對于JTableHeader來說還有tooltip提示以及排序過濾等,這些就不夾雜在這里講了,單獨開個專題:
先看最普通的JTableHeader的鼠標(biāo)事件,如圖:
實現(xiàn)很簡單,增加JTableHeader的鼠標(biāo)監(jiān)聽就可以了:
//add jtable header
listener
table.getTableHeader().addMouseListener(new MouseListener() {
然后判斷監(jiān)聽里觸發(fā)事件的是不是JTableHeader:
@Override
publicvoid mouseClicked(MouseEvent e) {
if (e.getSource() instanceof JTableHeader) {
if (SwingUtilities.isRightMouseButton(e)
然后在下面寫JTableHeader上的鼠標(biāo)右鍵事件就可以了,還有就是一些基本屬性,比如背景色、前景色、字體、寬度等,直接使用table.getTableHeader().setXXX就可以了.
接下里和JTable的單元格很類似,也是Renderer和Editor,就不全說了,參考JTable的單元格的例子就可以了,這兒先講個最簡單的Renderer:
實現(xiàn)效果如題,把JTableHeader換為JButton效果:
只需要實現(xiàn)TableCellRenderer接口就可以了:
publicclass MyHeaderButtonRenderer extends JButton implements
TableCellRenderer {
然后實現(xiàn)接口的方法:
@Override
public Component
getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
設(shè)置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());
然后比較重要的是設(shè)置JTableHeader高度的:
// set
height.
if (headerHeight != 0) {
setPreferredSize(new
Dimension(getWidth(), headerHeight));
} else {
setPreferredSize(new
Dimension(getWidth(), getHeight()));
}
然后我們需要提供一個方法給外部來設(shè)置高度:
/**
*settableheaderheight.
*/
publicvoid setHeight(int headerheight) {
headerHeight = headerheight;
}
只需要注意這一點,但我們直接使用Java提供的JTableHeader的setSize來設(shè)置的時候,表面是沒有問題的,但是當(dāng)我們拖動ScrollBar的時候可能出現(xiàn)繪制重疊的問題,這就是因為我們設(shè)置的View和UI不同步造成的,我們需要在Rnederer里設(shè)置,它是最后加載和渲染的,就不會出現(xiàn)繪制重疊的問題了.
還有一個例子,當(dāng)JTableHeader的列字?jǐn)?shù)太多時,需要分行顯示,在晚上見有人使用JtextArea來實現(xiàn),這樣既可以自動換行,但是存在一個簡單問題就是編輯效果不好處理,這里我用另外一種方法實現(xiàn),使用Jlist,可以實現(xiàn)多行了,當(dāng)然由此也可以實現(xiàn)自定義的組件,比如一個JPanel,在它上面可以放置其它組件的集合.
先看看效果:
這個和JButton是一樣的,繼承JList實現(xiàn)TableCellRenderer就可以了,設(shè)置一些Jlist的屬性:
publicclass MyHeaderListRenderer extends JList implements
TableCellRenderer {
設(shè)置屬性:
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);
然后實現(xiàn)TableCellRenderer的方法:
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int column) {
在里面設(shè)置
setListData(vector);
就完成了,使用和前面一樣:
TableCellRenderer
renderer = new MyHeaderListRenderer();
Enumeration<?> enumTemp =
table.getColumnModel().getColumns();
while (enumTemp.hasMoreElements()) {
((TableColumn) enumTemp.nextElement()).setHeaderRenderer(renderer);
}
本來不想寫這個例子的,但是為了放置某些看到人以為JTableHeader只能反正單個的類似Jbutton、JLabel這樣的組件,所以做了個JList上去,從簡單到復(fù)雜甚至你放個JTable上去也可以的,當(dāng)然要看你的需要了.
至于Editor的例子,和Rnederer的例子很相似,實現(xiàn)TableCellEditor接口,然后設(shè)置JTableHeader的setHeaderEditor就可以了,就不再寫了,參考JTable的單元格的Editor就可以.
最后再寫給Renderer和Editor混合的例子,和前面講的JTable的單元格一樣,也存在事件的問題和顯示的問題,如果不但需要顯示,還需要編輯的呈現(xiàn),必須同時設(shè)置Renderer和Editor.
先看效果:
它實現(xiàn)簡單的效果很簡單,只需要實現(xiàn)JCombobox類型的Renderer和Editor.就可以了:
先看Renderer:
publicclass MyHeaderComboxRenderer extends JComboBox implements
TableCellRenderer, MouseListener {
需要繼承JComboBox,實現(xiàn)TableCellRenderer接口,另外實現(xiàn)MouseListener接口的目的是我們鼠標(biāo)點擊時希望觸發(fā)的是JCombobox的PopUp事件,而不是JTableHeader的編輯事件.
構(gòu)造函數(shù)里我們添加JCombobox的Item:
public MyHeaderComboxRenderer(String[] items) {
for (int i = 0; i < items.length; i++) {
addItem(items[i]);
}
}
然后是實現(xiàn)TableCellRenderer的方法,設(shè)置屬性,和前面JButton基本一致:
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setBorder(border);
combox.setSelectedItem((value == null) ? "" : value.toString());
其它的設(shè)置背景色和字體、高度的參考JButton那個Renderer就可以了.
最后是處理鼠標(biāo)事件,如果不處理的話可能有這種情況出現(xiàn),沒有彈出JCombobox而進(jìn)入了單元格的編輯狀態(tài):
這當(dāng)然不是我們愿意見到的,所以自己處理一下鼠標(biāo)點擊:
/**
*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就算完成了,當(dāng)然實際應(yīng)用中如果你只是這么簡單的設(shè)置的話可
能會有繪制和刷新的問題,尤其是JTable頻繁更新的時候,這時候你需要重寫JTableHeader
的UI和JTableHeader,如下所示:
publicclass MyGroupTableHeaderUI extends BasicTableHeaderUI {
publicclass MyTableHeader extends JTableHeader implements
CellEditorListener {
甚至需要的時候TableColumn也要重寫:
publicclass MyTableColumn extends TableColumn {
這里就不詳細(xì)介紹這個了,一是一般用不到,而是下個專題介紹JTableHeader的合并和拆分
的時候,這些類都會被重寫,如果你真的需要重寫這些類的時候,參考那個JTableHeader的合
并的例子就可以了.