从JFrame创建JDialog,为什么我的监听器不起作用?

3
大约一周前,我开始着手开发一个选项类型的GUI。我从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();
    }
}
}

2
我们需要看到代码。 - Nick
我已经添加了有关该类的代码。抱歉。 - takisback
为什么你在这里有两个JDialogs对象(OptionsGUI的当前对象或“this”,以及你的“f” JDialog变量),当你只需要一个? - Hovercraft Full Of Eels
3
KeyListener需要焦点;请使用Key Bindings代替。 - trashgod
看起来在这里不需要扩展JDialog。而且你的JDialog的构造很笨拙:f = new JDialog(f, "Options"); 当你将 'f' 传递给JDialog构造函数时,它仍然为null。无论如何都没有太多意义。 - Guillaume Polet
显示剩余5条评论
1个回答

6
不要使用 KeyListener。像下面展示的那样,向文本字段添加一个 ActionListenerEnter 键已经绑定到接受输入文本的 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 https://dev59.com/5mXWa4cB1Zd3GeqPJhqD#11085850 */
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();
            }
        });
    }
}

请参阅 setDefaultButton(),此处有图示说明:[https://dev59.com/yms05IYBdhLWcg3wFOC8#7457102]。 - trashgod
谢谢,这很有帮助。对我的误解感到抱歉。 - takisback
只是为了以后参考,当我尝试将一个框设置为模态时,是否需要线程化我的操作事件? - takisback
我不理解这个上下文中的_thread_?我只是用匿名内部类进行说明。 - trashgod
对不起,用词不当,请创建一个单独的可运行文件。 - takisback
啊,我的疏忽:请参见初始线程 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接