如何在不触发侦听器的情况下从PropertyChangeListener更改JOptionPane的值?

时间:2011-08-10 22:03:04

标签: java swing jdialog joptionpane

我正在尝试制作一个管理一组体育运动员的计划。每个玩家都有一个enum Sport,SportManager有方便的工厂方法。我想要做的是打开一个对话框,其中包含一个名称的JTextField和一个用于选择运动的组合框。但是,我希望在文本字段为空时阻止用户关闭对话框,因此我写了一个PropertyChangeListener,这样当文本字段为空时,它会发出哔哔声让用户知道。但是,如果用户在发出蜂鸣声后放入文本中的某些内容,则不会触发侦听器而您无法在不按取消的情况下关闭对话框,因为该值已经是JOptionPane.OK_OPTION,并且取消是唯一的方法更改JOptionPane.VALUE_PROPERTY。所以我试着添加

message.setValue(JOptionPane.UNITIALIZED_VALUE);

在听众中。然而,这只是立即关闭窗口而不给用户填写文本字段的机会,大概是因为它触发了我刚刚注册的监听器。如何制作它以使其不止一次发出哔声并让用户有机会填写该字段?

FYI newPlayer是我正在注册动作的组件。

代码:

    newPlayer.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                Object[] msg = new Object [4];
                msg[0]  = new JLabel("Name:");
                final JTextField nameField = new JTextField();
                msg[1]=nameField;
                msg[2] = new JLabel("Sport: ");
                JComboBox<Sport> major = new JComboBox<Sport>(SportManager.getAllSports());
                msg[3]=major;
                final JOptionPane message = new JOptionPane();
                message.setMessage(msg);
                message.setMessageType(JOptionPane.PLAIN_MESSAGE);
                message.setOptionType(JOptionPane.OK_CANCEL_OPTION);
                final JDialog query = new JDialog(gui,"Create a new player",true);
                query.setContentPane(message);
                query.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
                message.addPropertyChangeListener(
                        new PropertyChangeListener() {
                            public void propertyChange(PropertyChangeEvent e) {
                                String prop = e.getPropertyName();


                                if (query.isVisible()&& (e.getSource() == message)&& (prop.equals(JOptionPane.VALUE_PROPERTY))) {
                                    if(nameField.getText().equals("")&&message.getValue().equals(JOptionPane.OK_OPTION)){
                                        Toolkit.getDefaultToolkit().beep();
                                        message.setValue(JOptionPane.UNINITIALIZED_VALUE);
                                        return;
                                    }
                                    query.dispose();
                                }
                            }

                        });
                query.pack();
                query.setVisible(true);
                if(Integer.parseInt(message.getValue().toString())==JOptionPane.OK_OPTION){
                    players.add(new Player(nameField.getText(),(Sport)major.getSelectedItem()));
                    edited=true;
                }
                gui.show(players);
            }
        });

5 个答案:

答案 0 :(得分:1)

  

但是,我希望阻止用户关闭对话框   文本字段为空白

我到达你要去的地方,但Java Swing并不是很擅长这一点。您无法阻止侦听器被调用。解决方案是忽略调用,但实现起来很复杂。

我解决这个问题的方法是让弹出窗口消失,检查返回的值以及是否为空/空,发出蜂鸣声并重新打开它,直到用户填写内容为止。

答案 1 :(得分:1)

我认为您无法使用JOptionPane执行此操作,但您可以使用TaskDialog框架和其他一些框架。

您也可以自己创建一个对话框,将更改侦听器附加到您的字段,并根据您的字段内容启用/禁用“确定”按钮。此过程通常称为“表单验证”

答案 2 :(得分:1)

JOptionPane内部不支持输入验证(Bug Reference)。您最好的选择是创建自己的自定义JDialog,它支持在输入数据无效时禁用“确定”按钮。

我建议阅读错误报告,因为其他人会谈论它并给出解决方法。

答案 3 :(得分:1)

  

但是,我想阻止用户在文本字段为空白时关闭对话框

Stopping Automatic Dialog Closing上的Swing教程中的CustomDialog示例中有一个工作示例,可以执行此操作。

在快速查看代码和工作示例后,我认为您的代码应该是:

if (query.isVisible()
&& (e.getSource() == message)
&& (prop.equals(JOptionPane.VALUE_PROPERTY)))
{
    if (message.getValue() == JOptionPane.UNINITIALIZED_VALUE)
        return;

    if (nameField.getText().equals("")
    && message.getValue().equals(JOptionPane.OK_OPTION))
    {
        Toolkit.getDefaultToolkit().beep();
        message.setValue(JOptionPane.UNINITIALIZED_VALUE);
    }
    else
        query.dispose();
}

否则,我会让您将代码与工作代码进行比较,看看有什么不同。

答案 4 :(得分:0)

解决此问题的一种方法是在对话框中添加CancelOk按钮。然后,禁用通过角落中的X关闭弹出窗口,强制用户单击CancelOk以完成/关闭对话框。现在,只需在文本字段中添加一个侦听器,如果文本字段为空,则会禁用Ok按钮。

从您的代码判断我认为您可以弄清楚如何实施这些步骤,但如果您遇到问题请告诉我们!祝你好运!