Java 如何在JTable中设置CellEditor?

Java 如何在JTable中设置CellEditor?,java,swing,jtable,tablecelleditor,Java,Swing,Jtable,Tablecelleditor,我想为JTable中的一个单元格设置CellEditor。它是一个单元格而不是all列,我在JDK中找不到名为cell的类 这个代码不能满足我的要求 table.getColumnModel().getColumn(columnIndex).setCellEditor(new DefaultCellEditor(new JComboBox)); 很简单。您只需要重写JTable的方法getCellRenderer。这里有一个例子 import java.awt.Component; imp

我想为
JTable
中的一个单元格设置
CellEditor
。它是一个单元格而不是all列,我在JDK中找不到名为
cell
的类

这个代码不能满足我的要求

table.getColumnModel().getColumn(columnIndex).setCellEditor(new DefaultCellEditor(new JComboBox));  

很简单。您只需要重写
JTable
的方法
getCellRenderer
。这里有一个例子

import java.awt.Component;
import java.awt.font.TextAttribute;
import java.util.Collections;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

@SuppressWarnings("unchecked")
public class TableRendererTest {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Renderer test");
        DefaultTableModel model = new DefaultTableModel(new String[] {"First", "Second", "Third" }, 3);
        model.setValueAt("First row cell", 0, 1);
        model.setValueAt("Striked out string", 1, 1);
        model.setValueAt("Last row cell", 2, 1);

        TableCellRenderer strikeOutRenderer = new StrikeOutRenderer();
        // table with strike-out renderer (last cell is not stroked out)
        // create a custom table with possibility to change renderer for a single cell.
        JTable tbl = new JTable(model) {
            @Override
            public TableCellRenderer getCellRenderer(int row, int column) {
                if (row == 1 && column == 1) {
                    return strikeOutRenderer;
                }
                return super.getCellRenderer(row, column);
            }
        };
        frm.add(new JScrollPane(tbl));

        frm.pack();
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.setVisible(true);
    }

    private static class StrikeOutRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            Component res = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            res.setFont(res.getFont().deriveFont(Collections.singletonMap(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON)));
            return res;
        }
    }
}
下面是完整解决方案的代码,因此您可以在任何地方使用该表,并可以为任何单元格定义渲染器

// defined in JCellStyleTable.java
public class JCellStyleTable extends JTable {


    private final Map<Cell, TableCellRenderer> renderersMap = new HashMap<>();

    private final Map<Cell, TableCellEditor> editorsMap = new HashMap<>();

    public JCellStyleTable() {
        super();
    }

    public JCellStyleTable(TableModel dm) {
        super(dm);
    }

    public void putRenderer(Cell cell, TableCellRenderer renderer) {
        renderersMap.put(Objects.requireNonNull(cell), renderer);
    }

    public TableCellRenderer getRenderer(Cell cell) {
        return renderersMap.get(Objects.requireNonNull(cell));
    }

    public void putEditor(Cell cell, TableCellEditor editor) {
        editorsMap.put(Objects.requireNonNull(cell), editor);
    }

    public TableCellEditor getEditor(Cell cell) {
        return editorsMap.get(Objects.requireNonNull(cell));
    }

    @Override
    public TableCellRenderer getCellRenderer(int row, int column) {
        TableCellRenderer result = renderersMap.get(new Cell(row, column));
        return result == null ? super.getCellRenderer(row, column) : result;
    }

    @Override
    public TableCellEditor getCellEditor(int row, int column) {
        return editorsMap.get(new Cell(row, column)); // when null - no editing
    }
}

// defined in CellBasedTableModel.java
public class CellBasedTableModel extends DefaultTableModel {
    private Collection<Cell> editableCells = new HashSet<>();

    public CellBasedTableModel() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return editableCells.contains(new Cell(row, column));
    }

    public void addEditableCell(Cell cell) {
        editableCells.add(cell);
    }

    public void removeEditableCell(Cell cell) {
        editableCells.remove(cell);
    }
}

// defined in Cell.java
public class Cell {
    private final int row, col;

    public Cell(int row, int col) {
        this.row = row;
        this.col = col;
    }

    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Cell) {
            Cell another = (Cell) obj;
            return another.col == col && another.row == row;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(new int[] {row, col});
    }
}
//在JCellStyleTable.java中定义
公共类JCellStyleTable扩展了JTable{
私有最终映射渲染器Map=newhashmap();
私有最终映射编辑器Map=newhashmap();
公共JCellStyleTable(){
超级();
}
公共JCellStyleTable(TableModel dm){
超级(dm);
}
公共单元格渲染器(单元格、TableCellRenderer渲染器){
RendersMap.put(Objects.requirennull(单元格),renderer);
}
公共TableCellRenderer getRenderer(单元格){
返回rendersmap.get(Objects.requirennull(单元格));
}
公共void编辑器(单元格、TableCellEditor编辑器){
editorsMap.put(Objects.requirennull(单元格),editor);
}
公共表格单元格编辑器getEditor(单元格){
返回editorsMap.get(Objects.requirennull(单元格));
}
@凌驾
公共TableCellRenderer getCellRenderer(int行,int列){
TableCellRenderer结果=rendersMap.get(新单元格(行、列));
返回结果==null?super.getCellRenderer(行、列):结果;
}
@凌驾
公共表CellEditor getCellEditor(int行,int列){
return editorsMap.get(新单元格(行、列));//为null时-无编辑
}
}
//在CellBasedTableModel.java中定义
公共类CellBasedTableModel扩展了DefaultTableModel{
私有集合editableCells=new HashSet();
public CellBasedTableModel(){
//TODO自动生成的构造函数存根
}
@凌驾
公共布尔值可编辑(int行,int列){
返回editableCells.contains(新单元格(行、列));
}
公共无效可添加单元格(单元格){
可编辑单元格。添加(单元格);
}
公共无效removeEditableCell(单元格){
可编辑单元格。删除(单元格);
}
}
//在Cell.java中定义
公共类单元{
私有最终整数行,col;
公共单元格(整数行,整数列){
this.row=行;
this.col=col;
}
public int getRow(){
返回行;
}
公共int getCol(){
返回列;
}
@凌驾
公共布尔等于(对象obj){
if(单元的obj实例){
另一个单元格=(单元格)obj;
返回other.col==col&&other.row==row;
}
返回false;
}
@凌驾
公共int hashCode(){
返回Arrays.hashCode(新的int[]{row,col});
}
}

这很简单。您只需要重写
JTable
的方法
getCellRenderer
。这里有一个例子

import java.awt.Component;
import java.awt.font.TextAttribute;
import java.util.Collections;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

@SuppressWarnings("unchecked")
public class TableRendererTest {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Renderer test");
        DefaultTableModel model = new DefaultTableModel(new String[] {"First", "Second", "Third" }, 3);
        model.setValueAt("First row cell", 0, 1);
        model.setValueAt("Striked out string", 1, 1);
        model.setValueAt("Last row cell", 2, 1);

        TableCellRenderer strikeOutRenderer = new StrikeOutRenderer();
        // table with strike-out renderer (last cell is not stroked out)
        // create a custom table with possibility to change renderer for a single cell.
        JTable tbl = new JTable(model) {
            @Override
            public TableCellRenderer getCellRenderer(int row, int column) {
                if (row == 1 && column == 1) {
                    return strikeOutRenderer;
                }
                return super.getCellRenderer(row, column);
            }
        };
        frm.add(new JScrollPane(tbl));

        frm.pack();
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.setVisible(true);
    }

    private static class StrikeOutRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            Component res = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            res.setFont(res.getFont().deriveFont(Collections.singletonMap(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON)));
            return res;
        }
    }
}
下面是完整解决方案的代码,因此您可以在任何地方使用该表,并可以为任何单元格定义渲染器

// defined in JCellStyleTable.java
public class JCellStyleTable extends JTable {


    private final Map<Cell, TableCellRenderer> renderersMap = new HashMap<>();

    private final Map<Cell, TableCellEditor> editorsMap = new HashMap<>();

    public JCellStyleTable() {
        super();
    }

    public JCellStyleTable(TableModel dm) {
        super(dm);
    }

    public void putRenderer(Cell cell, TableCellRenderer renderer) {
        renderersMap.put(Objects.requireNonNull(cell), renderer);
    }

    public TableCellRenderer getRenderer(Cell cell) {
        return renderersMap.get(Objects.requireNonNull(cell));
    }

    public void putEditor(Cell cell, TableCellEditor editor) {
        editorsMap.put(Objects.requireNonNull(cell), editor);
    }

    public TableCellEditor getEditor(Cell cell) {
        return editorsMap.get(Objects.requireNonNull(cell));
    }

    @Override
    public TableCellRenderer getCellRenderer(int row, int column) {
        TableCellRenderer result = renderersMap.get(new Cell(row, column));
        return result == null ? super.getCellRenderer(row, column) : result;
    }

    @Override
    public TableCellEditor getCellEditor(int row, int column) {
        return editorsMap.get(new Cell(row, column)); // when null - no editing
    }
}

// defined in CellBasedTableModel.java
public class CellBasedTableModel extends DefaultTableModel {
    private Collection<Cell> editableCells = new HashSet<>();

    public CellBasedTableModel() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return editableCells.contains(new Cell(row, column));
    }

    public void addEditableCell(Cell cell) {
        editableCells.add(cell);
    }

    public void removeEditableCell(Cell cell) {
        editableCells.remove(cell);
    }
}

// defined in Cell.java
public class Cell {
    private final int row, col;

    public Cell(int row, int col) {
        this.row = row;
        this.col = col;
    }

    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Cell) {
            Cell another = (Cell) obj;
            return another.col == col && another.row == row;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(new int[] {row, col});
    }
}
//在JCellStyleTable.java中定义
公共类JCellStyleTable扩展了JTable{
私有最终映射渲染器Map=newhashmap();
私有最终映射编辑器Map=newhashmap();
公共JCellStyleTable(){
超级();
}
公共JCellStyleTable(TableModel dm){
超级(dm);
}
公共单元格渲染器(单元格、TableCellRenderer渲染器){
RendersMap.put(Objects.requirennull(单元格),renderer);
}
公共TableCellRenderer getRenderer(单元格){
返回rendersmap.get(Objects.requirennull(单元格));
}
公共void编辑器(单元格、TableCellEditor编辑器){
editorsMap.put(Objects.requirennull(单元格),editor);
}
公共表格单元格编辑器getEditor(单元格){
返回editorsMap.get(Objects.requirennull(单元格));
}
@凌驾
公共TableCellRenderer getCellRenderer(int行,int列){
TableCellRenderer结果=rendersMap.get(新单元格(行、列));
返回结果==null?super.getCellRenderer(行、列):结果;
}
@凌驾
公共表CellEditor getCellEditor(int行,int列){
return editorsMap.get(新单元格(行、列));//为null时-无编辑
}
}
//在CellBasedTableModel.java中定义
公共类CellBasedTableModel扩展了DefaultTableModel{
私有集合editableCells=new HashSet();
public CellBasedTableModel(){
//TODO自动生成的构造函数存根
}
@凌驾
公共布尔值可编辑(int行,int列){
返回editableCells.contains(新单元格(行、列));
}
公共无效可添加单元格(单元格){
可编辑单元格。添加(单元格);
}
公共无效removeEditableCell(单元格){
可编辑单元格。删除(单元格);
}
}
//在Cell.java中定义
公共类单元{
私有最终整数行,col;
公共单元格(整数行,整数列){
this.row=行;
this.col=col;
}
public int getRow(){
返回行;
}
公共int getCol(){
返回列;
}
@凌驾
公共布尔等于(对象obj){
if(单元的obj实例){
另一个单元格=(单元格)obj;
返回other.col==col&&other.row==row;
}
返回false;
}
@凌驾
公共int hashCode(){
返回Arrays.hashCode(新的int[]{row,col});
}
}

um…谢谢您的帮助,可能我的表达式不正确,我的需求,例如,当我单击单元格(1,1)时,JTable将在该单元格上弹出一个JcomboBox组件,当我单击单元格(n,1)时,JTable将不弹出任何内容,n表示其他行number@huyangqing这很容易。您可以覆盖
JTable
中的方法
getCellEditor(int行,int列)
。我已经为你修改了第二个例子