Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的三态复选框_Java_Swing_Checkbox - Fatal编程技术网

Java中的三态复选框

Java中的三态复选框,java,swing,checkbox,Java,Swing,Checkbox,我真的可以在Java中使用三态复选框。这听起来很简单,但我只见过真正的[注:链接现在断开] 在我的例子中,三个单选按钮占用了太多的空间,可能会让用户感到困惑。它基本上是一个搜索对话框。我需要正确、错误或“不在乎”选项。人们使用的是不同的技巧吗?使用下拉菜单。我会使用你发布的技巧 只要您的复杂性在另一个类中(有效),并且它的行为与任何其他控件一样,谁会在乎呢?(这似乎是所有swing背后的假设,大多数swing类似乎都很复杂。)认为“丑陋的实现”是一个古老的链接。该页面上的一条建议是几年前更新的。

我真的可以在Java中使用三态复选框。这听起来很简单,但我只见过真正的[注:链接现在断开]


在我的例子中,三个单选按钮占用了太多的空间,可能会让用户感到困惑。它基本上是一个搜索对话框。我需要正确、错误或“不在乎”选项。人们使用的是不同的技巧吗?

使用下拉菜单。

我会使用你发布的技巧

只要您的复杂性在另一个类中(有效),并且它的行为与任何其他控件一样,谁会在乎呢?(这似乎是所有swing背后的假设,大多数swing类似乎都很复杂。)

认为“丑陋的实现”是一个古老的链接。该页面上的一条建议是几年前更新的。我还没有测试旧的实现,所以我不知道新的实现是更好还是更差


更改用户界面。“三态”复选框是不寻常的,它确实会让用户感到困惑。下拉列表是一个很好的选择,但对于对话框中的多次出现,它也会给用户带来很多困惑。

我找到了一种方法,通过简单地添加一个侦听器来创建一个三态复选框:


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

在所有的反馈之后,我认为下拉列表可能是一个更好的选择。但是,我想在这里为大家分享我的代码。

三态复选框是带有部分选中子节点的TreeView的标准UI习惯用法。它们广泛应用于复杂层次视图(如Google Earth)中的层管理。

JIDE在其中公开了一些非常好的功能,其中一个恰好是三态复选框

我建议您去运行,看看它是否满足您的需要

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

样本框架:

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文件的解决方案,而JavaAPI提供了覆盖paintIcon(..)方法的强大功能

记住复选框状态的最佳轻量级解决方案是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(“我的复选框”)

+1好主意。如果UI组件很难编码且不标准,那么用户也会有这种感觉。您上次以这种方式使用三态复选框是什么时候?我从来没有。虽然我同意@byron的观点,但从用户的角度来看,三态复选框实际上是相当标准的。哪些用户?我是一个开发者和超级用户,我鄙视三态复选框,通常是因为不清楚第三态是什么意思;通常,这意味着某些细节对您隐藏。这是一个可用性和可访问性的噩梦。大多数时候,这意味着复选框适用于一类事物,这些事物有不同的状态,你不希望它们被改变。检查它会检查它们,将其保留在第三种状态以不更改它。即使是超级用户也很常见。三状态复选框的典型用法:更改多对象选择的属性,灰色+选定的第三状态表示“某些项目具有此属性,而某些项目没有,我不会更改任何项目”。是的,我认为亨氏卡布兹在这方面做得非常好。我也会推荐!我们将这种方法用于表示开/关状态聚合的复选框。交互切换所有开/关,中间状态只能通过与单个元素的交互来达到。它工作得很好,而且我认为它在UI设计方面更合理。那么为什么要使用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));
    }
}