概述
我们都知道JTable提供了columnModel可以设置指定的实现了TableCellEditor接口的控件但其实现时是整个列使用同一个cellEditor
例如combobox的celleditor就会导致整个列的combobox中的数据相同,这在条件选择时可以这样,但大多数时候我们需要每一行的combobox中的内容不一样
就是说思路上我们要指定每一样的不一样的combobox才可以实现
网上有教程什么在table中复写getCellEditor(int row, int column)然后指定行列为自定义的celleditor,虽然这样可以实现但对于每一行都要new一个combobox的celleditor这样肯定是不不可行的,
网上对于这种需求实现的例子很少,而且很多还是在骗分
今天就教大家如何实现这样的需求指定JTable的某列为JComboboxCellEditor并且每个Combobox可以显示不一样的数据
简单思路:
1、自定义单元编辑器(其中getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)需要通过先删除原有item在加载model对应单元中的原始数据)
2、自定义tablemodle,在tablemodel中定义好combobox列的数据为list或数组按需求写,并在tablemodel中设置一个方法返回此数据(这儿简单介绍一下在tablemodle中有一个getValueAt(int row, int column)它返回的是table显示的数据,就是说第一次某单元格是list数据它会返回一个list但如果有选择后他就返回选择后的值不会返回list,所以我们要自定义方法返回原始数据)
代码实现:
1、Jcombobxcelleditor
public class JComboboxCellEditor extends JComboBox<Object> implements TableCellEditor {
// extends DefaultCellEditor
protected EventListenerList listenerList = new EventListenerList();
protected ChangeEvent changeEvent = new ChangeEvent(this);
// 构造方法初始化事件监听器
public JComboboxCellEditor() {
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
fireEditingStopped();
}
});
}
protected void fireEditingStopped() {
CellEditorListener listener;
Object[] listeners = listenerList.getListenerList();
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] == CellEditorListener.class) {
listener = (CellEditorListener) listeners[i + 1];
listener.editingStopped(changeEvent);
}
}
}
protected void fireEditingCanceled() {
CellEditorListener listener;
Object[] listeners = listenerList.getListenerList();
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] == CellEditorListener.class) {
listener = (CellEditorListener) listeners[i + 1];
listener.editingCanceled(changeEvent);
}
}
}
/**
* 添加单元格编辑监听
*/
@Override
public void addCellEditorListener(CellEditorListener listener) {
listenerList.add(CellEditorListener.class, listener);
}
/**
* 移除单元格编辑监听
*/
@Override
public void removeCellEditorListener(CellEditorListener listener) {
listenerList.remove(CellEditorListener.class, listener);
}
/**
* 取消编辑
*/
@Override
public void cancelCellEditing() {
fireEditingCanceled();
}
/**
* 停止编辑
*/
@Override
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
/**
* 启用单元格编辑
*/
@Override
public boolean isCellEditable(EventObject event) {
return true;
}
/**
* 是否可以选择
*/
@Override
public boolean shouldSelectCell(EventObject event) {
return true;
}
/**
* 获取单元格选择的项
*/
@Override
public Object getCellEditorValue() {
return this.getSelectedItem();
}
/**
* 获取表中的编辑控件
*/
@SuppressWarnings("unchecked")
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
//
if (isSelected) {
//
setForeground(table.getForeground());
//
super.setBackground(table.getBackground());
//
} else {
//
setForeground(table.getForeground());
//
setBackground(table.getBackground());
//
}
Object object = ((JComboboxTableModel) table.getModel()).getOrigianlDataAt(row, column);
if (object instanceof List) {
this.removeAllItems();
List<Object> list = (List<Object>) object;
for (Object o : list) {
this.addItem(o);
}
}
return this;
}
}
2、TableModel
public class JComboboxTableModel extends DefaultTableModel {
// 原数据列表,这个是原始的数据
List<List<Object>> data;
// 列名
private List<Object> columnNames;
public List<Object> getColumnNames() {
return columnNames;
}
/**
* 通过list类型数据构造tablemodel
*
* @param data
* @param columnNames
*/
public JComboboxTableModel(List<List<Object>> data, List<Object> columnNames) {
// 将list类型数据转化为Vector类型
Vector<Vector<Object>> vectorData = FormatUtil.getVectorByTwoDimemsionalList(data);
Vector<Object> vectorcolumnNames = FormatUtil.getVectorByOneDimensionalList(columnNames);
// 设置table的DataVector
setDataVector(vectorData, vectorcolumnNames);
// 设置原数据
this.data = data;
this.columnNames = columnNames;
}
/**
* 通过array类型数据构造tablemodel
*
* @param data
* @param columnNames
*/
public JComboboxTableModel(Object[][] data, Object[] columnNames) {
super(data, columnNames);
this.data = FormatUtil.getListByTwoDimensionalArray(data);
this.columnNames = Arrays.asList(columnNames);
}
/**
* table通过这个方法获取模型数据
*/
@SuppressWarnings("unchecked")
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (this.getDataVector() == null || this.getDataVector().size() == 0)
return null;
if (rowIndex >= this.getDataVector().size()) {
throw new IndexOutOfBoundsException("The rowIndex is out of bounds. Your rowIndex is :" + rowIndex
+ " , and the row size is :" + this.getDataVector().size());
}
List<Object> row = (List<Object>) this.getDataVector().get(rowIndex);
if (row == null || row.size() == 0)
return null;
if (columnIndex >= row.size()) {
throw new IndexOutOfBoundsException("The columnIndex is out of bounds. Your columnIndex is :" + columnIndex
+ " , and the columns size is :" + row.size());
}
// 对list特殊处理
// 如果某单元格中数据是list类型则显示list中的第一个数据
// (当然这个在设计中只是针对数据第一次在table中显示和没有通过combobox进行选择的数据)
if (row.get(columnIndex) instanceof List) {
return ((List<Object>) row.get(columnIndex)).get(0);
}
return row.get(columnIndex);
}
/**
* combobox通过这个方法获取数据
*
* @param rowIndex
* @param columnIndex
* @return
*/
public Object getOrigianlDataAt(int rowIndex, int columnIndex) {
if (this.data == null || this.data.size() == 0)
return null;
if (rowIndex >= this.data.size()) {
throw new IndexOutOfBoundsException("The rowIndex is out of bounds. Your rowIndex is :" + rowIndex
+ " , and the row size is :" + this.data.size());
}
List<Object> row = (List<Object>) this.data.get(rowIndex);
if (row == null || row.size() == 0)
return null;
if (columnIndex >= row.size()) {
throw new IndexOutOfBoundsException("The columnIndex is out of bounds. Your columnIndex is :" + columnIndex
+ " , and the columns size is :" + row.size());
}
return row.get(columnIndex);
}
/**
* 添加List类型的数据
*
* @param data
*/
public void addRow(List<Object> data) {
Vector<Object> rowData = FormatUtil.getVectorByOneDimensionalList(data);
this.insertRow(this.getRowCount(), rowData);
this.data.add(data);
}
/**
* 添加Array类型的数据
*/
@Override
public void addRow(Object[] rowData) {
super.addRow(rowData);
this.data.add(Arrays.asList(rowData));
}
@SuppressWarnings("rawtypes")
@Override
public void addRow(Vector rowData) {
// TODO 暂时不会用到这种添加方式,有需求再改
super.addRow(rowData);
}
}
3、JTable中的数据考虑到线程安全使用个的是Vector这作者写了个转化工具这也提供出来了(供给大家参考)
public class FormatUtil {
/**
* 二维数组转化为List
*
* @author JiangGengchao
* @param a
* @return
*/
public static <T> List<List<T>> getListByTwoDimensionalArray(T[][] a) {
List<List<T>> list1 = new ArrayList<List<T>>();
for (int i = 0; i < a.length; i++) {
List<T> list2 = new ArrayList<T>();
for (int j = 0; j < a[i].length; j++) {
list2.add(a[i][j]);
}
list1.add(list2);
}
return list1;
}
/**
* 二维List转化为Vector
*
* @param list
* @return
*/
public static <T> Vector<Vector<T>> getVectorByTwoDimemsionalList(List<List<T>> list) {
Vector<Vector<T>> vector1 = new Vector<Vector<T>>();
Iterator<List<T>> iterator1 = list.iterator();
while (iterator1.hasNext()) {
Iterator<T> iterator2 = iterator1.next().iterator();
Vector<T> vector2 = new Vector<T>();
while (iterator2.hasNext()) {
vector2.add(iterator2.next());
}
vector1.add(vector2);
}
return vector1;
}
/**
* 一维List转化为一维Vector
*
* @param list
* @return
*/
public static <T> Vector<T> getVectorByOneDimensionalList(List<T> list) {
Vector<T> vector = new Vector<T>();
Iterator<T> iterator = list.iterator();
while (iterator.hasNext()) {
vector.add(iterator.next());
}
return vector;
}
}
4、简单JTable封装
public class JIrmComboboxTable extends JTable {
/**
* 暂时还需要手动设置列模型的cellEditor,后期可以改成动态识别list然后自动设置
*
* @param column
*/
public void setCellRendererAndEditor(int column) {
this.getColumnModel().getColumn(column).setCellEditor(new JComboboxCellEditor());
}
// 坑爹设置了model后table就不调用这个方法获取cellEditor了
@Override
public TableCellEditor getCellEditor(int row, int column) {
return super.getCellEditor(row, column);
}
public void addRow(List<Object> items) {
// TODO 这个功能在model中提供了,这儿暂时不做提供
}
}
3、测试:
public class MyComponentTest extends JFrame {
public MyComponentTest() {
this.setTitle("MyComponentTest");
this.setSize(500, 400);
this.setLocationRelativeTo(null);
this.getContentPane().setLayout(new BorderLayout());
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
initUI3();
this.setVisible(true);
}
/**
* 时间段控件
*/
private void initUI1() {
JPeriodTimePicker periodTimePicker = new JPeriodTimePicker();
this.add(periodTimePicker);
}
/**
* 数字段控件
*/
private void initUI2() {
JPeriodNumberField periodNumberField = new JPeriodNumberField(64, 32, -Double.MAX_VALUE, Double.MAX_VALUE);
this.add(periodNumberField);
}
/**
* combobox的table
*/
private void initUI3() {
List<Object> templist1 = new ArrayList<Object>();
templist1.add("list11");
templist1.add("list12");
List<Object> templist2 = new ArrayList<Object>();
templist2.add("list21");
templist2.add("list22");
templist2.add("list23");
List<Object> columnNames = new ArrayList<Object>();
columnNames.add("c21");
columnNames.add("c22");
columnNames.add("list");
List<Object> r1 = new ArrayList<Object>();
r1.add("c11");
r1.add("c12");
r1.add(templist1);
List<Object> r2 = new ArrayList<Object>();
r2.add("c21");
r2.add("c22");
r2.add(templist2);
List<List<Object>> data = new ArrayList<List<Object>>();
data.add(r1);
data.add(r2);
// Object[][] data = { { "test11", "test12", templist1 }, { "test21",
// "test22", templist2 } };
// Object[] columnNames = { "c1", "c2", "list" };
model = new JComboboxTableModel(data, columnNames);
JIrmComboboxTable table = new JIrmComboboxTable();
table.setRowHeight(24);
table.setModel(model);
table.setCellRendererAndEditor(2);
// JTable table = new JTable(3,3){
// @Override
// public TableCellEditor getCellEditor(int row, int column) {
// if(row == 2 && column == 2) {
// ComboBoxCellEditor cellEditor = new ComboBoxCellEditor();
// cellEditor.addItem("12");
// cellEditor.addItem("34");
// return cellEditor;
// }
// return super.getCellEditor(row, column);
// }
// };
// table.setRowHeight(30);
JScrollPane sp = new JScrollPane(table);
JButton addOneRowData = new JButton(addDataAction);
this.add(sp, BorderLayout.CENTER);
this.add(addOneRowData, BorderLayout.SOUTH);
}
private JComboboxTableModel model;
/**
* 动态添加一行数据
* @author JiangGengchao
* @date 2016年4月14日
*/
private MAction addDataAction = new MAction("动态添加数据") {
@Override
public void execute(ActionEvent e) {
List<Object> newColumnList = new ArrayList<Object>();
newColumnList.add("ncl1");
newColumnList.add("ncl2");
List<Object> newRowList = new ArrayList<Object>();
newRowList.add("new1");
newRowList.add("new2");
newRowList.add(newColumnList);
model.addRow(newRowList);
}
};
public static void main(String[] args) {
new MyComponentTest();
}
}
笔者只是在这儿记录备忘的,希望能帮助到看客
最后
以上就是从容黑猫为你收集整理的java之swing中Jtable的动态一列中的每行的Jcombobox显示不一样的数据的全部内容,希望文章能够帮你解决java之swing中Jtable的动态一列中的每行的Jcombobox显示不一样的数据所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复