JDialog из JFrame, почему мои слушатели не работают?

Около недели назад я начал работать над графическим интерфейсом типа опций. Я начал с JFrame и добавил немного функциональности с помощью различных прослушивателей кнопок и клавиш. У меня все это работало, и я решил, что хочу, чтобы окно было модальным. Я преобразовал JFrame в JDialog, и, хотя он по-прежнему НЕ модальный, вся функциональность все еще там, но когда я устанавливаю его как модальный (true ИЛИ false), я теряю все функциональные возможности моих слушателей. Любая идея о том, что не так?

Я работаю над загрузкой своего SVN на GitHub. Если вам нужно увидеть код, просто прокомментируйте это и дайте мне несколько минут. Заранее спасибо.

package main;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import javax.swing.*;
import Twitter.SearchTweets;

public class OptionsGUI {

// auto generated
private static final long serialVersionUID = 1L;

private JDialog f;
private JPanel buttonPanel;
private JPanel optionsLabelPanel;
private JPanel optionsSetPanel;

private JLabel sortLocationLabel;
private JLabel timeoutLabel;
private JLabel maxTweetsLabel;
private JLabel keywordsLabel;   
private JLabel currentKeywordsLabel;

private JButton add;
private JButton remove;
private JButton save;
private JButton cancel; 

private JCheckBox sortLocationField;
private JTextField setTimeoutField;
private JTextField setMaxTweetsField;
private JTextField addKeywordField;
private JComboBox currentKeywordsField;

public OptionsGUI() {
    f = new JDialog(f, "Options");
    buttonPanel = new JPanel();
    optionsLabelPanel = new JPanel();
    optionsSetPanel = new JPanel();

    sortLocationLabel = new JLabel("Sort by location: ");
    sortLocationLabel.setHorizontalAlignment(JLabel.RIGHT);
    timeoutLabel = new JLabel("Timeout (in seconds): ");
    timeoutLabel.setHorizontalAlignment(JLabel.RIGHT);
    maxTweetsLabel = new JLabel("Maximum Tweets to show: ");
    maxTweetsLabel.setHorizontalAlignment(JLabel.RIGHT);
    keywordsLabel = new JLabel("Keyword to add: ");
    keywordsLabel.setHorizontalAlignment(JLabel.RIGHT);
    currentKeywordsLabel = new JLabel("Current keywords: ");
    currentKeywordsLabel.setHorizontalAlignment(JLabel.RIGHT);

    add = new JButton("Add Keyword");
    remove = new JButton("Remove Keyword");
    save = new JButton("Save");
    cancel = new JButton("Cancel");

    sortLocationField = new JCheckBox();
    setTimeoutField = new JTextField(10);
    setMaxTweetsField = new JTextField(10);
    addKeywordField = new JTextField(10);
    currentKeywordsField = new JComboBox();
    currentKeywordsField.setEditable(false);

    buttonPanel.setLayout(new GridLayout(2,2));
    buttonPanel.add(add);
    buttonPanel.add(remove);
    buttonPanel.add(save);
    buttonPanel.add(cancel);

    optionsLabelPanel.setLayout(new GridLayout(5,1));
    optionsLabelPanel.add(sortLocationLabel);
    optionsLabelPanel.add(timeoutLabel);
    optionsLabelPanel.add(maxTweetsLabel);
    optionsLabelPanel.add(keywordsLabel);
    optionsLabelPanel.add(currentKeywordsLabel);

    optionsSetPanel.setLayout(new GridLayout(5,1));
    optionsSetPanel.add(sortLocationField);
    optionsSetPanel.add(setTimeoutField);
    optionsSetPanel.add(setMaxTweetsField);
    optionsSetPanel.add(addKeywordField);
    optionsSetPanel.add(currentKeywordsField);

    sortLocationField.setSelected(BasicGUI.isSortedByLocation());
    setTimeoutField.setText("" + SearchTweets.getTimeout());
    setMaxTweetsField.setText("" + BasicGUI.getMaxTweets());
    if (SearchTweets.getKeywords().size() > 0) {
        for (String keyword: SearchTweets.getKeywords()) {
            currentKeywordsField.addItem(keyword);
        }
    }
    else
        currentKeywordsField.addItem("(none)");

    f.getContentPane().setLayout(new BorderLayout());
    f.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
    f.getContentPane().add(optionsLabelPanel, BorderLayout.WEST);
    f.getContentPane().add(optionsSetPanel, BorderLayout.CENTER);
    f.setBounds(50, 50, 300, 235);
    f.setResizable(false);
    f.setAlwaysOnTop(true);
    f.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    f.setVisible(true);
    addKeywordField.requestFocus();


    add.addActionListener(new ButtonListener());
    addKeywordField.addKeyListener(new KeyChecker());
    remove.addActionListener(new ButtonListener());
    save.addActionListener(new ButtonListener());
    cancel.addActionListener(new ButtonListener());
}

public class ButtonListener implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == add) {
            String newKeyword  = addKeywordField.getText();
            if (newKeyword != null && newKeyword.length() > 0) {
                boolean duplicate = false;
                ArrayList<String> keywords = SearchTweets.getKeywords();
                for (int i = 0; i < keywords.size(); i++) {
                    if (keywords.get(i).equalsIgnoreCase(newKeyword)) {
                        duplicate = true;
                        break;
                    }
                }
                addKeywordField.transferFocus();
                if (duplicate ==  false) {
                    if (keywords.size() == 0)
                        currentKeywordsField.removeItem("(none)");
                    currentKeywordsField.addItem(addKeywordField.getText());
                    currentKeywordsField.setSelectedItem(addKeywordField.getText());
                }
                else {
                    JOptionPane.showMessageDialog(null, "Please enter a keyword that is not already in the list.", "Duplicate Keyword", JOptionPane.ERROR_MESSAGE);
                    f.toFront();
                    addKeywordField.requestFocus();
                    addKeywordField.setText("");
                }
            }
            else {
                JOptionPane.showMessageDialog(null, "Please enter a keyword before clicking \"Add\".", "Empty Field", JOptionPane.ERROR_MESSAGE);
                f.toFront();
                addKeywordField.requestFocus();
            }
            f.toFront();
            addKeywordField.requestFocus();
            addKeywordField.setText("");
        }

        else if (e.getSource() == remove) {
            if (currentKeywordsField.getSelectedItem() != null) {
                if (!(((String)currentKeywordsField.getSelectedItem()).equals("(none)"))) {
                    currentKeywordsField.removeItem(currentKeywordsField.getSelectedItem());
                    if (currentKeywordsField.getItemCount() == 0) {
                        currentKeywordsField.addItem("(none)");
                    }
                }
                else
                    JOptionPane.showMessageDialog(null, "No keywords have been entered yet.", "Empty List", JOptionPane.ERROR_MESSAGE);
                f.toFront();
            }
        }

        else if (e.getSource() == save) {

            boolean inputFail = false;
            //input checking try block
            try {

                int tempTimeout = Integer.parseInt(setTimeoutField.getText());
                if (tempTimeout < 0)
                    throw new Exception();

                int tempMaxTweets = Integer.parseInt(setMaxTweetsField.getText());
                if (tempMaxTweets < 0)
                    throw new Exception();

                BasicGUI.setSortedByLocation(sortLocationField.isSelected());
                SearchTweets.setTimeout(tempTimeout);
                BasicGUI.setMaxTweets(tempMaxTweets);

            } catch (NumberFormatException error) {
                inputFail = true;
                JOptionPane.showMessageDialog(null, "Please insure that Timeout and Maximum\nTweets are both integers.", "Invalid Input", JOptionPane.ERROR_MESSAGE);
                f.toFront();
            } catch (Exception error) {
                inputFail = true;
                JOptionPane.showMessageDialog(null, "Please be sure to enter a nonzero\ninteger for Timeout and Maximum Tweets.\n0 for either insures no timeout or a\nmaximum amount of tweets shown.", "Invalid Input", JOptionPane.ERROR_MESSAGE);
                if (Integer.parseInt(setTimeoutField.getText()) < 0) 
                    setTimeoutField.setText("" + SearchTweets.getTimeout());
                if ( Integer.parseInt(setMaxTweetsField.getText()) < 0)
                    setMaxTweetsField.setText("" + BasicGUI.getMaxTweets());
                f.toFront();
            } 

            if (inputFail == false) {
                SearchTweets.deleteKeywords();
                for (int i = 0; i < currentKeywordsField.getItemCount(); i++) {
                    SearchTweets.addKeyword((String)currentKeywordsField.getItemAt(i));
                }
                BasicGUI.setOptionsOpen(false);
                f.dispose();
            }
            BasicGUI.setSettingsPaneValues();
        }

        else if (e.getSource() == cancel) {
            BasicGUI.setOptionsOpen(false);
            f.dispose();
        }

        else {
            JOptionPane.showMessageDialog(null, "Error: Button not recognized");
        }

    }

}

public class KeyChecker implements KeyListener {
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                add.doClick();
        }
    }

    public void keyReleased(KeyEvent arg0) {
        //ignore
    }

    public void keyTyped(KeyEvent arg0) {
        //ignore
    }
}

public class ListenCloseWdw extends WindowAdapter{
    public void windowClosing(WindowEvent e){
        BasicGUI.setOptionsOpen(false);
        f.dispose();
    }
}
}

person takisback    schedule 18.06.2012    source источник
comment
Нам нужно увидеть код.   -  person Nick    schedule 18.06.2012
comment
Я добавил код для рассматриваемого класса. Извини.   -  person takisback    schedule 18.06.2012
comment
Почему у вас есть два объекта JDialogs здесь (текущий объект OptionsGUI или this и ваша переменная f JDialog), когда у вас должен быть только один?   -  person Hovercraft Full Of Eels    schedule 18.06.2012
comment
судно на воздушной подушке, я понимаю, что вы имеете в виду, я удалил расширения, и оно все еще действует так же. Когда для модальности установлено значение false, мои слушатели работают, когда я устанавливаю для модальности значение true, они теряют функциональность.   -  person takisback    schedule 18.06.2012
comment
Ни короткой, ни полной. KeyListener требует внимания; вместо этого используйте привязки клавиш.   -  person trashgod    schedule 18.06.2012
comment
Похоже, расширение JDialog здесь не требуется. И конструкция вашего JDialog неуклюжа: f = new JDialog(f, "Options"); когда вы передаете 'f конструктору JDialog, он все еще равен нулю. В любом случае, это не имеет особого смысла.   -  person Guillaume Polet    schedule 18.06.2012
comment
@ Гийом Полет, я удалил расширения и изменил свой конструктор на просто f = new JDialog(). Все те же проблемы.   -  person takisback    schedule 18.06.2012
comment
@trashgod Я хочу сосредоточиться. Я хочу, чтобы мой прослушиватель клавиш срабатывал только при нажатии клавиши ввода, когда мое единственное текстовое поле находится в фокусе.   -  person takisback    schedule 18.06.2012
comment
Enter уже привязан; добавить прослушиватель действий в само текстовое поле.   -  person trashgod    schedule 18.06.2012
comment
@trashgod Да. У меня есть addKeywordField.addKeyListener (новый KeyChecker()); Дело не в том, что я неправильно использую прослушиватели (я надеюсь), они работают правильно, когда окно НЕ является моделью или если компонент является JFrame.   -  person takisback    schedule 18.06.2012


Ответы (1)


Не используйте для этого KeyListener. Добавьте ActionListener в текстовое поле, как показано ниже. Клавиша Enter уже привязана к Action, которая принимает введенный текст.

См. также Как использовать действия и Как использовать привязки клавиш.

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

/** @see http://stackoverflow.com/a/11085850/230513 */
public class EnterTest extends JPanel {

    public EnterTest() {
        super(new GridLayout(0, 1));
        final JButton add = new JButton(new AbstractAction("Add") {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Add");
            }
        });
        JTextField addKeywordField = new JTextField("Press enter.");
        addKeywordField.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                add.doClick();
            }
        });
        this.add(addKeywordField);
        this.add(add);
    }

    private void display() {
        JFrame f = new JFrame("EnterTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new EnterTest().display();
            }
        });
    }
}
person trashgod    schedule 18.06.2012
comment
См. также setDefaultButton(), проиллюстрированный здесь. - person trashgod; 18.06.2012
comment
Спасибо, это помогло. Извините за мои недоразумения. - person takisback; 18.06.2012
comment
Просто для справки в будущем, когда я пытаюсь установить модальное поле, необходимо ли обрабатывать события моих действий? - person takisback; 18.06.2012
comment
Я не понимаю thread в этом контексте? Я использовал анонимные внутренние классы только для иллюстрации. - person trashgod; 18.06.2012
comment
Извините, плохое использование слов, создание отдельного исполняемого файла. - person takisback; 18.06.2012
comment
Ах, моя оплошность: см. также Начальные темы. - person trashgod; 18.06.2012