2009-08-11 18 views
11

Ich könnte wirklich eine dreistufige Checkbox in Java verwenden. Es klingt wie eine einfache Sache, aber ich habe nur wirklich gesehen ugly implementations [Hinweis: Link jetzt gebrochen].Tristate Checkboxes in Java

Drei Radiobuttons nehmen nur zu viel Grundbesitz auf und werden in meinem Fall für die Benutzer wahrscheinlich verwirrend sein. Es ist im Grunde für einen Suchdialog. Ich brauche wahre, falsche oder "egal" Optionen. Gibt es eine andere Technik, die Menschen benutzen?

Antwort

5

ich einen Weg, um eine Tri-State-Checkbox machen gefunden, indem einfach einen Zuhörer:


public class TriStateActionListener implements ActionListener{ 
    final protected Icon icon; 

    public TriStateActionListener(Icon icon){ 
     this.icon=icon; 
    } 

    public static Boolean getState(javax.swing.JCheckBox cb){ 
     if (cb.getIcon()==null) return null; 
     if (cb.isSelected()) return true; 
     else return false; 
    } 

    public void actionPerformed(ActionEvent e) { 
     javax.swing.JCheckBox cb=(javax.swing.JCheckBox)e.getSource(); 
     if (!cb.isSelected()){ 
      cb.setIcon(icon); 
     } 
     else if (cb.getIcon()!=null){ 
      cb.setIcon(null); 
      cb.setSelected(false); 
     } 
    } 
} 

dann in dem Anwendungscode, es ist nur eine einzige Zeile:


jCheckBox1.addActionListener(new TriStateActionListener(getResourceMap().getIcon("TriStateIcon"))); 

Nachdem all Feedback, ich denke ein Drop-Down könnte eine bessere Wahl sein. Aber ich wollte meinen Code hier für alle anderen teilen.

14

Verwenden Sie eine Dropdown-Liste.

+1

+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. –

+8

Obwohl ich dem Punkt von @byron zustimme, ist eine Checkbox mit drei Zuständen tatsächlich vom Standpunkt des Benutzers ziemlich normal. –

+5

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

0

Ich würde nur die von Ihnen gepostete verwenden.

Solange Ihre Komplexität in einer anderen Klasse (das funktioniert) und es funktioniert genau wie jede andere Kontrolle, wen interessiert das? (Das scheint die Annahme hinter allem Swing zu sein, scheinen die meisten Swing-Klassen über diese kompliziert.)

2

Diese "hässliche Implementierungen" ist ein alter Link. Einer der Vorschläge auf dieser Seite wurde vor ein paar Jahren aktualisiert. Ich habe die alte Implementierung nicht getestet, also weiß ich nicht, ob die neue besser oder schlechter ist.

TristateCheckBox Revisited

+0

Ja, ich denke, Heinz Kabutz, das ist sehr gut gemacht. Ich würde das auch empfehlen! – codevour

0

Ändern der UI. Tristate Check-Box ist ungewöhnlich und kann Benutzer wirklich verwirren. Das Drop-down ist eine gute Option, aber für mehr als ein Vorkommen im Dialog bringt es auch eine Menge Verwirrung für den Benutzer mit sich.

2

Tristate-Kontrollkästchen sind Standard-UI-Idiome für Baumansichten mit teilweise überprüften untergeordneten Knoten. Sie werden in der Ebenenverwaltung in komplexen hierarchischen Ansichten wie Google Earth häufig verwendet.

3

JIDE haben Open Source einige sehr schöne Funktionalität in ihre Common Layer, von denen ein Tri-State-Checkbox

Tristate checkboxes

passiert sein würde ich vorschlagen, dass Sie die webstart demo laufen gehen, um zu sehen, ob es Ihren Bedürfnissen entspricht

4

enter image description here

In dieser Implementierung der drei Zustand kann nur über programmatisch festgelegt werden. Um tragbar zu sein, werden Bilder verwendet, die in dasselbe Java-Paket eingefügt werden müssen.

enter image description here enter image description here enter image description here

public class TristateCheckBox extends JCheckBox { 

    private static final long serialVersionUID = 1L; 
    private boolean halfState; 
    private static Icon selected = new javax.swing.ImageIcon(TristateCheckBox.class.getResource("selected.png")); 
    private static Icon unselected = new javax.swing.ImageIcon(TristateCheckBox.class.getResource("unselected.png")); 
    private static Icon halfselected = new javax.swing.ImageIcon(TristateCheckBox.class.getResource("halfselected.png")); 

    @Override 
    public void paint(Graphics g) { 
     if (isSelected()) { 
      halfState = false; 
     } 
     setIcon(halfState ? halfselected : isSelected() ? selected : unselected); 
     super.paint(g); 
    } 

    public boolean isHalfSelected() { 
     return halfState; 
    } 

    public void setHalfSelected(boolean halfState) { 
     this.halfState = halfState; 
     if (halfState) { 
      setSelected(false); 
      repaint(); 
     } 
    } 
} 

Probenrahmen:

public class NewJFrame19 extends javax.swing.JFrame { 

    private final TristateCheckBox myCheckBox; 

    public NewJFrame19() { 
     myCheckBox = new TristateCheckBox(); 
     myCheckBox.setText("123123"); 
     add(myCheckBox); 

     jButton1 = new javax.swing.JButton(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     getContentPane().setLayout(new java.awt.FlowLayout()); 

     jButton1.setText("jButton1"); 
     jButton1.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       jButton1ActionPerformed(evt); 
      } 
     }); 
     getContentPane().add(jButton1); 

     pack(); 
    } 

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     myCheckBox.setHalfSelected(true); 
    }           

    public static void main(String args[]) { 

     try { 
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
       if ("Windows".equals(info.getName())) { 
        javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (ClassNotFoundException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (InstantiationException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (IllegalAccessException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } 
     /* Create and display the form */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       new NewJFrame19().setVisible(true); 
      } 
     }); 
    } 
    private javax.swing.JButton jButton1; 
} 
+1

Wir verwendeten diesen Ansatz für ein Kontrollkästchen, das die Aggregation von Ein/Aus-Zuständen bezeichnet. Interaktion schaltet alle ein/aus, der Zwischenzustand ist nur über Interaktion mit den einzelnen Elementen erreichbar. Funktioniert sehr gut und ich denke, es ist mehr Sound in Bezug auf UI-Design. –

3

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.

enter image description here

/* 
* 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");

Verwandte Themen