2

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

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

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

基于这个 oracle 教程,我尝试制作我的渲染器和编辑器,并将其包含在这个 oracle 提供的示例中。

在布尔渲染器和布尔编辑器下方。我把他们注册到这个班级

        ....
        ....

        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;
    }
}
4

1 回答 1

4

对于您的渲染器
您必须给它一个构造函数,并在构造函数内部将其设置为不透明:

public BooleanRenderer() {
  setOpaque(true);
}

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

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

  • 首先,我必须反对你的设计,因为让用户输入正确的文本,“T”或“F”太容易出现用户输入错误。最好给他一个选择,例如使用 JComboBox。
  • 接下来,摆脱if (isSelected)编辑器中的块。编辑器将在需要时被调用,并且选择可能是错误的,使您的代码无法运行。
  • 最重要的是:摆脱编辑器的 bool 字段。在该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
      }

   }
}
于 2013-01-02T22:21:03.387 回答