Can't figure out error with ActionListener

前端 未结 2 1846
忘了有多久
忘了有多久 2020-12-12 00:20

The following is my program. the goal is to convert from a roman numeral to an Arabic number after a user types in the numeral and presses the enter key.

This is a

相关标签:
2条回答
  • 2020-12-12 01:08

    KeyListeners are NEVER appropriate solutions to use with text components, if you want to be notified when a text component changes, you use a DocumentListener, if you want to change/filter what can be entered into a text component, you use a DocumentFilter, if you need to change a special key, like Enter, you should use a key binding

    See How to Use Key Bindings for more details.

    One of the problems you could have with KeyListener is not knowing when the key stroke is processed by the text component, in your case, it may not be a major issue, but it could change the way the program works on different platforms.

    Instead, you can override the JTextArea's key binding for the Enter key (named insert-break). This provides you with the ability to actually change the behavior of the key stroke, or, in your case, manage how you process the event. For example, this replaces the Action for the text area's Enter key, but retains the previous/default behavior...

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import javax.swing.AbstractAction;
    import javax.swing.Action;
    import javax.swing.ActionMap;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class KeyBindingsTest {
    
        public static void main(String[] args) {
            new KeyBindingsTest();
        }
    
        public KeyBindingsTest() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private JTextArea ta;
    
            public TestPane() {
                ta = new JTextArea(10, 20);
                ActionMap am = ta.getActionMap();
    
                Action proxy = am.get("insert-break");
                am.put("insert-break", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        // You can process the event through the original action BEFORE
                        // you do your own processing
                        //proxy.actionPerformed(e);
                        System.out.println("You pressed the enter key, you can have candy");
                        // Or you can process the event through the original action AFTER
                        // you do your own processing, you have now gained control
                        proxy.actionPerformed(e);
                    }
                });
    
                setLayout(new BorderLayout());
                add(ta);
            }
    
        }
    
    }
    

    Now, you could even go to the extent for creating your own JTextArea which supported ActionPerformed...

    public class ActionableTextArea extends JTextArea {
    
        private String actionCommand;
    
        public ActionableTextArea() {
            installKeyBindings();
        }
    
        public ActionableTextArea(String text) {
            super(text);
            installKeyBindings();
        }
    
        public ActionableTextArea(int rows, int columns) {
            super(rows, columns);
            installKeyBindings();
        }
    
        public ActionableTextArea(String text, int rows, int columns) {
            super(text, rows, columns);
            installKeyBindings();
        }
    
        public ActionableTextArea(Document doc) {
            super(doc);
            installKeyBindings();
        }
    
        public ActionableTextArea(Document doc, String text, int rows, int columns) {
            super(doc, text, rows, columns);
            installKeyBindings();
        }
    
        protected void installKeyBindings() {
            ActionMap am = getActionMap();
            Action proxy = am.get("insert-break");
            am.put("insert-break", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                        // You can process the event through the original action BEFORE
                    // you do your own processing
                    //proxy.actionPerformed(e);
                    fireActionPerformed();
                        // Or you can process the event through the original action AFTER
                    // you do your own processing, you have now gained control
                    proxy.actionPerformed(e);
                }
            });
        }
    
        public void addActionListener(ActionListener listener) {
            listenerList.add(ActionListener.class, listener);
        }
    
        public void removeActionListener(ActionListener listener) {
            listenerList.remove(ActionListener.class, listener);
        }
    
        public void setActionCommand(String actionCommand) {
            this.actionCommand = actionCommand;
        }
    
        public String getActionCommand() {
            return actionCommand;
        }
    
        protected void fireActionPerformed() {
            ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
            if (listeners.length > 0) {
                ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, getActionCommand());
                for (ActionListener listener : listeners) {
                    listener.actionPerformed(evt);
                }
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-12 01:13

    For a better answer, see @MadProgrammer 's answer.

    My solution:

    There is no ActionListener for JTextArea.

    So just use KeyListener instead

    HandlerForTextArea handler = new HandlerForTextArea();
    enterRomanNumber.addKeyListener(handler);
    

    Implements KeyListener

    private class HandlerForTextArea implements KeyListener
    {
    
        @Override
        public void keyPressed(KeyEvent arg0) {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void keyReleased(KeyEvent arg0) {
            // TODO Auto-generated method stub
            if (arg0.getKeyCode() == VK_ENTER){
                // TODO Your bussiness
            }
        }
    
        @Override
        public void keyTyped(KeyEvent arg0) {
            // TODO Auto-generated method stub
        }
    }
    
    0 讨论(0)
提交回复
热议问题