Java中的三态复选框

我真的可以在Java中使用三态复选框。 这听起来很简单,但我只看到了非常难看的实现 [注意:链接现在已经破了]。

三个单选按钮只占用太多空间,在我的情况下可能会让用户感到困惑。 它基本上用于搜索对话框。 我需要真实,虚假或“不关心”的选择。 是否有人们使用的不同技术?

使用下拉菜单。

我找到了一种通过简单地添加一个监听器来制作三态复选框的方法:

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); } } } 

然后在应用程序代码中,它只是一行:

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

在得到所有反馈之后,我认为下拉可能是更好的选择。 但是,我想在这里为其他人分享我的代码。

在此处输入图像描述

在此实现中,只能通过编程方式设置三个状态。 为了外观和感觉便携它使用图像,必须放在同一个java包内。

在此处输入图像描述在此处输入图像描述在此处输入图像描述

 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(); } } } 

样本框架:

 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; } 

我不知道为什么有人会给这些解决方案添加额外的图标png文件,而java api覆盖 paintIcon(..)方法提供了很好的function。

记住CheckBox状态的最佳轻量级解决方案是IMO ClientProperty属性。

在此处输入图像描述

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

用法: TCheckBox tcb = new TCheckBox("My CheckBox");

JIDE在他们的公共层中开源了一些非常好的function,其中一个恰好是一个三态复选框

三态复选框

我建议你去运行webstart演示 ,看看它是否符合你的需求

“丑陋的实现”是一个旧的链接。 该页面上的一条建议在几年前就已更新。 我没有测试过旧的实现,所以我不知道新的实现是好还是坏。

重访TristateCheckBox

三态复选框是Treeviews的标准UI惯用语,具有部分检查的子节点。 它们广泛用于复杂层次结构视图(如Google Earth)中的图层管理。

我只想用你发布的那个。

只要你的复杂性在另一个类(有效)并且它就像任何其他控件一样,谁在乎呢? (这似乎是所有挥杆背后的假设,大多数挥杆类似乎是关于这个复杂的。)

更改用户界面。 三态复选框很不寻常,可能会让用户感到困惑。 下拉是一个不错的选择,但是在对话框中多出一次,它也会给用户带来很多困惑。