Как изменить значение JOptionPane из PropertyChangeListener без запуска слушателя? - PullRequest
3 голосов
/ 11 августа 2011

Я пытаюсь составить программу для управления группой спортивных игроков.У каждого игрока есть 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 ]

1 голос
/ 11 августа 2011

Однако я хочу, чтобы пользователь не мог закрыть диалоговое окно, пока текстовое поле пусто

Пример CustomDialog из раздела учебного пособия по Swing по Остановка автоматического закрытия диалога имеет рабочий пример, который делает это.

После быстрого просмотра вашего кода и рабочего примера я думаю, что ваш код должен выглядеть примерно так:

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

В противном случае, я позволю вам сравнить ваш код с рабочим кодом, чтобы увидеть разницу.

1 голос
/ 11 августа 2011

JOptionPane внутренне не поддерживает проверку входных данных ( Ссылка на ошибку ). Лучше всего создать свой собственный JDialog, который поддерживает отключение кнопки ОК, если введенные данные недействительны.

Я бы порекомендовал прочитать отчет об ошибке, поскольку другие люди обсуждают это и предлагают обходные пути.

1 голос
/ 11 августа 2011

Я не думаю, что вы можете сделать это с JOptionPane, но вы можете использовать TaskDialog framework и некоторые другие.

Вы также можете создать диалоговое окно самостоятельно, присоединить слушателей изменений к своим полям и включить / отключить кнопку ОК на основе содержимого ваших полей. Этот процесс обычно называют «проверкой формы»

1 голос
/ 11 августа 2011

Однако я хочу, чтобы пользователь не мог закрыть диалоговое окно, пока текстовое поле пустое

Я понимаю, куда вы идете, но Java Swing не очень хорош в этом.Вы не можете предотвратить вызов слушателя.Решение состоит в том, чтобы игнорировать вызов, но это сложно реализовать.

Способ, которым я решил эту проблему, - позволить всплывающему окну исчезнуть, проверить возвращаемое значение и, если оно пустое / пустое, подать звуковой сигнали снова открывайте его, пока пользователь не заполнит что-либо.

0 голосов
/ 11 августа 2011

Одним из способов решения этой проблемы является добавление кнопок Cancel и Ok в диалоговое окно. Затем отключите закрытие всплывающего окна с помощью X в углу, заставляя пользователя нажимать либо Cancel, либо Ok, чтобы завершить / закрыть диалоговое окно. Теперь просто добавьте слушателя в текстовое поле, которое отключит кнопку Ok, если текстовое поле пустое.

Судя по вашему коду, я предполагаю, что вы сможете выяснить, как реализовать эти шаги, но если у вас возникнут проблемы, дайте нам знать! Удачи!

...