Swing/TriStateCheckBox のバックアップの現在との差分(No.3)
TITLE:JCheckBoxに不定状態のアイコンを追加する
Posted by aterai at 2011-12-12
JCheckBoxに不定状態のアイコンを追加する
JCheckBoxの選択状態、非選択状態に加えて、不定状態を表すアイコンを追加します。- category: swing folder: TriStateCheckBox title: JCheckBoxに不定状態のアイコンを追加する tags: [JCheckBox, Icon, UIManager, JTableHeader, JTable] author: aterai pubdate: 2011-12-12T15:00:11+09:00 description: JCheckBoxの選択状態、非選択状態に加えて不定状態を表すアイコンを追加します。 image:
概要
JCheckBox
の選択状態、非選択状態に加えて不定状態を表すアイコンを追加します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spanadd
class TriStateCheckBox extends JCheckBox {
#spanend
private transient TriStateActionListener listener;
private transient Icon icon;
#spandel
**サンプルコード [#a11c010e]
#spanend
#spandel
#code{{
#spanend
#spandel
JCheckBox checkBox = new JCheckBox("TriState JCheckBox") {
#spanend
protected TriStateActionListener listener = null;
class TriStateActionListener implements ActionListener{
protected Icon icon;
public void setIcon(Icon icon) {
this.icon = icon;
protected TriStateCheckBox(String title) {
super(title);
}
#spanadd
#spanend
public void updateStatus(Status s) {
switch (s) {
case SELECTED:
setSelected(true);
setIcon(null);
break;
case DESELECTED:
setSelected(false);
setIcon(null);
break;
case INDETERMINATE:
setSelected(false);
setIcon(icon);
break;
default:
throw new AssertionError("Unknown Status");
}
@Override public void actionPerformed(ActionEvent e) {
JCheckBox cb = (JCheckBox)e.getSource();
if(!cb.isSelected()) {
cb.setIcon(icon);
}else if(cb.getIcon()!=null){
cb.setIcon(null);
cb.setSelected(false);
}
}
}
#spanadd
#spanend
@Override public void updateUI() {
final Icon oi = getIcon();
setIcon(null);
removeActionListener(listener);
setIcon(null);
super.updateUI();
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
if(listener==null) {
listener = new TriStateActionListener();
}
Icon icon = new IndeterminateIcon();
listener.setIcon(icon);
addActionListener(listener);
if(oi!=null) {
setIcon(icon);
}
}
});
listener = new TriStateActionListener();
icon = new IndeterminateIcon();
listener.setIcon(icon);
addActionListener(listener);
if (Objects.nonNull(getIcon())) {
setIcon(icon);
}
}
#spandel
};
#spanend
#spandel
View in GitHub: Java, Kotlin#spanend
class IndeterminateIcon implements Icon {
private final Color color = UIManager.getColor("CheckBox.foreground");
private final Icon icon = UIManager.getIcon("CheckBox.icon");
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
icon.paintIcon(c, g, x, y);
int w = getIconWidth(), h = getIconHeight();
int a = 4, b = 2;
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(Color.BLACK);
g2.translate(x, y);
g2.fillRect(a, (h-b)/2, w-a-a, b);
g2.translate(-x, -y);
}
@Override public int getIconWidth() { return icon.getIconWidth(); }
@Override public int getIconHeight() { return icon.getIconHeight(); }
// private FOREGROUND = UIManager.getColor("CheckBox.foreground");
private static final Color FOREGROUND = Color.BLACK;
private static final int MARGIN = 4;
private static final int HEIGHT = 2;
private final Icon icon = UIManager.getIcon("CheckBox.icon");
#spanadd
#spanend
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g.create();
g2.translate(x, y);
icon.paintIcon(c, g2, 0, 0);
g2.setPaint(FOREGROUND);
g2.fillRect(
MARGIN,
(getIconHeight() - HEIGHT) / 2,
getIconWidth() - MARGIN - MARGIN,
HEIGHT);
g2.dispose();
}
#spanadd
#spanend
@Override public int getIconWidth() {
return icon.getIconWidth();
}
#spanadd
#spanend
@Override public int getIconHeight() {
return icon.getIconHeight();
}
}
#spanadd
#spanend
#spanadd
enum Status {
#spanend
SELECTED, DESELECTED, INDETERMINATE
#spanadd
}
#spanend
解説
上記のサンプルでは、UIManager.getIcon("CheckBox.icon");で取得した非選択状態のチェックボックスアイコンの上に横棒を引いて不定状態のアイコンを作成しています。解説
-
UIManager.getIcon("CheckBox.icon")
で取得した非選択状態のチェックボックスアイコンの上に一本の横棒を引いて不定状態のアイコンを作成 -
JCheckBox#getIcon()
がnull
の場合、チェックボックスは不定状態であると判定して上記の不定状態のアイコンを表示 - 横棒の色は
UIManager.getColor("CheckBox.foreground")
を使用しているがLookAndFeel
によっては無意味 - JTableHeaderにJCheckBoxを追加してセルの値を切り替えるで使用すると
NimbusLookAndFeel
でアイコンと文字列のベースラインがずれる?- 文字列も
ImageIcon
にして回避
- 文字列も
-
NimbusLookAndFeel
で不定状態アイコンのフォーカスやロールオーバーが表示されない
- 不定状態かどうかは、JCheckBox#getIcon()がnullかどうかで判断する手抜き版
- 横棒の色はUIManager.getColor("CheckBox.foreground");を使用しているが、LnFによっては無意味
- JTableHeaderにJCheckBoxを追加してセルの値を切り替える で使用すると、Nimbus LnF の場合だけ、アイコンと文字列のベースラインがずれる?
- Nimbus LnF で、不定状態アイコンのフォーカスやロールオーバーが表示されない
参考リンク
参考リンク
- JavaSpecialists 145 - TristateCheckBox Revisited
- swing - Tristate Checkboxes in Java - Stack Overflow