java swing項目桌面軟件仍是蠻香的,至少有了我本身的桌面軟件|Java 開發實戰

這是我參與更文挑戰的第5天,活動詳情查看: 更文挑戰java

本文正在參加「Java主題月 - Java 開發實戰」,詳情查看 活動連接web

最近利用空閒時間本身琢磨了一下java swing 編程,其實在從事javaweb以前我一直嚮往的就是java swing 開發,不知道爲何可能當時以爲Windows上的exe程序非常神奇,關於windows上製做exe我以前也有介紹編程

exe打包教程一windows

exe打包教程二數組

java swing開發都是本身琢磨的,有的地方寫的不規範,不過大多都是網上借鑑的,應該不算離譜的。markdown

今天看了看本身的java swing的程序,感受寫的還不錯,可是發現如今遇到一個瓶頸問題,就是jtable的使用,因爲一開始概念不理解如今jtable得從新寫,以前我吧數據放在jtable上了,可是真正開發的java swing數據都是放在TableModel上的。下面就Jtable的使用,好好整理了一番,途中參考的文章我都會放在下面列出,讀者能夠本身參考**mvc

JTable結構梳理

  • JTable=TableHeader+TableColumnless

  • 顧名思義咱們知道表格是由表頭和表列組成的,這兩個都是單獨的控件。可是JTable中若是想讓表頭顯示僅僅將JTable加入Jpanel或者Jframe中是不行的,我這裏提供兩種方式實現編輯器

  • 一、分別將TableHeader和TableColumn加入控件中單獨的顯示,這種狀況不常見ide

  • 二、先將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,表格則會按照本身的實際佔地面積顯示,不會多佔的。

這裏寫圖片描述

這裏寫圖片描述

JTable數據顯示

  • java swing中jtable是mvc形式的,因此jtable僅僅是數據的顯示,而真正和數據綁定的倒是TableModel這個接口,咱們先看看這個接口的內部有哪些方法,這樣咱們內心纔有個底。

這裏寫圖片描述

  • 衆多周知jtable中經常使用的兩種構造函數一個是數組另外一個是vector,這兩種構造函數中都是採用了匿名內部類實現tablemodel,前者用的是AbstractTableModel,後者是DefaultTableModel。而DefaultTableModel有事繼承了AbstractTableModel,因此咱們平時若是自定義model的話,都會去繼承AbstractTableModel的。咱們在去源碼裏能夠看見這裏寫圖片描述,咱們會發現AbstractTableModel有事繼承TableModel這個接口的。因此咱們的全部方法都是源於他。

  • 咱們觀察AbstractTableModel源碼中註釋發現,咱們只須要繼承AbstractTableModel類後只須要實現三個必須的方法,其餘的方法根據須要實現

public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);
複製代碼

這裏寫圖片描述

  • 這三個方法的做用就是經過model高數jtable我須要一個幾行幾列的表格,至於每一個單元格顯示的內容就是經過getValueAt這個方法實現的,到這裏咱們就實現了,jtable的model自定義顯示。
//表格的列,須要用戶本身設定好
	private int column;
	//待加載的數據  數據每行的列數和上面要統一好
	private List<Object> list;
	
	public MyTableModel(List<Object> 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操做

這裏寫圖片描述

if("增長".equals(command)){
			List<Object> data = getData();
			data.add("test5");
			data.add("test6");
			datamModel.setList(data);
//			datamModel.fireTableStructureChanged();
			datamModel.fireTableRowsInserted(5,6);
		}else if("刪除".equals(command)){
			List<Object> data = getData();
			data.remove(2);
			datamModel.setList(data);
			datamModel.fireTableRowsDeleted(1, 1);
		}else if("更新".equals(command)){
			List<Object> 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等控件的,可是咱們發現咱們定義的控件在表格上顯示成了控件對應的類的字符串了,這又是爲何呢。下面請隨我一塊兒看看源碼吧:
/**
     *  Returns <code>Object.class</code> regardless of <code>columnIndex</code>.
     *
     *  @param columnIndex  the column being queried
     *  @return the Object.class
     */
    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);
複製代碼
相關文章
相關標籤/搜索