3

我想要有历史的命令窗口。我做了okAction并将它绑在Ok按钮上。发出命令时调用此命令。

如果命令成功,则从输入单元格中删除命令文本并添加到历史记录中。这是用 editable 制作的JComboBox

Ok如果用户从历史记录中选择了某个命令,则与按下按钮时相同。所以我也将相同的动作绑定到组合框。

不幸的是,使用组合框进行操作也会导致调用动作。在下面的例子中,这是模拟命令失败,一个动作被调用了 3 次。

为什么?

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
import javax.swing.border.*;

public class JCommandWindow extends JFrame {

    private static final Random rnd = new Random();
    private static final long serialVersionUID = 1L;
    private AbstractAction okAction = new AbstractAction("Ok") {

        private static final long serialVersionUID = 1L;

        @Override
        public void actionPerformed(ActionEvent e) {

            if (issue((String) inputComboBox.getSelectedItem())) {
                inputComboBox.setSelectedItem("");
            } else {
                inputComboBox.getEditor().selectAll();
            }
        }
    };
    private AbstractAction cancelAction = new AbstractAction("Cancel") {

        private static final long serialVersionUID = 1L;

        @Override
        public void actionPerformed(ActionEvent e) {
            close();
        }
    };
    private JTextArea logTextArea = new JTextArea();

    {
        logTextArea.setWrapStyleWord(true);
        logTextArea.setBorder(new EtchedBorder());
        logTextArea.setEditable(false);
    }
    private JScrollPane logScrollPane = new JScrollPane(logTextArea);

    {
        logScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        logScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    }
    private JPanel logPanel = new JPanel();

    {
        logPanel.setLayout(new BorderLayout());
        logPanel.setBorder(new EmptyBorder(5, 5, 0, 5));
        logPanel.add(logScrollPane, BorderLayout.CENTER);
    }
    private DefaultComboBoxModel historyModel = new DefaultComboBoxModel();
    private JComboBox inputComboBox = new JComboBox();

    {
        inputComboBox.setModel(historyModel);
        inputComboBox.setEditable(true);
        inputComboBox.addActionListener(okAction);
    }
    private JPanel inputPanel = new JPanel();

    {
        inputPanel.setLayout(new BorderLayout());
        inputPanel.setBorder(new EmptyBorder(5, 5, 5, 0));
        inputPanel.add(inputComboBox, BorderLayout.CENTER);
    }
    private JButton okButton = new JButton(okAction);
    private JButton cancelButton = new JButton(cancelAction);
    private JPanel buttonPanel = new JPanel();

    {
        buttonPanel.setLayout(new FlowLayout());
        buttonPanel.add(okButton);
        buttonPanel.add(cancelButton);
    }
    private JPanel bottomPanel = new JPanel();

    {
        bottomPanel.setLayout(new BorderLayout());
        bottomPanel.add(inputPanel, BorderLayout.CENTER);
        bottomPanel.add(buttonPanel, BorderLayout.EAST);
    }
    private final JRootPane rootPane = getRootPane();

    {
        rootPane.setLayout(new BorderLayout());
        rootPane.add(logPanel, BorderLayout.CENTER);
        rootPane.add(bottomPanel, BorderLayout.SOUTH);

        rootPane.setDefaultButton(okButton);
        rootPane.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
                // TODO Auto-generated method stub
            }

            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
            }

            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    cancelAction.actionPerformed(null);
                }
            }
        });
        addWindowFocusListener(new WindowFocusListener() {

            @Override
            public void windowLostFocus(WindowEvent e) {
                // TODO Auto-generated method stub
            }

            @Override
            public void windowGainedFocus(WindowEvent e) {
                inputComboBox.requestFocusInWindow();
            }
        });
    }

    public JCommandWindow() {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }

    public void close() {
        WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
    }

    @Override
    public void pack() {
        super.pack();
        // Get the size of the screen
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        int w = dim.width * 2 / 3;
        int h = dim.height * 2 / 3;
        setSize(w, h);
        int x = (dim.width - w) / 2;
        int y = (dim.height - h) / 2;
        // Move the window
        setLocation(x, y);
    }

    public void addText(String text) {
        logTextArea.append(text + "\n");
        logTextArea.setCaretPosition(logTextArea.getDocument().getLength());
    }

    public void rememberCommand(String command) {
        historyModel.addElement(command);
    }

    public boolean issue(String command) {
        /*
        if( rnd.nextBoolean() ) {
        addText(command + " succeeded");
        rememberCommand(command);
        return true;
        }
        else {
        addText(command + " failed");
        return false;
        }
         */
        addText(command + " failed");
        return false;
    }

    public static void main(String[] args) {
        JCommandWindow commandWindow = new JCommandWindow();
        commandWindow.pack();
        commandWindow.setVisible(true);
    }
}
4

1 回答 1

4

当可编辑组合框失去焦点时,触发事件的contentsChanged方法,JComboBox触发actionPerformed. ActionListener然后,focusLost再次调用相同的actionPerformed.

然后,最终触发按钮按下的动作。

于 2012-09-28T19:00:03.303 回答