java - 尽管实现了 "getColumnClass",但 JTable 显示 true/false 而不是 CheckBox

标签 java

我有一个 JTable,我想在其中以复选框的形式显示 boolean 值,它应该能够被编辑(选中/取消选中)。

为了实现这一目标,我实现了 AbstractTableModel 的子类,其中包含所有需要的方法、getColumnClass 和 isCellEditable 实现。

问题是,显示的是 true/false,而不是 CheckBox。仅当我单击单元格时,才会调用 getColumnClass-Method 并且复选框会出现一小段时间。

我发现,JTable 从不在开始时调用“getColumnClass”,而是在我想单击单元格时调用。

public class OrderTableModel extends AbstractTableModel {
    private ArrayList<Orders> orders;
    private final String[] HEADER = {"Date", "isParty", "isHost"};

public OrderTableModel(ArrayList<Orders> orders)
{
    this.orders = orders;
}

public OrderTableModel(){
    orders = new ArrayList<>();
}

@Override
public String getColumnName(int column) {
    return HEADER[column];
}

@Override
public int getRowCount() {
    return orders.size() > 20 ? orders.size() : 20;
}

@Override
public int getColumnCount() {
    return HEADER.length;
}

@Override
public Class<?> getColumnClass(int columnIndex) {
    System.out.println("in getColumnClass");
    switch(columnIndex)
    {
        case 1: return Boolean.class;
        case 2: return Boolean.class;
        default: return String.class;
    }

}


@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
    return true;
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    ...
}

最佳答案

无论如何,我创建了自己的 MRE使用您的代码,但充实它,以便它可以编译和运行,并且代码按预期工作:JCheckBoxes出现在您期望看到它们的地方。请自行测试一下:

enter image description here

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;

@SuppressWarnings("serial")
public class OrderTableFun  extends JPanel {
    private OrderTableModel model = new OrderTableModel();
    private JTable table = new JTable(model);

    public OrderTableFun() {
        Random random = new Random();
        for (int i = 0; i < 20; i++) {
            String name = "name " + i;
            boolean party = random.nextBoolean();
            boolean host = random.nextBoolean();
            Orders order = new Orders(name, party, host);
            model.addOrders(order);
        }

        setLayout(new BorderLayout());
        add(new JScrollPane(table));
    }

    private static void createAndShowGui() {
        OrderTableFun mainPanel = new OrderTableFun();

        JFrame frame = new JFrame("OrderTableFun");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}
@SuppressWarnings("serial")
class OrderTableModel extends AbstractTableModel {
    private ArrayList<Orders> orders;
    private final String[] HEADER = { "Date", "isParty", "isHost" };

    public OrderTableModel(ArrayList<Orders> orders) {
        this.orders = orders;
    }

    public OrderTableModel() {
        orders = new ArrayList<>();
    }

    @Override
    public String getColumnName(int column) {
        return HEADER[column];
    }

    @Override
    public int getRowCount() {
        // !! return orders.size() > 20 ? orders.size() : 20;
        return orders.size(); // !!
    }

    @Override
    public int getColumnCount() {
        return HEADER.length;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        System.out.println("in getColumnClass");
        switch (columnIndex) {
        case 1:
            return Boolean.class;
        case 2:
            return Boolean.class;
        default:
            return String.class;
        }

    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return true;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        Orders order = (Orders) orders.get(rowIndex);
        switch (columnIndex) {
        case 0:
            String name = (String) aValue;
            order.setName(name);
            break;
        case 1:
            Boolean party = (Boolean) aValue;
            order.setParty(party);
        case 2:
            Boolean host = (Boolean) aValue;
            order.setHost(host);
        }
        fireTableRowsUpdated(rowIndex, rowIndex);
    }

    public void addOrders(Orders order) {
        orders.add(order);
        fireTableRowsInserted(getRowCount() - 1, getRowCount());
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Orders order = (Orders) orders.get(rowIndex);
        switch (columnIndex) {
        case 0:
            return order.getName();
        case 1:
            return order.isParty();
        case 2:
            return order.isHost();

        default:
            return null;
        }
    }
}
class Orders {
    String name;
    boolean party;
    boolean host;

    public Orders(String name, boolean party, boolean host) {
        this.name = name;
        this.party = party;
        this.host = host;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isParty() {
        return party;
    }

    public void setParty(boolean party) {
        this.party = party;
    }

    public boolean isHost() {
        return host;
    }

    public void setHost(boolean host) {
        this.host = host;
    }

}

我更改了 getRowCount 以反射(reflect)可用 Orders 对象的实际数量。

关于java - 尽管实现了 "getColumnClass",但 JTable 显示 true/false 而不是 CheckBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56327653/

相关文章:

Java 8 元空间垃圾回收

java - 高并发系统中的锁定

java - 如何在java spring boot中使用mongoDB高级过滤器

java - 如何以排序的方式检索文档的值?

java - Elasticsearch:在传输层捕获异常

java - Struts2登录拦截器不工作

java - 如何设置扫描区域 ZXing Scanner

java - 在Android Studio中使用Volley下载文件

java - 如何对AbstractRoutingDataSource进行安全频繁的DataSource切换?

java - Android:保存的缩略图不应出现在图库中