概要
JTable
のセルエディタ、セルレンダラに設定したJCheckBox
のチェックアイコンをJTable
の行の高さに応じてリサイズします。
Screenshot
Advertisement
サンプルコード
class ScaledIcon implements Icon {
private final Icon icon;
private final int width;
private final int height;
protected ScaledIcon(Icon icon, int width, int height) {
this.icon = icon;
this.width = width;
this.height = height;
}
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.translate(x, y);
double sx = width / (double) icon.getIconWidth();
double sy = height / (double) icon.getIconHeight();
g2.scale(sx, sy);
icon.paintIcon(c, g2, 0, 0);
g2.dispose();
}
@Override public int getIconWidth() {
return width;
}
@Override public int getIconHeight() {
return height;
}
}
class CheckBoxIcon implements Icon {
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
if (!(c instanceof AbstractButton)) {
return;
}
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.translate(x, y);
g2.setPaint(Color.DARK_GRAY);
float s = Math.min(getIconWidth(), getIconHeight()) * .05f;
float w = getIconWidth() - s - s;
float h = getIconHeight() - s - s;
float gw = w / 8f;
float gh = h / 8f;
g2.setStroke(new BasicStroke(s));
g2.draw(new Rectangle2D.Float(s, s, w, h));
AbstractButton b = (AbstractButton) c;
if (b.getModel().isSelected()) {
g2.setStroke(new BasicStroke(3f * s));
Path2D p = new Path2D.Float();
p.moveTo(x + 2f * gw, y + .5f * h);
p.lineTo(x + .4f * w, y + h - 2f * gh);
p.lineTo(x + w - 2f * gw, y + 2f * gh);
g2.draw(p);
}
g2.dispose();
}
@Override public int getIconWidth() {
return 1000;
}
@Override public int getIconHeight() {
return 1000;
}
}
View in GitHub: Java, Kotlin解説
CheckBoxIcon
Path2D
で作成したチェック図形を描画するサイズ1000x1000px
のIcon
を作成UIManager.getIcon("CheckBox.icon")
でLookAndFeel
デフォルトのIcon
を使用しても良いがWindowsLookAndFeel
の場合チェックマークが拡大でモザイクになってしまう
ScaledIcon
Icon#paintIcon(...)
をオーバーライドしてGraphics2D.scale(double, double)
で指定した値(このサンプルでは行の高さの40px
)まで縮小して描画する別Icon
でラップ
- セルエディタ、セルレンダラ用の
JCheckBox
にJCheckBox#setIcon(...)
で設定JTable#prepareRenderer(...)
とJTable#prepareEditor(...)
をオーバーライドして上記のScaledIcon
を行の高さに調整して設定
JTable table = new JTable(model) {
private final Insets iconIns = new Insets(4, 4, 4, 4);
private final transient Icon checkIcon = new CheckBoxIcon();
@Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (c instanceof JCheckBox) {
int s = getRowHeight(row) - iconIns.top - iconIns.bottom;
JCheckBox cb = (JCheckBox) c;
cb.setIcon(new ScaledIcon(checkIcon, s, s));
cb.setBorderPainted(false);
}
return c;
}
@Override public Component prepareEditor(TableCellEditor editor, int row, int column) {
Component c = super.prepareEditor(editor, row, column);
if (c instanceof JCheckBox) {
int s = getRowHeight(row) - iconIns.top - iconIns.bottom;
JCheckBox cb = (JCheckBox) c;
cb.setIcon(new ScaledIcon(checkIcon, s, s));
cb.setBackground(getSelectionBackground());
}
return c;
}
};
table.setRowHeight(40);
table.setSelectionBackground(Color.WHITE);