天天看點

java swing 表格控件_java swing 開發 -JTable

最近利用空閑時間自己琢磨了一下java swing 程式設計,其實在從事javaweb之前我一直向往的就是java swing 開發,不知道為什麼可能當時覺得Windows上的exe程式很是神奇,關于windows上制作exe我之前也有介紹

java swing開發都是自己琢磨的,有的地方寫的不規範,不過大多都是網上借鑒的,應該不算離譜的。今天看了看自己的java swing的程式,感覺寫的還不錯,但是發現現在遇到一個瓶頸問題,就是jtable的使用,由于一開始概念不了解現在jtable得重新寫,之前我吧資料放在jtable上了,但是真正開發的java swing資料都是放在TableModel上的。下面就Jtable的使用,好好整理了一番,途中參考的文章我都會放在下面列出,讀者可以自己參考

JTable結構梳理

JTable=TableHeader+TableColumn

顧名思義我們知道表格是由表頭和表列組成的,這兩個都是單獨的控件。但是JTable中如果想讓表頭顯示僅僅将JTable加入Jpanel或者Jframe中是不行的,我這裡提供兩種方式實作

1、分别将TableHeader和TableColumn加入控件中單獨的顯示,這種情況不常見

2、先将JTable加入jscrollpane(滾動條)中,然後在将滾動條加入到對應的控件中(Jpanel或者是Jframe).java swing 開發中加入滾動條是很常見的操作,是以這種方式的加入表格還是很推薦的。

table = new JTable(data, columnNames);

table.setBackground(Color.gray);

table.setPreferredScrollableViewportSize(new Dimension(800, 100));

table.setFillsViewportHeight(false);

pane = new JScrollPane(table);

this.add(pane);

上面的代碼就是簡單的實作将表格以顯示表頭的方式加入到jframe中顯示。其中我們能夠看到多了幾個設定,setPreferredScrollableViewportSize可有可無的,無所謂,但是setFillsViewportHeight是設定表格在縱向上的鋪展情況,什麼意思呢,如果這裡設定為true則表格就會在縱向上鋪滿jframe,如果是false,表格則會按照自己的實際占地面積顯示,不會多占的。

java swing 表格控件_java swing 開發 -JTable
java swing 表格控件_java swing 開發 -JTable

JTable資料顯示

java swing中jtable是mvc形式的,是以jtable僅僅是資料的顯示,而真正和資料綁定的卻是TableModel這個接口,我們先看看這個接口的内部有哪些方法,這樣我們心裡才有個底。

java swing 表格控件_java swing 開發 -JTable

衆多周知jtable中常用的兩種構造函數一個是數組另一個是vector,這兩種構造函數中都是采用了匿名内部類實作tablemodel,前者用的是AbstractTableModel,後者是DefaultTableModel。而DefaultTableModel有事繼承了AbstractTableModel,是以我們平時如果自定義model的話,都會去繼承AbstractTableModel的。我們在去源碼裡可以看見

java swing 表格控件_java swing 開發 -JTable

,我們會發現AbstractTableModel有事繼承TableModel這個接口的。是以我們的所有方法都是源于他。

我們觀察AbstractTableModel源碼中注釋發現,我們隻需要繼承AbstractTableModel類後隻需要實作三個必須的方法,其他的方法根據需要實作

public int getRowCount();

public int getColumnCount();

public Object getValueAt(int row, int column);

java swing 表格控件_java swing 開發 -JTable

這三個方法的作用就是通過model高數jtable我需要一個幾行幾列的表格,至于每個單元格顯示的内容就是通過getValueAt這個方法實作的,到這裡我們就實作了,jtable的model自定義顯示。

//表格的列,需要使用者自己設定好

private int column;

//待加載的資料 資料每行的列數和上面要統一好

private List list;

public MyTableModel(List list,int column){

this.column=column;

this.list=list;

}

@Override

public int getRowCount() {

// TODO Auto-generated method stub

return list.size();

}

@Override

public int getColumnCount() {

// TODO Auto-generated method stub

return this.column;

}

@Override

public Object getValueAt(int rowIndex, int columnIndex) {

// TODO Auto-generated method stub

return list.get(rowIndex).toString()+"_"+rowIndex+"_"+columnIndex;

}

上面的代碼就是我的model類,裡面有個穿list的構造函數,然後我們看看我們的三個方法就起到了作用了。然後在getValueAt擷取指定行數的list的指定内容就可以填充到表格上了。

jtable資料的CURD

在上面我們繼承了AbstractTableModel,這裡面有對資料的CURD操作

java swing 表格控件_java swing 開發 -JTable

if("增加".equals(command)){

List data = getData();

data.add("test5");

data.add("test6");

datamModel.setList(data);

// datamModel.fireTableStructureChanged();

datamModel.fireTableRowsInserted(5,6);

}else if("删除".equals(command)){

List data = getData();

data.remove(2);

datamModel.setList(data);

datamModel.fireTableRowsDeleted(1, 1);

}else if("更新".equals(command)){

List data = getData();

data.set(0, "test0_1");

datamModel.setList(data);

datamModel.fireTableRowsUpdated(0, 5);

}

裡面都會帶有參數比如datamModel.fireTableRowsUpdated(0, 5);的意思是通州JTable顯示子產品去重新整理從1-6行的所有資料,是以說比如你更新了第一行的資料,而你用的兩個參數是1,4.那麼恭喜你,你的更新JTable無法實作,因為他隻更新從第二行開始到第五行的資料。其他的方法參數和他一樣。通過上面就可以輕松實作JTable的CURD操作。

JTable控件顯示法

相信有的朋友遇到過,表格中需要顯示CheckBox、button等控件的,但是我們發現我們定義的控件在表格上顯示成了控件對應的類的字元串了,這又是為什麼呢。下面請随我一起看看源碼吧:

public Class> getColumnClass(int columnIndex) {

return Object.class;

}

源碼中AbstractTableModel的getColumnClass的方法是JTable決定顯示類型的主要依據,源碼中傳回的預設是object.class,這就意味着我們在jtable是true或false或其他類,在這裡都會傳回object.class,那麼jtable就會采用預設的渲染方式去渲染表格,預設的就是所有都是字元串形式展示,這個設定在JTable中的源碼中

protected void createDefaultRenderers() {

defaultRenderersByColumnClass = new UIDefaults(8, 0.75f);

// Objects

setLazyRenderer(Object.class, "javax.swing.table.DefaultTableCellRenderer$UIResource");

// Numbers

setLazyRenderer(Number.class, "javax.swing.JTable$NumberRenderer");

// Doubles and Floats

setLazyRenderer(Float.class, "javax.swing.JTable$DoubleRenderer");

setLazyRenderer(Double.class, "javax.swing.JTable$DoubleRenderer");

// Dates

setLazyRenderer(Date.class, "javax.swing.JTable$DateRenderer");

// Icons and ImageIcons

setLazyRenderer(Icon.class, "javax.swing.JTable$IconRenderer");

setLazyRenderer(ImageIcon.class, "javax.swing.JTable$IconRenderer");

// Booleans

setLazyRenderer(Boolean.class, "javax.swing.JTable$BooleanRenderer");

}

源碼中就有渲染器專門處理bool類型的,那麼我們隻需要在getColumnClass進行處理就行了,在我們的bool的單元格傳回bool類JTable就會采用bool類型的渲染器了。

return getValueAt(0, c).getClass();

這樣我們就可以顯示一些其他的控件了,還有一些比如每行都需要一行按鈕來實作修改改行的功能,這些按鈕正常我們不需要再資料中添加(避免資料過于龐大),如果不在資料中添加那麼我們的getClass方法就起不到作用,這個用到了下面的知識來解決

JTable渲染和編輯

這種呢其實就是上面的getClass底層的實作方式,JTable中源碼我們上面可以看出JTable通過傳回的不同的類來調用不同的渲染器,現在我們不通過傳回類的方式來渲染,而是自己定義一個渲染器,然後通過JTable提供的方法設定用該渲染器渲染該單元格!

setCellEditor和setCellRenderer

大家可以觀察源碼,在JTable的編輯器中AbstractCellEditor是基礎的抽象類,他繼承了CellEditor,怎麼樣熟悉嗎,這個不就是和AbstractTableModel 是一樣的嗎。但是這個類不能反回控件需要和TableCellEditor結合使用,或者我們隻是用另外一個基礎類DefaultCellEditor,

DefaultCellEditor和AbstractTableModel 有設麼差別呢,他們都是一樣實作了CellEditor接口,但是前者構造中隻能傳入控件,也就是說每日次實力隻能通過不同構造函數建構不同的控件,但是後者是抽象類,繼承的類可以自定義構造函數,這就友善我們夠贊多個不同的控件了,是以這兩個大家看情況使用。最後都是通過getTableCellEditorComponent這個函數将控件傳回出去。

設定完了編輯器,我們最終要是隻渲染器,就是JTable最終如何顯示的問題。和上面的那個一樣。繼承TableCellRenderer類,通過getTableCellRendererComponent方法傳回渲染成設麼控件,渲染的控件我們可以進行二次封裝。

調用如下 兩個參數就是通過上面兩個類構造的類

column.setCellEditor(editor);

column.setCellRenderer(renderer);