JTable 标题中的复选框与 Nimbus L&F 的呈现方式不同

发布于 2025-01-07 08:13:32 字数 1166 浏览 0 评论 0原文

我在 JTable 标题中有复选框,我使用 Nimbus L&F 并自定义标题背景,但复选框的背景采用默认的灰色背景,而不是像其他列那样自定义背景。

以下是 CheckboxRenderer 类

public class CheckBoxHeader extends JCheckBox implements TableCellRenderer{

public CheckBoxHeader(ItemListener itemListener) {      
    addItemListener(itemListener);
    setHorizontalAlignment(SwingConstants.CENTER);
    setOpaque(true);        
}

public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {                    
        JTableHeader header = table.getTableHeader();           
        Color bg = header.getBackground();
        setBackground(new Color(bg.getRed(), bg.getGreen(), bg.getBlue()));     
    return this;
}

,在 Table

TableColumn tc = getColumnModel().getColumn(0);  
tc.setCellEditor(getDefaultEditor(Boolean.class));  
tc.setCellRenderer(getDefaultRenderer(Boolean.class));      
((JComponent)getDefaultRenderer(Boolean.class)).setOpaque(true);        
tc.setHeaderRenderer(new CheckBoxHeader());

AFAIK 中,要正确渲染应使用 DefaultTableCellRenderer 渲染的标头,但我没有找到它的方法。有什么建议吗?

I have Checkbox in JTable Header, I am using Nimbus L&F and customize the header background but the background of the checkbox takes the default grey background not the customize one as others column do.

Following is the CheckboxRenderer class

public class CheckBoxHeader extends JCheckBox implements TableCellRenderer{

public CheckBoxHeader(ItemListener itemListener) {      
    addItemListener(itemListener);
    setHorizontalAlignment(SwingConstants.CENTER);
    setOpaque(true);        
}

public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {                    
        JTableHeader header = table.getTableHeader();           
        Color bg = header.getBackground();
        setBackground(new Color(bg.getRed(), bg.getGreen(), bg.getBlue()));     
    return this;
}

And in Table

TableColumn tc = getColumnModel().getColumn(0);  
tc.setCellEditor(getDefaultEditor(Boolean.class));  
tc.setCellRenderer(getDefaultRenderer(Boolean.class));      
((JComponent)getDefaultRenderer(Boolean.class)).setOpaque(true);        
tc.setHeaderRenderer(new CheckBoxHeader());

AFAIK to get the proper rendering of the header it should render with DefaultTableCellRenderer but i am not getting the way for it. Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愚人国度 2025-01-14 08:13:32

我不太确定它是否适用于所有 LnF(仅测试 Windows 7、Java 1.7.0_03):

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class NimbusHeaderCheckBox {
  public JComponent makeUI() {
    Object[] columnNames = {Status.INDETERMINATE, "Integer", "String"};
    Object[][] data = {{true, 1, "b"}, {false, 9, "a"}, {true, 5, "c"}};
    DefaultTableModel model = new DefaultTableModel(data, columnNames) {
      @Override public Class<?> getColumnClass(int column) {
        return getValueAt(0, column).getClass();
      }
    };
    JTable table = new JTable(model);
    model.addTableModelListener(new HeaderCheckBoxHandler(table));

    TableCellRenderer r = new HeaderRenderer(table.getTableHeader(), 0);
    table.getColumnModel().getColumn(0).setHeaderRenderer(r);
    //<ins>
    TableCellRenderer leftAlign = new LeftAlignHeaderRenderer();
    table.getColumnModel().getColumn(1).setHeaderRenderer(leftAlign);
    table.getColumnModel().getColumn(2).setHeaderRenderer(leftAlign);
    //</ins>
    table.getTableHeader().setReorderingAllowed(false);
    return new JScrollPane(table);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() { createAndShowGUI(); }
    });
  }
  public static void createAndShowGUI() {
    try {
      //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels())
        if ("Nimbus".equals(laf.getName())) UIManager.setLookAndFeel(laf.getClassName());
    } catch(Exception e) {
      e.printStackTrace();
    }
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new NimbusHeaderCheckBox().makeUI());
    frame.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
class HeaderRenderer extends JCheckBox implements TableCellRenderer {
  public HeaderRenderer(JTableHeader header, final int targetColumnIndex) {
    super((String)null);
    setOpaque(false);
    setFont(header.getFont());
    header.addMouseListener(new MouseAdapter() {
      @Override public void mouseClicked(MouseEvent e) {
        JTableHeader header = (JTableHeader)e.getSource();
        JTable table = header.getTable();
        TableColumnModel columnModel = table.getColumnModel();
        int vci = columnModel.getColumnIndexAtX(e.getX());
        int mci = table.convertColumnIndexToModel(vci);
        if(mci == targetColumnIndex) {
          TableColumn column = columnModel.getColumn(vci);
          Object v = column.getHeaderValue();
          boolean b = Status.DESELECTED.equals(v)?true:false;
          TableModel m = table.getModel();
          for(int i=0; i<m.getRowCount(); i++) m.setValueAt(b, i, mci);
          column.setHeaderValue(b?Status.SELECTED:Status.DESELECTED);
        }
      }
    });
  }
  @Override public Component getTableCellRendererComponent(
      JTable tbl, Object val, boolean isS, boolean hasF, int row, int col) {
    if(val instanceof Status) {
      switch((Status)val) {
      case SELECTED:
        setSelected(true); setEnabled(true); break;
      case DESELECTED:
        setSelected(false); setEnabled(true); break;
      case INDETERMINATE:
        setSelected(true); setEnabled(false); break;
      }
    } else {
      setSelected(true); setEnabled(false);
    }
    TableCellRenderer r = tbl.getTableHeader().getDefaultRenderer();
    JLabel l=(JLabel)r.getTableCellRendererComponent(tbl, null, isS, hasF, row, col);

    l.setIcon(new CheckBoxIcon(this));
    l.setText(null); //XXX Nimbus LnF ???
    ////This block has no effect at all as all the columns are center aligned
    ////(pointed out by rcnpl)
    //if(tbl.convertColumnIndexToModel(col)==0) {
    //  l.setHorizontalAlignment(SwingConstants.CENTER);
    //} else {
    //  l.setHorizontalAlignment(SwingConstants.LEFT);
    //}
    //<ins>
    l.setHorizontalAlignment(SwingConstants.CENTER);
    //</ins>
    return l;
  }
}
//<ins>
class LeftAlignHeaderRenderer implements TableCellRenderer {
  @Override public Component getTableCellRendererComponent(
    JTable t, Object v, boolean isS, boolean hasF, int row, int col) {
    TableCellRenderer r = t.getTableHeader().getDefaultRenderer();
    JLabel l=(JLabel)r.getTableCellRendererComponent(t, v, isS, hasF, row, col);
    l.setHorizontalAlignment(SwingConstants.LEFT);
    return l;
  }
}
//</ins>
enum Status { SELECTED, DESELECTED, INDETERMINATE }
class CheckBoxIcon implements Icon {
  private final JCheckBox check;
  public CheckBoxIcon(JCheckBox check) {
    this.check = check;
  }
  @Override public int getIconWidth() {
    return check.getPreferredSize().width;
  }
  @Override public int getIconHeight() {
    return check.getPreferredSize().height;
  }
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    SwingUtilities.paintComponent(
        g, check, (Container)c, x, y, getIconWidth(), getIconHeight());
  }
}
class HeaderCheckBoxHandler implements TableModelListener {
  private final JTable table;
  public HeaderCheckBoxHandler(JTable table) {
    this.table = table;
  }
  @Override public void tableChanged(TableModelEvent e) {
    if(e.getType()==TableModelEvent.UPDATE && e.getColumn()==0) {
      int mci = 0;
      int vci = table.convertColumnIndexToView(mci);
      TableColumn column = table.getColumnModel().getColumn(vci);
      Object title = column.getHeaderValue();
      if(!Status.INDETERMINATE.equals(title)) {
        column.setHeaderValue(Status.INDETERMINATE);
      } else {
        int selected = 0, deselected = 0;
        TableModel m = table.getModel();
        for(int i=0; i<m.getRowCount(); i++) {
          if(Boolean.TRUE.equals(m.getValueAt(i, mci))) {
            selected++;
          } else {
            deselected++;
          }
        }
        if(selected==0) {
          column.setHeaderValue(Status.DESELECTED);
        } else if(deselected==0) {
          column.setHeaderValue(Status.SELECTED);
        } else {
          return;
        }
      }
      table.getTableHeader().repaint();
    }
  }
}

I'm not so sure if it work on all LnF(testing only Windows 7, Java 1.7.0_03):

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class NimbusHeaderCheckBox {
  public JComponent makeUI() {
    Object[] columnNames = {Status.INDETERMINATE, "Integer", "String"};
    Object[][] data = {{true, 1, "b"}, {false, 9, "a"}, {true, 5, "c"}};
    DefaultTableModel model = new DefaultTableModel(data, columnNames) {
      @Override public Class<?> getColumnClass(int column) {
        return getValueAt(0, column).getClass();
      }
    };
    JTable table = new JTable(model);
    model.addTableModelListener(new HeaderCheckBoxHandler(table));

    TableCellRenderer r = new HeaderRenderer(table.getTableHeader(), 0);
    table.getColumnModel().getColumn(0).setHeaderRenderer(r);
    //<ins>
    TableCellRenderer leftAlign = new LeftAlignHeaderRenderer();
    table.getColumnModel().getColumn(1).setHeaderRenderer(leftAlign);
    table.getColumnModel().getColumn(2).setHeaderRenderer(leftAlign);
    //</ins>
    table.getTableHeader().setReorderingAllowed(false);
    return new JScrollPane(table);
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() { createAndShowGUI(); }
    });
  }
  public static void createAndShowGUI() {
    try {
      //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels())
        if ("Nimbus".equals(laf.getName())) UIManager.setLookAndFeel(laf.getClassName());
    } catch(Exception e) {
      e.printStackTrace();
    }
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new NimbusHeaderCheckBox().makeUI());
    frame.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
class HeaderRenderer extends JCheckBox implements TableCellRenderer {
  public HeaderRenderer(JTableHeader header, final int targetColumnIndex) {
    super((String)null);
    setOpaque(false);
    setFont(header.getFont());
    header.addMouseListener(new MouseAdapter() {
      @Override public void mouseClicked(MouseEvent e) {
        JTableHeader header = (JTableHeader)e.getSource();
        JTable table = header.getTable();
        TableColumnModel columnModel = table.getColumnModel();
        int vci = columnModel.getColumnIndexAtX(e.getX());
        int mci = table.convertColumnIndexToModel(vci);
        if(mci == targetColumnIndex) {
          TableColumn column = columnModel.getColumn(vci);
          Object v = column.getHeaderValue();
          boolean b = Status.DESELECTED.equals(v)?true:false;
          TableModel m = table.getModel();
          for(int i=0; i<m.getRowCount(); i++) m.setValueAt(b, i, mci);
          column.setHeaderValue(b?Status.SELECTED:Status.DESELECTED);
        }
      }
    });
  }
  @Override public Component getTableCellRendererComponent(
      JTable tbl, Object val, boolean isS, boolean hasF, int row, int col) {
    if(val instanceof Status) {
      switch((Status)val) {
      case SELECTED:
        setSelected(true); setEnabled(true); break;
      case DESELECTED:
        setSelected(false); setEnabled(true); break;
      case INDETERMINATE:
        setSelected(true); setEnabled(false); break;
      }
    } else {
      setSelected(true); setEnabled(false);
    }
    TableCellRenderer r = tbl.getTableHeader().getDefaultRenderer();
    JLabel l=(JLabel)r.getTableCellRendererComponent(tbl, null, isS, hasF, row, col);

    l.setIcon(new CheckBoxIcon(this));
    l.setText(null); //XXX Nimbus LnF ???
    ////This block has no effect at all as all the columns are center aligned
    ////(pointed out by rcnpl)
    //if(tbl.convertColumnIndexToModel(col)==0) {
    //  l.setHorizontalAlignment(SwingConstants.CENTER);
    //} else {
    //  l.setHorizontalAlignment(SwingConstants.LEFT);
    //}
    //<ins>
    l.setHorizontalAlignment(SwingConstants.CENTER);
    //</ins>
    return l;
  }
}
//<ins>
class LeftAlignHeaderRenderer implements TableCellRenderer {
  @Override public Component getTableCellRendererComponent(
    JTable t, Object v, boolean isS, boolean hasF, int row, int col) {
    TableCellRenderer r = t.getTableHeader().getDefaultRenderer();
    JLabel l=(JLabel)r.getTableCellRendererComponent(t, v, isS, hasF, row, col);
    l.setHorizontalAlignment(SwingConstants.LEFT);
    return l;
  }
}
//</ins>
enum Status { SELECTED, DESELECTED, INDETERMINATE }
class CheckBoxIcon implements Icon {
  private final JCheckBox check;
  public CheckBoxIcon(JCheckBox check) {
    this.check = check;
  }
  @Override public int getIconWidth() {
    return check.getPreferredSize().width;
  }
  @Override public int getIconHeight() {
    return check.getPreferredSize().height;
  }
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    SwingUtilities.paintComponent(
        g, check, (Container)c, x, y, getIconWidth(), getIconHeight());
  }
}
class HeaderCheckBoxHandler implements TableModelListener {
  private final JTable table;
  public HeaderCheckBoxHandler(JTable table) {
    this.table = table;
  }
  @Override public void tableChanged(TableModelEvent e) {
    if(e.getType()==TableModelEvent.UPDATE && e.getColumn()==0) {
      int mci = 0;
      int vci = table.convertColumnIndexToView(mci);
      TableColumn column = table.getColumnModel().getColumn(vci);
      Object title = column.getHeaderValue();
      if(!Status.INDETERMINATE.equals(title)) {
        column.setHeaderValue(Status.INDETERMINATE);
      } else {
        int selected = 0, deselected = 0;
        TableModel m = table.getModel();
        for(int i=0; i<m.getRowCount(); i++) {
          if(Boolean.TRUE.equals(m.getValueAt(i, mci))) {
            selected++;
          } else {
            deselected++;
          }
        }
        if(selected==0) {
          column.setHeaderValue(Status.DESELECTED);
        } else if(deselected==0) {
          column.setHeaderValue(Status.SELECTED);
        } else {
          return;
        }
      }
      table.getTableHeader().repaint();
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文