Axiu Blog
这个问题首先是创建`abstractTableModel`,然后创建以此Model为内容的JTable,接着创建按钮显示,用`TableCellRenderer`和`TableCellEditor`,创建样式和响应事件。 一般到这里,创建的table就可以正常显示并且内容按钮也能响应了。但是作为主要功能,每行按钮只能点击一次,并且不影响其他按钮的效果才是
最近工作忙到头大,看到eclipse要吐……遇到的问题也很多,有个比较奇怪的问题描述是这样的:JTable有MxN个cell,其中第5列为按钮,按钮可点击一次,之后变为disable状态;其他列为不可编辑的文本内容。 ### 分析 拿到这个问题首先是创建`abstractTableModel`,然后创建以此Model为内容的JTable,接着创建按钮显示,用`TableCellRenderer
最近工作忙到头大,看到eclipse要吐……遇到的问题也很多,有个比较奇怪的问题描述是这样的:JTable有MxN个cell,其中第5列为按钮,按钮可点击一次,之后变为disable状态;其他列为不可编辑的文本内容。 ### 分析 拿到这个问题首先是创建`abstractTableModel`,然后创建以此Model为内容的JTable,接着创建按钮显示,用`TableCellRenderer
为JTable每行按钮单独设定点击状态
Max

最近工作忙到头大,看到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