-2

My action button reads a JTextField value and updates that same field with only the digits included in the original value. It also copies the digits to clipboard automatically and makes a JLabel visible, letting the user know it's copied. This label goes invisible again as soon as the user types again in the text field.

Example: user inputs "abc123cde456" and clicks the action button. The output is "123456". A label is shown, telling the value was copied.

I've made this button default with getRootPane().setDefaultButton(button) so the user can trigger it using Enter key. The problem is, when using the key instead of mouse clicking, the output and copy to clipboard work, but the JLabel does not get visible.

I noticed the Enter key works properly when I set the focus off the JTextField before hitting the key, but the only way to do that in my layout is to hold the mouse click on top of the button and "drag it" outside, so the focus goes to the button instead of JTextField, like this:

passing focus to button before hitting Enter key

Code below - by the way, I'm working on NetBeans IDE:

JFrame class

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;

public class FrameZ extends javax.swing.JFrame {

    public FrameZ() {
        initComponents();
        labelCopied.setVisible(false);
        inputTxt.addActionListener(actionButton.getActionListeners()[0]);
        getRootPane().setDefaultButton(actionButton);
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        inputTxt = new javax.swing.JTextField();
        actionButton = new javax.swing.JButton();
        labelCopied = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        inputTxt.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                inputTxtKeyTyped(evt);
            }
        });

        actionButton.setText("Only numbers");
        actionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                actionButtonActionPerformed(evt);
            }
        });

        labelCopied.setText("Copied!");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(labelCopied)
                        .addGap(72, 72, 72))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(inputTxt, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE)
                        .addComponent(actionButton)
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(actionButton)
                    .addComponent(inputTxt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(labelCopied)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    private void actionButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             

        String inputValue = inputTxt.getText();
        StringBuilder digitsOnly = new StringBuilder();

        for (int i = 0; i < inputValue.length(); i++) {
            char c = inputValue.charAt(i);
            if (Character.isDigit(c)) {
                digitsOnly.append(c);
            }
        }

        inputTxt.setText(digitsOnly.toString());

        //copying to clipboard:
        StringSelection strSelect = new StringSelection(inputTxt.getText());
        Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard();
        clpbrd.setContents(strSelect, null);

        labelCopied.setVisible(true);
    }                                            

    private void inputTxtKeyTyped(java.awt.event.KeyEvent evt) {                                  
            labelCopied.setVisible(false);
    }                                 

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new FrameZ().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton actionButton;
    private javax.swing.JTextField inputTxt;
    private javax.swing.JLabel labelCopied;
    }

Main class

    public class Main {
    public static void main(String args[]){
        FrameZ frm = new FrameZ();

        frm.setVisible(true);
        frm.setResizable(false);
        frm.setLocationRelativeTo(null);
    }
}
elxapinhon
  • 43
  • 1
  • 10
  • 5
    Post an [mcve] that demonstrates the problem. – camickr Aug 27 '17 at 00:08
  • The *enter-key* does **not act** as *clicking* **by default** of the operating system or swing. It is an action that must be defined from within your program. Just research something like "*swing button enter key*". You will find results showing you how to define default actions for the enter key. For example you can define the default button of your application. If your app has focus and you hit enter, then it will trigger that button and so on. – Zabuzard Aug 27 '17 at 00:16
  • 1
    If doing as @camickr requested means that you need to post all of your code, please do so. I'm not able to run your posted code. – Charles Knell Aug 27 '17 at 00:16
  • 3
    @CharlesK.: no, it doesn't mean that at all. "all of your code" could mean 12 large classes and several packages, image files and a database. It usually means that he should create a ***small*** self-contained proof of concept program, one that compiles, runs, that demonstrates the problem for us, that has no outside dependencies such as database, and that is small enough to post in its entirety as code-formatted text as an [edit] to his question. Please don't ask for "all the code". – Hovercraft Full Of Eels Aug 27 '17 at 00:29
  • I just updated the code. This time you guys should be able to run it and see the problem. Thanks – elxapinhon Aug 28 '17 at 03:07
  • Tip: Add @camickr (or whoever, the `@` is important) to *notify* the person of a new comment. – Andrew Thompson Aug 28 '17 at 16:16
  • @elxapinhon, I copied and pasted the code and it doesn't compile for me. I don't have time to fix your errors. The code you post should be tested to make sure it compiles and demonstrates the problem. – camickr Aug 28 '17 at 16:25
  • @camickr Updated again. This one must work. Sorry about the previous one. – elxapinhon Aug 28 '17 at 22:03

1 Answers1

0

To problem solve you need to either:

  1. use a debugger to step through the code
  2. add System.out.println(...) statement to your code

Either of the above will help you understand the logic flow to see if it is what you expect.

I don't use an IDE so I made the following changes to add some debug code:

private void actionButtonActionPerformed(java.awt.event.ActionEvent evt) {
System.out.println("action");

and

private void inputTxtKeyTyped(java.awt.event.KeyEvent evt) {
    System.out.println("hide");

If you make these changes and type data in your text field and use the Enter key you will see output like:

hide
hide
hide
hide
action
hide

Why does this happen? Well, it would appear that the Enter key generates a KeyTyped event and this event is processed AFTER the ActionEvent

One way to fix this is to wrap the logic that makes the label visible in a SwingUtilities.invokeLater(...). This will cause the code to be added to the end of the Event Queue so it will be executed after the event generated by the Enter key:

    //labelCopied.setVisible(true);
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            labelCopied.setVisible(true);
        }
    });
camickr
  • 321,443
  • 19
  • 166
  • 288