Ich weiß nicht, warum jemand die Lösungen mit zusätzlichen Symbolen png-Dateien geben würde, während java api für großen funcionality gibt überschreiben paintIcon (..) Methode.
Die beste leichte Lösung zum Merken des CheckBox-Status ist IMO ClientProperty Attribut.
/*
* Tri-state checkbox example
* @s1w_
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class TCheckBox extends JCheckBox implements Icon, ActionListener {
final static boolean MIDasSELECTED = true; //consider mid-state as selected ?
public TCheckBox() { this(""); }
public TCheckBox(String text) {
super(text);
putClientProperty("SelectionState", 0);
setIcon(this);
addActionListener(this);
}
public TCheckBox(String text, int sel) {
/* tri-state checkbox has 3 selection states:
* 0 unselected
* 1 mid-state selection
* 2 fully selected
*/
super(text, sel > 1 ? true : false);
switch (sel) {
case 2: setSelected(true);
case 1:
case 0:
putClientProperty("SelectionState", sel);
break;
default:
throw new IllegalArgumentException();
}
addActionListener(this);
setIcon(this);
}
@Override
public boolean isSelected() {
if (MIDasSELECTED && (getSelectionState() > 0)) return true;
else return super.isSelected();
}
public int getSelectionState() {
return (getClientProperty("SelectionState") != null ? (int)getClientProperty("SelectionState") :
super.isSelected() ? 2 :
0);
}
public void setSelectionState(int sel) {
switch (sel) {
case 2: setSelected(true);
break;
case 1:
case 0: setSelected(false);
break;
default: throw new IllegalArgumentException();
}
putClientProperty("SelectionState", sel);
}
final static Icon icon = UIManager.getIcon("CheckBox.icon");
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
icon.paintIcon(c, g, x, y);
if (getSelectionState() != 1) return;
int w = getIconWidth();
int h = getIconHeight();
g.setColor(c.isEnabled() ? new Color(51, 51, 51) : new Color(122, 138, 153));
g.fillRect(x+4, y+4, w-8, h-8);
if (!c.isEnabled()) return;
g.setColor(new Color(81, 81, 81));
g.drawRect(x+4, y+4, w-9, h-9);
}
@Override
public int getIconWidth() {
return icon.getIconWidth();
}
@Override
public int getIconHeight() {
return icon.getIconHeight();
}
public void actionPerformed(ActionEvent e) {
TCheckBox tcb = (TCheckBox)e.getSource();
if (tcb.getSelectionState() == 0)
tcb.setSelected(false);
tcb.putClientProperty("SelectionState", tcb.getSelectionState() == 2 ? 0 :
tcb.getSelectionState() + 1);
// test
System.out.println(">>>>IS SELECTED: "+tcb.isSelected());
System.out.println(">>>>IN MID STATE: "+(tcb.getSelectionState()==1));
}
}
Nutzung: TCheckBox tcb = new TCheckBox("My CheckBox");
+1 gute Idee. Wenn eine UI-Komponente schwer zu programmieren und nicht standardkonform ist, wird dies auch für den Benutzer so aussehen. Wann haben Sie das letzte Mal auf diese Weise ein Kontrollkästchen mit drei Zuständen verwendet? Ich habe nie. –
Obwohl ich dem Punkt von @byron zustimme, ist eine Checkbox mit drei Zuständen tatsächlich vom Standpunkt des Benutzers ziemlich normal. –
Welche Benutzer? Ich bin ein Entwickler und Power-User, und ich verachte Tri-State-Checkboxen, normalerweise weil es nicht klar ist, was der dritte Zustand bedeutet; In der Regel bedeutet dies, dass einige Details vor Ihnen verborgen sind. Es ist ein Albtraum der Benutzerfreundlichkeit und Zugänglichkeit. – Rob