为JTable每行按钮单独设定点击状态

By
写代码

最近工作忙到头大,看到eclipse要吐……遇到的问题也很多,有个比较奇怪的问题描述是这样的:JTable有MxN个cell,其中第5列为按钮,按钮可点击一次,之后变为disable状态;其他列为不可编辑的文本内容。

分析

拿到这个问题首先是创建abstractTableModel,然后创建以此Model为内容的JTable,接着创建按钮显示,用TableCellRendererTableCellEditor,创建样式和响应事件。
一般到这里,创建的table就可以正常显示并且内容按钮也能响应了。但是作为主要功能,每行按钮只能点击一次,并且不影响其他按钮的效果才是关键。
直接在render和editor里设置返回button的状态肯定不行,因为是按照table.getColumnModel().getColumn(5).setCellRenderer(render);来指定,即按列改变状态。点击一次全部取消掉,那其他行的按钮就没办法用了。
挠头挠了半天,终于想到&找到解决办法了。

关键点在AbstractTableModel这里。isCellEditable这个函数是用于cell是否可编辑的,通常如果包含按钮的话,就用getColumnClass(col).equals(JButton.class)来判断,并返回true,其他返回false,即不可编辑。

以此为突破口,只要在TableModel里加入行列和可否编辑的信息并存储就行了。那就是……双key单value?这肯定不行。

解决办法 Map:cell row & column, key

最后想到在AbstractTableModel里加上了一个Map,其中CellEditableKey包含row和column元素,即该tableModel的行和列信息,然后以Map来存放行列对应的Boolean信息。

public class CellEditableKey{
	private int row;
	private int column;
	public CellEditableKey(int row, int column){
		this.setRow(row);
		this.setColumn(column);
	}
	public int getRow() {
		return row;
	}
	public void setRow(int row) {
		this.row = row;
	}
	public int getColumn() {
		return column;
	}
	public void setColumn(int column) {
		this.column = column;
	}
}

另外加入两个函数addCellEditablesetCellEditable,分别在插入数据的时候和更改cell的可编辑状态时用。该部分代码如下

    public void addCellEditable(CellEditableKey mKey, boolean value) {
		for (CellEditableKey key : map.keySet()) {
			if (key.getRow() == mKey.getRow()
					&& key.getColumn() == mKey.getColumn()) {
				return;
			}
		}
		map.put(mKey, value);
    }
    
    public void setCellEditable(int row, int col, boolean value) {
  	  for(CellEditableKey key : map.keySet()){
		  if(key.getRow() == row && key.getColumn() == col){
			  map.put(key, value);
		  }
	  }
	  if(getColumnClass(col).equals(JButton.class)){
		  JButton btn = (JButton)getValueAt(row, col);
		  btn.setEnabled(value);
	  }
  	  this.fireTableCellUpdated(row, col);
    }
    
	public boolean isCellEditable(int rowIndex, int columnIndex) {
	  	  for(CellEditableKey key : map.keySet()){
			  if(key.getRow() == rowIndex && key.getColumn() == columnIndex){
				  return map.get(key);
			  }
		  }
		return false;
	}

这样,为TableCellEditor绑定ActionListener之后,在actionPerformed里触发一个
getControlModel().setCellEditable(row, 5, false);即可单独改变单个按钮状态,在这里再用一个clicked来记录是否点击,以避免重复触发,即可实现需要的功能了。

结论

Java的UI变数好大,很多问题怎么绕弯,最后都可以解决。关键就是动脑筋&办法效率了。作为一个新手,能解决问题是好的,慢慢就要想更精简&有效率的方法了。程序员果然是为“懒”而生的。

欢迎有类似问题经验的同学赐教。

您已经发表过意见了!

Comments: 6

  1. 这个对我来说有点难

    2015年02月09日
  2. 这个对我来说是天文~其实早就进来过,看不懂没吭声,再来不吭声就不是大叔了

    @zwwooooo 2015年02月10日
  3. 这是java吧,所有编程都差不多,就是要去死记硬背多敲代码才会熟悉一些控件语法等。 写代码虽然很累,但是实现了还是很有成就感的,呵呵。

    2015年02月16日
  4. 你知道的,我是在看天书···

    @@yywryywr 2015年02月25日
  5. 思路很清晰。

    @vfhky 2015年03月01日

发表评论

您的电子邮箱地址不会被公开。

*

:razz: