表格(表頭放置組件)
本來(lái)今天想寫JTable的單元格合并的,但是突然想到明天早上要趕飛機(jī)去參加大學(xué)同學(xué)的婚禮,可能時(shí)間會(huì)不夠,所以寫JTableHeader了,還簡(jiǎn)單點(diǎn).
前面已經(jīng)把JTable的單元格的操作已經(jīng)講的差不多了,現(xiàn)在說(shuō)一下JTableHeader,其實(shí)JTableHeader和JTable的單元格很類似,也可以實(shí)現(xiàn)Renderer和Editor.但是JTableHeader的UI還是比較復(fù)雜的,設(shè)置也和JTable的單元格是不一樣的,所以很多特殊效果是實(shí)現(xiàn)不了的,比如鼠標(biāo)的進(jìn)入和離開的渲染(有知道的可以教教我,這個(gè)效果我實(shí)驗(yàn)了好久,都不好用.)等,當(dāng)然很多時(shí)候?qū)τ?/span>JTableHeader來(lái)說(shuō),根本不需要實(shí)現(xiàn)復(fù)雜的效果,這里我們只介紹簡(jiǎn)單的效果.
首先是JTableHeader的鼠標(biāo)事件,然后是JTableHeader上面放置Java的組件,然后是JTableHeader的合并和拆分例子.當(dāng)然對(duì)于JTableHeader來(lái)說(shuō)還有tooltip提示以及排序過(guò)濾等,這些就不夾雜在這里講了,單獨(dú)開個(gè)專題:
先看最普通的JTableHeader的鼠標(biāo)事件,如圖:

實(shí)現(xiàn)很簡(jiǎ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,就不全說(shuō)了,參考JTable的單元格的例子就可以了,這兒先講個(gè)最簡(jiǎn)單的Renderer:
實(shí)現(xiàn)效果如題,把JTableHeader換為JButton效果:

只需要實(shí)現(xiàn)TableCellRenderer接口就可以了:
publicclass MyHeaderButtonRenderer extends JButton implements
TableCellRenderer {
然后實(shí)現(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()));
}
然后我們需要提供一個(gè)方法給外部來(lái)設(shè)置高度:
/**
*settableheaderheight.
*/
publicvoid setHeight(int headerheight) {
headerHeight = headerheight;
}
只需要注意這一點(diǎn),但我們直接使用Java提供的JTableHeader的setSize來(lái)設(shè)置的時(shí)候,表面是沒有問(wèn)題的,但是當(dāng)我們拖動(dòng)ScrollBar的時(shí)候可能出現(xiàn)繪制重疊的問(wèn)題,這就是因?yàn)槲覀冊(cè)O(shè)置的View和UI不同步造成的,我們需要在Rnederer里設(shè)置,它是最后加載和渲染的,就不會(huì)出現(xiàn)繪制重疊的問(wèn)題了.
還有一個(gè)例子,當(dāng)JTableHeader的列字?jǐn)?shù)太多時(shí),需要分行顯示,在晚上見有人使用JtextArea來(lái)實(shí)現(xiàn),這樣既可以自動(dòng)換行,但是存在一個(gè)簡(jiǎn)單問(wèn)題就是編輯效果不好處理,這里我用另外一種方法實(shí)現(xiàn),使用Jlist,可以實(shí)現(xiàn)多行了,當(dāng)然由此也可以實(shí)現(xiàn)自定義的組件,比如一個(gè)JPanel,在它上面可以放置其它組件的集合.
先看看效果:

這個(gè)和JButton是一樣的,繼承JList實(shí)現(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);
然后實(shí)現(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);
}
本來(lái)不想寫這個(gè)例子的,但是為了放置某些看到人以為JTableHeader只能反正單個(gè)的類似Jbutton、JLabel這樣的組件,所以做了個(gè)JList上去,從簡(jiǎn)單到復(fù)雜甚至你放個(gè)JTable上去也可以的,當(dāng)然要看你的需要了.
至于Editor的例子,和Rnederer的例子很相似,實(shí)現(xiàn)TableCellEditor接口,然后設(shè)置JTableHeader的setHeaderEditor就可以了,就不再寫了,參考JTable的單元格的Editor就可以.
最后再寫給Renderer和Editor混合的例子,和前面講的JTable的單元格一樣,也存在事件的問(wèn)題和顯示的問(wèn)題,如果不但需要顯示,還需要編輯的呈現(xiàn),必須同時(shí)設(shè)置Renderer和Editor.
先看效果:


它實(shí)現(xiàn)簡(jiǎn)單的效果很簡(jiǎn)單,只需要實(shí)現(xiàn)JCombobox類型的Renderer和Editor.就可以了:
先看Renderer:
publicclass MyHeaderComboxRenderer extends JComboBox implements
TableCellRenderer, MouseListener {
需要繼承JComboBox,實(shí)現(xiàn)TableCellRenderer接口,另外實(shí)現(xiàn)MouseListener接口的目的是我們鼠標(biāo)點(diǎn)擊時(shí)希望觸發(fā)的是JCombobox的PopUp事件,而不是JTableHeader的編輯事件.
構(gòu)造函數(shù)里我們添加JCombobox的Item:
public MyHeaderComboxRenderer(String[] items) {
for (int i = 0; i < items.length; i++) {
addItem(items[i]);
}
}
然后是實(shí)現(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那個(gè)Renderer就可以了.
最后是處理鼠標(biāo)事件,如果不處理的話可能有這種情況出現(xiàn),沒有彈出JCombobox而進(jìn)入了單元格的編輯狀態(tài):

這當(dāng)然不是我們?cè)敢庖姷降?/span>,所以自己處理一下鼠標(biāo)點(diǎn)擊:
/**
*Invokedwhenamousebuttonhasbeenpressedonacomponent.
*/
publicvoid mouseClicked(MouseEvent e) {
this.firePopupMenuWillBecomeVisible();
}
至于Editor我們使用Sun提供給我們的就可以了,
new DefaultCellEditor(combox)
最后就是使用了,
String[] items = { "首選項(xiàng)", "次選項(xiàng)", "末選項(xiàng)" };
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)然實(shí)際應(yīng)用中如果你只是這么簡(jiǎn)單的設(shè)置的話可
能會(huì)有繪制和刷新的問(wèn)題,尤其是JTable頻繁更新的時(shí)候,這時(shí)候你需要重寫JTableHeader
的UI和JTableHeader,如下所示:
publicclass MyGroupTableHeaderUI extends BasicTableHeaderUI {
publicclass MyTableHeader extends JTableHeader implements CellEditorListener {
甚至需要的時(shí)候TableColumn也要重寫:
publicclass MyTableColumn extends TableColumn {
這里就不詳細(xì)介紹這個(gè)了,一是一般用不到,而是下個(gè)專題介紹JTableHeader的合并和拆分
的時(shí)候,這些類都會(huì)被重寫,如果你真的需要重寫這些類的時(shí)候,參考那個(gè)JTableHeader的合
并的例子就可以了.
posted on 2010-04-08 20:36 zeyuphoenix 閱讀(4245) 評(píng)論(0) 編輯 收藏 所屬分類: JTable的使用