Java 如何在 JTable 中呈现复选框?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4154802/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 12:07:06  来源:igfitidea点击:

How to render a checkbox in a JTable?

javaswingcheckboxjtable

提问by tiendv

This is my code to render a JTable and change the color of rows, but it doesn't show a checkbox in column 6, only string (true,false).

这是我渲染 JTable 并更改行颜色的代码,但它在第 6 列中没有显示复选框,只有字符串 (true,false)。

Can you provide a solution to fix this?

你能提供解决这个问题的解决方案吗?

Thanks in advance.

提前致谢。

    public class JLabelRenderer extends JLabel implements TableCellRenderer
{
  private MyJTable myTable;
  /**
   * Creates a Custom JLabel Cell Renderer
   * @param t your JTable implmentation that holds the Hashtable to inquire for
   * rows and colors to paint.
   */
  public JLabelRenderer(MyJTable t)
  {
    this.myTable = t;
  }

  /**
   * Returns the component used for drawing the cell.  This method is
   * used to configure the renderer appropriately before drawing.
   * see TableCellRenderer.getTableCellRendererComponent(...); for more comments on the method
   */
  public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
  {
    setOpaque(true); //JLabel isn't opaque by default

    setText(value.toString());
    setFont(myTable.getFont());

    if(!isSelected)//if the row is not selected then use the custom color
    setBackground(myTable.getRowToPaint(row));
    else //if the row is selected use the default selection color
    setBackground(myTable.getSelectionBackground());

    //Foreground could be changed using another Hashtable...
    setForeground(myTable.getForeground());

    // Since the renderer is a component, return itself
    return this;
  }

  // The following methods override the defaults for performance reasons
  public void validate() {}
  public void revalidate() {}
  protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
  public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
}

This is the table:

这是表:

import javax.swing.JTable;    
import javax.swing.table.*;
import java.util.Hashtable;
import java.awt.Color;

public class MyJTable extends JTable
{
  Hashtable rowsToPaint = new Hashtable(1);

  /**
   * Default Constructor
   */
  public MyJTable()
  {
    super();
  }

  /**
   * Set the TableModel and then render each column with a custom cell renderer
   * @param tm TableModel
   */
  public void setModel(TableModel tm)
  {
    super.setModel(tm);
    renderColumns(new JLabelRenderer(this));
  }

  /**
   * Add a new entry indicating:
   * @param row the row to paint - the first row = 0;
   * @param bgColor background color
   */
  public void addRowToPaint(int row, Color bgColor)
  {
    rowsToPaint.put(new Integer(row), bgColor);
    this.repaint();// you need to repaint the table for each you put in the hashtable.
  }

  /**
   * Returns the user selected BG Color or default BG Color.
   * @param row the row to paint
   * @return Color BG Color selected by the user for the row
   */
  public Color getRowToPaint(int row)
  {
    Color bgColor = (Color)rowsToPaint.get(new Integer(row));
    return (bgColor != null)?bgColor:getBackground();
  }

  /**
   * Render all columns with the specified cell renderer
   * @param cellRender TableCellRenderer
   */
  public  void renderColumns(TableCellRenderer cellRender)
  {
    for(int i=0; i<this.getModel().getColumnCount(); i++)
    {
      renderColumn(this.getColumnModel().getColumn(i), cellRender);
    }
  }

  /**
   * Render a TableColumn with the sepecified Cell Renderer
   * @param col TableColumn
   * @param cellRender TableCellRenderer
   */
  public void renderColumn(TableColumn col, TableCellRenderer cellRender)
  {
    try{
          col.setCellRenderer(cellRender);
        }catch(Exception e){System.err.println("Error rendering column: [HeaderValue]: "+col.getHeaderValue().toString()+" [Identifier]: "+col.getIdentifier().toString());}
  }
}

here is my screen alt text

这是我的屏幕 替代文字

采纳答案by akf

As you probably know, JTable will render boolean values as checkboxes for you. I suppose that your problem is that, out of the box, you cannot set custom background color per row based on specific criteria in your data. You can create a new TableCellRendererfor your booleancolumn.

您可能知道,JTable 将为您呈现布尔值作为复选框。我想您的问题是,开箱即用,您无法根据数据中的特定条件设置每行的自定义背景颜色。您可以TableCellRenderer为您的boolean列创建一个新的。

You have a couple options:

您有几个选择:

  1. you can put a test in your current renderer to determine whether the valuepassed in is boolean or not, and if so, configure a JCheckboxinstance to be returned. This could effect what you want, but you would need to be careful, as your renderer is called often and if you create one-off JCheckboxes, it could cause a lot of churn.

  2. alternatively, you could create a new TableCellRendererthat extends JCheckbox(just as your current one extends JLabel. You would want to refactor your current coloring logic such that it could be shared between the two renderers. Finally, you would want to associate this renderer with your column. You can either do this by setting it as the default renderer on the table for a certain Class(myTable.setDefaultRenderer(Class, TableCellRenderer)), or setting it as the renderer for a specific column (myTable.getColumnModel().getColumn(int).setCellRenderer(TableCellRenderer))

  1. 您可以在当前渲染器中进行测试以确定value传入的是否为布尔值,如果是,则配置JCheckbox要返回的实例。这可能会影响您想要的效果,但您需要小心,因为您的渲染器经常被调用,如果您创建一次性JCheckboxes,它可能会导致大量流失。

  2. 或者,您可以创建一个新的TableCellRenderer扩展JCheckbox(就像您当前的扩展一样JLabel。您希望重构当前的着色逻辑,以便它可以在两个渲染器之间共享。最后,您希望将此渲染器与您的列相关联。您可以通过将其设置为表上某个Class( myTable.setDefaultRenderer(Class, TableCellRenderer))的默认渲染器来执行此操作,或者将其设置为特定列 ( myTable.getColumnModel().getColumn(int).setCellRenderer(TableCellRenderer))的渲染器

回答by Adamski

The best solution to this problem is to implement your own TableModel(typically by sub-classing AbstractTableModel) and implement the getColumnClass(int)method to return Boolean.classfor the column you wish to render as a JCheckBox.

此问题的最佳解决方案是实现您自己的TableModel(通常通过子类化AbstractTableModel)并实现getColumnClass(int)方法以返回Boolean.class您希望呈现为JCheckBox.

There is no need to implement your own TableCellRendereras the DefaultTableCellRendererused by JTableby default will automatically render Booleancolumns as JCheckboxes.

无需实现您自己TableCellRendererDefaultTableCellRendererJTable因为默认情况下使用的会自动将Boolean列呈现为JCheckboxes。

回答by tiendv

Thanks akfi solved it by :

谢谢akf我通过以下方式解决了它:

add class :

添加类:

public class CheckBoxRenderer extends JCheckBox implements TableCellRenderer {

          CheckBoxRenderer() {
            setHorizontalAlignment(JLabel.CENTER);
          }

          public Component getTableCellRendererComponent(JTable table, Object value,
              boolean isSelected, boolean hasFocus, int row, int column) {
            if (isSelected) {
              setForeground(table.getSelectionForeground());
              //super.setBackground(table.getSelectionBackground());
              setBackground(table.getSelectionBackground());
            } else {
              setForeground(table.getForeground());
              setBackground(table.getBackground());
            }
            setSelected((value != null && ((Boolean) value).booleanValue()));
            return this;
          }
}

Edit constructor of Mytable:

编辑 Mytable 的构造函数:

 public MyJTable(DefaultTableModel md)
  {
    super(md);
    CheckBoxRenderer checkBoxRenderer = new CheckBoxRenderer();
    this.getColumnModel().getColumn(6).setCellRenderer(checkBoxRenderer);
  }

回答by camickr

I find it easier to use the Table Row Renderingapproach for something like this. It will work without creating individual renderers for each column.

我发现使用Table Row Rendering方法来处理这样的事情更容易。它无需为每列创建单独的渲染器即可工作。