TITLE:JTableのセルがクリップされている場合のみJToolTipを表示
Posted by aterai at 2009-10-12

JTableのセルがクリップされている場合のみJToolTipを表示

JTableのセルがクリップされている場合のみJToolTipを表示します。
  • category: swing folder: ClippedCellTooltips title: JTableのセルがクリップされている場合のみJToolTipを表示 tags: [JTable, JTableHeader, TableCellRenderer, JToolTip] author: aterai pubdate: 2009-10-12T17:37:22+09:00 description: JTableのセルがクリップされている場合のみJToolTipを表示します。 image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTJNQAyg-I/AAAAAAAAAUA/F6oQbiUShl4/s800/ClippedCellTooltips.png

概要

JTableのセルがクリップされている場合のみJToolTipを表示します。
ClippedCellTooltips.png

サンプルコード

#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
class ToolTipHeaderRenderer implements TableCellRenderer {
  private final TableCellRenderer renderer;
  private final Icon icon = UIManager.getIcon("Table.ascendingSortIcon");
  public ToolTipHeaderRenderer(TableCellRenderer renderer) {
    this.renderer = renderer;
  }
  public Component getTableCellRendererComponent(JTable table,Object value,
          boolean isSelected, boolean hasFocus, int row, int column) {
    JLabel l = (JLabel)renderer.getTableCellRendererComponent(
      table, value, isSelected, hasFocus, row, column);
    Insets i = l.getInsets();
    Rectangle rect = table.getCellRect(row, column, false);
    rect.width -= i.left + i.right;
    RowSorter<? extends TableModel> sorter = table.getRowSorter();
    if(sorter!=null && !sorter.getSortKeys().isEmpty()
                    && sorter.getSortKeys().get(0).getColumn()==column) {
      rect.width -= icon.getIconWidth() + 2; //XXX
  // private final Icon icon = UIManager.getIcon("Table.ascendingSortIcon");
  @Override public Component getTableCellRendererComponent(JTable table,
      Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    JTableHeader header = table.getTableHeader();
    TableCellRenderer r = header.getDefaultRenderer();
    Component c = r.getTableCellRendererComponent(
        table, value, isSelected, hasFocus, row, column);
    if (c instanceof JLabel) {
      JLabel l = (JLabel) c;
      Insets i = l.getInsets();
      Rectangle rect = header.getHeaderRect(column);
      rect.width -= i.left + i.right;
      boolean isClipped = isClipped(l, rect);
      // isClipped = fontMetrics.stringWidth(l.getText()) > rect.width;
      l.setToolTipText(isClipped ? l.getText() : header.getToolTipText());
    }
    FontMetrics fm = l.getFontMetrics(l.getFont());
    String str = value.toString();
    int cellTextWidth = fm.stringWidth(str);
    l.setToolTipText(cellTextWidth>rect.width?str:null);
    return l;
    return c;
  }
#spanadd

#spanend
  private static boolean isClipped(JLabel label, Rectangle viewR) {
    Rectangle iconR = new Rectangle();
    Rectangle textR = new Rectangle();
    String str = SwingUtilities.layoutCompoundLabel(
        label,
        label.getFontMetrics(label.getFont()),
        label.getText(),
        label.getIcon(),
        label.getVerticalAlignment(),
        label.getHorizontalAlignment(),
        label.getVerticalTextPosition(),
        label.getHorizontalTextPosition(),
        viewR,
        iconR,
        textR,
        label.getIconTextGap());
    return !Objects.equals(label.getText(), str);
  }
}

解説

  • ヘッダセル
    • TableCellRendererで、セルの幅と文字列の長さを比較して、ToolTipを設定
    • ソートアイコンと文字列の間のgapが不明?

解説

  • ヘッダセル
    • TableCellRenderer内でセルの幅と文字列の長さを比較しToolTipを設定
    • ソートアイコンなどが存在する場合を考慮してSwingUtilities.layoutCompoundLabel(...)メソッドを使用してJLabel内の文字列が省略されているかどうかを判断する
    • ソートアイコンと文字列の間隔はJLabel#getIconTextGap()で取得してセル幅から除外する
      • Windows 10で使用されるWindowsLookAndFeelのように文字列の上にソートアイコンが表示される場合(TableCellRenderer#getIcon()null)はこのアイコンの幅を無視する
  • セル
    • JTable#prepareRendererメソッドをオーバーライドし、セルの幅と文字列の長さを比較してToolTipを設定
  • セル
    • JTable#prepareRendererメソッドをオーバーライドし、セルの幅と文字列の長さを比較して、ToolTipを設定
JTable table = new JTable(model) {
  public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
  @Override public Component prepareRenderer(
      TableCellRenderer tcr, int row, int column) {
    Component c = super.prepareRenderer(tcr, row, column);
    if(c instanceof JComponent) {
       JComponent l = (JComponent)c;
       Object o = getValueAt(row, column);
       Insets i = l.getInsets();
       Rectangle rect = getCellRect(row, column, false);
       rect.width -= i.left + i.right;
       FontMetrics fm = l.getFontMetrics(l.getFont());
       String str = o.toString();
       int cellTextWidth = fm.stringWidth(str);
       l.setToolTipText(cellTextWidth>rect.width?str:null);
    if (c instanceof JComponent) {
      JComponent l = (JComponent) c;
      Insets i = l.getInsets();
      Rectangle rect = getCellRect(row, column, false);
      rect.width -= i.left + i.right;
      FontMetrics fm = l.getFontMetrics(l.getFont());
      String str = Objects.toString(getValueAt(row, column), "");
      int cellTextWidth = fm.stringWidth(str);
      l.setToolTipText(cellTextWidth > rect.width ? str : getToolTipText());
    }
    return c;
  }
};

参考リンク

参考リンク

コメント

コメント