java Java中的三态复选框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1263323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 15:51:29  来源:igfitidea点击:

Tristate Checkboxes in Java

javaswingcheckbox

提问by User1

I could really use a tri-stated checkbox in Java. It sounds like a simple thing, but I've only seen really ugly implementations[note: link now broken].

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

Three radio buttons just take up too much real estate and will probably be confusing for the users in my case. It's basically for a search dialog. I need true, false or "don't care" options. Is there a different technique that people use?

三个单选按钮占用了太多的空间,在我的情况下可能会让用户感到困惑。它基本上用于搜索对话框。我需要真、假或“不在乎”选项。人们使用不同的技术吗?

采纳答案by User1

I found a way to make a tri-state checkbox by simply adding a listener:

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


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

Then in the application code, it's just a single line:

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


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

After all the feedback, I'm thinking a drop-down may be a better choice. But, I wanted to share my code here for everyone else.

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

回答by Gandalf

Use a drop-down.

使用下拉菜单。

回答by Daniel De León

enter image description here

在此处输入图片说明

In this implementation the three state can be only set via programmatically. To be Look and Feel portable it use images, that must be placed inside the the same java package.

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

enter image description hereenter image description hereenter 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();
        }
    }
}

Sample frame:

示例框架:

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

回答by s1w_

I dont know why anyone would give the solutions with additional icon png files while java apigives great funcionality for overridingpaintIcon(..) method.

我不知道为什么有人会提供带有附加图标 png 文件的解决方案,而java api覆盖paintIcon(..) 方法提供了强大的功能。

The best lightweight solution to remember CheckBox state is IMO ClientPropertyattribute.

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

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

usage: TCheckBox tcb = new TCheckBox("My CheckBox");

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

回答by Tim Sparg

JIDE have open sourced some very nice functionality in their Common Layer, one of which happens to be a tristate checkbox

JIDE 在其Common Layer 中开源了一些非常好的功能,其中之一恰好是三态复选框

Tristate checkboxes

三态复选框

I would suggest that you go run the webstart demoto see if it meets your needs

我建议你去运行webstart 演示看看它是否满足你的需求

回答by whatnick

Tristate check-boxes are standard UI idiom for Treeviews with partially checked children nodes. They are widely used in layer management in complex hierarchial views such as Google Earth.

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

回答by camickr

That "ugly implementations" is an old link. One of the suggestions on that page was updated a couple of years ago. I haven't tested the old implementation, so I don't know if the new one is any better or worse.

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

TristateCheckBox Revisited

重新审视 TristateCheckBox

回答by Rastislav Komara

Change the UI. Tristate check-box is unusual and can really confuse users. The drop down is good option but for more then one occurrence within dialog it will also bring a lot of confusion to user.

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

回答by Bill K

I'd just use the one you posted.

我就用你贴的那个。

As long as your complexity is in another class (that works) and it acts just like any other control, who cares? (That seems to be the assumption behind all of swing, most swing classes seem to be about this complicated.)

只要您的复杂性在另一个类中(有效)并且它的行为就像任何其他控件一样,谁在乎?(这似乎是所有挥杆背后的假设,大多数挥杆课程似乎都如此复杂。)