JTable:如何将Boolean渲染为Color,并使用JTextField编辑为文本?

时间:2013-01-02 22:08:03

标签: java swing jtable render

我尝试制作布尔渲染器和布尔编辑器。

布尔渲染器应将布尔值渲染为颜色(两种颜色)。 布尔编辑器应返回JTextField并启用编辑为字符串“T”和“F”

因此,如果单击单元格并键入“T”或“F”,则单元格的颜色必须移动到相应的颜色。

基于this oracle tutorial我尝试制作渲染器和编辑器并将其包含在this oracle provided example中。

布尔渲染器和布尔编辑器下面。我将它们注册到this class

        ....
        ....

        table.setDefaultRenderer(Color.class,
                new ColorRenderer(true));
        table.setDefaultEditor(Color.class,
                new ColorEditor());


        table.setDefaultRenderer(Boolean.class, new BooleanRenderer()); // My
        table.setDefaultEditor(Boolean.class, new BooleanEditor());     // My

        //Add the scroll pane to this panel.
        add(scrollPane);
        ....
        ....

根本不会渲染单元格,并且事情无法正常工作!。

我的代码出了什么问题?

我的渲染器:

import java.awt.Color;
import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;


public class BooleanRenderer extends JLabel implements TableCellRenderer
{
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        if (hasFocus)
        {
            Boolean bol = (Boolean) value;
            if (bol == Boolean.FALSE)
            {
                this.setBackground(Color.red);
                this.setText("");
            } else if (bol == Boolean.TRUE)
            {
                this.setBackground(Color.BLACK);
            }
        }
        else
        {
            Boolean bol = (Boolean) value;
            if (bol == Boolean.FALSE)
            {
                this.setBackground(Color.red);
                this.setText("");
            } else if (bol == Boolean.TRUE)
            {
                this.setBackground(Color.BLACK);
            }
        }

        if (isSelected)
        {
            Boolean bol = (Boolean) value;
            if (bol == Boolean.FALSE)
            {
                this.setBackground(Color.red);
                this.setText("");
            } else if (bol == Boolean.TRUE)
            {
                this.setBackground(Color.BLACK);
            }
        } else
        {
            Boolean bol = (Boolean) value;
            if (bol == Boolean.FALSE)
            {
                this.setBackground(Color.red);
                this.setText("");
            } else if (bol == Boolean.TRUE)
            {
                this.setBackground(Color.BLACK);
            }
        }


        return this;
    }
}

我的编辑:

import java.awt.Component;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellEditor;


public class BooleanEditor extends AbstractCellEditor
        implements TableCellEditor
{

    Boolean bool;
    JTextField tf = new JTextField();

    @Override
    public Object getCellEditorValue()
    {
        return bool;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
    {


        if (isSelected)
        {
            bool = (Boolean) value;
            if (tf.getText().equals("T"))
            {
                bool = new Boolean(true);
            } else
            {
                if (tf.getText().equals("F"))
                {
                    bool = new Boolean(false);
                }
            }

        }
        return tf;
    }
}

1 个答案:

答案 0 :(得分:4)

适用于您的渲染器
你必须给它一个构造函数并在构造函数内部,将它设置为opaque:

public BooleanRenderer() {
  setOpaque(true);
}

否则JLabel根本不会显示任何背景颜色。

对于您的JTable单元格编辑器:

  • 首先,我必须建议不要使用您的设计,因为要让用户输入正确的文字,“T”或“F”太容易出现用户输入错误。最好给他一个选择,比如使用JComboBox。
  • 接下来,摆脱编辑器中的if (isSelected)块。编辑器将在需要时被调用,并且选中的代码可能会错误,导致代码无法正常运行。
  • 最重要的是:摆脱编辑的布尔字段。在getCellEditorValue()方法中,查询组件的值并根据此值返回相应的布尔值。

例如:

public class BooleanEditor extends AbstractCellEditor implements TableCellEditor {

   JComboBox<Boolean> combo = new JComboBox<Boolean>(new Boolean[] {
         Boolean.TRUE, Boolean.FALSE });

   public BooleanEditor() {
      combo.setRenderer(new DefaultListCellRenderer() {
         @Override
         public Component getListCellRendererComponent(JList<?> list,
               Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Boolean boolValue = (Boolean) value;
            String displayString = "";
            if (boolValue == null) {
               displayString = "";
            } else if (boolValue) {
               displayString = "T";
            } else {
               displayString = "F";
            }
            return super.getListCellRendererComponent(list, displayString,
                  index, isSelected, cellHasFocus);
         }
      });
   }

   @Override
   public Object getCellEditorValue() {
      return combo.getSelectedItem();
   }

   @Override
   public Component getTableCellEditorComponent(JTable table, Object value,
         boolean isSelected, int row, int column) {
      if (value == null) {
         combo.setSelectedIndex(-1);
      } else {
         combo.setSelectedItem((Boolean) value);
      }
      return combo;
   }
}

我的整个SSCCE

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class BoolColorTable {
   @SuppressWarnings("serial")
   private static void createAndShowGui() {
      // null just to test how code will react to this situation
      // that hopefully won't occur
      Boolean[][] data = { null, { true }, { false }, { true }, { false },
            { false }, { true } };
      String[] colNames = { "Data" };
      DefaultTableModel model = new DefaultTableModel(data, colNames);
      JTable table = new JTable(model) {
         @Override
         public Class<?> getColumnClass(int column) {
            if (column == 0) {
               return Boolean.class;
            }
            return super.getColumnClass(column);
         }
      };

      table.setDefaultRenderer(Boolean.class, new BooleanRenderer());
      table.setDefaultEditor(Boolean.class, new BooleanEditor());

      JScrollPane mainPanel = new JScrollPane(table);

      JFrame frame = new JFrame("BoolColorTable");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class BooleanRenderer extends JLabel implements TableCellRenderer {
   public BooleanRenderer() {
      setOpaque(true);
   }

   @Override
   public Component getTableCellRendererComponent(JTable table, Object value,
         boolean isSelected, boolean hasFocus, int row, int column) {
      Boolean boolValue = (Boolean) value;
      if (boolValue == null) {
         setBackground(null);
      } else {
         if (!boolValue) {
            this.setBackground(Color.red);
         } else {
            this.setBackground(Color.BLACK);
         }
      }
      return this;
   }
}

@SuppressWarnings("serial")
class BooleanEditor extends AbstractCellEditor implements TableCellEditor {

   JComboBox<Boolean> combo = new JComboBox<Boolean>(new Boolean[] {
         Boolean.TRUE, Boolean.FALSE });

   public BooleanEditor() {
      combo.setRenderer(new DefaultListCellRenderer() {
         @Override
         public Component getListCellRendererComponent(JList<?> list,
               Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Boolean boolValue = (Boolean) value;
            String displayString = "";
            if (boolValue == null) {
               displayString = "";
            } else if (boolValue) {
               displayString = "T";
            } else {
               displayString = "F";
            }
            return super.getListCellRendererComponent(list, displayString,
                  index, isSelected, cellHasFocus);
         }
      });
   }

   @Override
   public Object getCellEditorValue() {
      return combo.getSelectedItem();
   }

   @Override
   public Component getTableCellEditorComponent(JTable table, Object value,
         boolean isSelected, int row, int column) {
      if (value == null) {
         combo.setSelectedIndex(-1);
      } else {
         combo.setSelectedItem((Boolean) value);
      }
      return combo;
   }
}

修改
如果您绝对需要允许用户输入“T”或“F”,那么您可以通过向编辑器的JTextField添加DocumentFilter来实现这一点,并使其大部分都是白痴证明只有三个不区分大小写的文本字段条目:“t”,“f”或空。

例如:

@SuppressWarnings("serial")
class BooleanStringEditor extends AbstractCellEditor implements TableCellEditor {
   private JTextField textField = new JTextField();

   public BooleanStringEditor() {
      PlainDocument doc = (PlainDocument) textField.getDocument();
      doc.setDocumentFilter(new MyDocFilter());
   }

   @Override
   public Object getCellEditorValue() {
      if (textField.getText().equalsIgnoreCase("t")) {
         return Boolean.TRUE;
      } else if (textField.getText().equalsIgnoreCase("f")) {
         return Boolean.FALSE;
      }
      // default if user messes up
      return null;
   }

   @Override
   public Component getTableCellEditorComponent(JTable table, Object value,
         boolean isSelected, int row, int column) {
      Boolean boolValue = (Boolean) value;
      if (boolValue == null) {
         textField.setText("");
      } else if (boolValue) {
         textField.setText("T");
      } else {
         textField.setText("F");
      }
      return textField;
   }

}

class MyDocFilter extends DocumentFilter {

   private boolean test(String text) {
      if (text.isEmpty()) {
         return true;
      }
      if (text.equalsIgnoreCase("t") || text.equalsIgnoreCase("f")) {
         return true;
      }
      return false;
   }

   @Override
   public void insertString(FilterBypass fb, int offset, String string,
         AttributeSet attr) throws BadLocationException {

      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.insert(offset, string);

      if (test(sb.toString())) {
         super.insertString(fb, offset, string, attr);
      } else {
         // warn the user and don't allow the insert
      }
   }

   @Override
   public void replace(FilterBypass fb, int offset, int length, String text,
         AttributeSet attrs) throws BadLocationException {

      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.replace(offset, offset + length, text);

      if (test(sb.toString())) {
         super.replace(fb, offset, length, text, attrs);
      } else {
         // warn the user and don't allow the insert
      }

   }

   @Override
   public void remove(FilterBypass fb, int offset, int length)
         throws BadLocationException {
      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.delete(offset, offset + length);

      if (test(sb.toString())) {
         super.remove(fb, offset, length);
      } else {
         // warn the user and don't allow the insert
      }

   }
}