JDialog от JFrame, защо слушателите ми не работят?

Преди около седмица започнах да работя върху GUI тип опции. Започнах с JFrame и добавих доста функционалност с различни слушатели на бутони и ключове. Всичко това работеше и реших, че искам прозорецът да е модален. Преобразувах JFrame в JDialog и въпреки че все още НЕ е модален, цялата функционалност е все още там, но когато го задам да бъде модален (вярно ИЛИ невярно), губя цялата функционалност на моите слушатели. Някаква идея какво не е наред?

Работя по качването на моя 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
hovercraft, разбирам какво искаш да кажеш, премахнах разширенията и все още действа по същия начин. Когато модалността е настроена на false, моите слушатели работят, когато настроя modality на 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, той все още е null. Така или иначе няма много смисъл.   -  person Guillaume Polet    schedule 18.06.2012
comment
@ Guillaume Polet, премахнах разширенията и промених конструктора си само на f = new JDialog(). Все същите проблеми.   -  person takisback    schedule 18.06.2012
comment
@trashgod Все пак искам фокус. Искам моят слушател на клавиши да се задейства само когато е натиснат enter, докато единственото ми текстово поле е на фокус.   -  person takisback    schedule 18.06.2012
comment
Enter вече е обвързан; добавете слушател на действие към самото текстово поле.   -  person trashgod    schedule 18.06.2012
comment
@trashgod аз го правя. Имам addKeywordField.addKeyListener(new 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
Не разбирам нишка в този контекст? Използвах анонимни вътрешни класове само за илюстрация. - person trashgod; 18.06.2012
comment
Съжалявам, лоша употреба на думи, създаване на отделен runnable. - person takisback; 18.06.2012
comment
А, моя грешка: вижте също Първоначални теми. - person trashgod; 18.06.2012