I improved the Alex KeySpy app . JFrame keeps focus, so you can minimize or maximize the application and still press any key when the application is in focus.
Here is the graphical interface.

I put the information in the label / value grid to make it easier to find the values ββyou are interested in.
And here is the code. This is a good example of a GridBagLayout.
package com.ggl.testing; import java.awt.Component; import java.awt.Container; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingUtilities; public class KeySpy implements Runnable { private KeySpyPanel keySpyPanel; public static void main(String[] args) { SwingUtilities.invokeLater(new KeySpy()); } @Override public void run() { final JFrame frame = new JFrame("Key Spy"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); frame.addWindowFocusListener(new WindowAdapter() { public void windowGainedFocus(WindowEvent e) { frame.requestFocusInWindow(); } }); keySpyPanel = new KeySpyPanel(); frame.add(keySpyPanel.getPanel()); frame.addKeyListener(new KeyPressedListener(this)); frame.pack(); frame.setVisible(true); } public KeySpyPanel getKeySpyPanel() { return keySpyPanel; } public class KeySpyPanel { private final Insets bottomInsets = new Insets(10, 10, 10, 10); private final Insets normalInsets = new Insets(10, 10, 0, 10); private JPanel panel; private JTextField keyCodeField; private JTextField keyTextField; private JTextField keyCharField; private JTextField keyLocationField; private JTextField modifiersField; private JTextField extModifiersField; private JTextField rawCodeField; private JTextField primaryLevelUnicodeField; private JTextField scancodeField; private JTextField extendedKeyCodeField; public KeySpyPanel() { createPartControl(); } private void createPartControl() { panel = new JPanel(); panel.setLayout(new GridBagLayout()); int gridy = 0; JLabel anyKeyLabel = new JLabel("Press any key"); anyKeyLabel.setFont(anyKeyLabel.getFont().deriveFont(36F)); anyKeyLabel.setHorizontalAlignment(JLabel.CENTER); addComponent(panel, anyKeyLabel, 0, gridy++, 2, 1, normalInsets, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL); JLabel keyCodeLabel = new JLabel("KeyCode:"); addComponent(panel, keyCodeLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); keyCodeField = new JTextField(20); keyCodeField.setEditable(false); addComponent(panel, keyCodeField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel keyTextLabel = new JLabel("KeyText:"); addComponent(panel, keyTextLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); keyTextField = new JTextField(20); keyTextField.setEditable(false); addComponent(panel, keyTextField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel keyCharLabel = new JLabel("KeyChar:"); addComponent(panel, keyCharLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); keyCharField = new JTextField(20); keyCharField.setEditable(false); addComponent(panel, keyCharField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel keyLocationLabel = new JLabel("KeyLocation:"); addComponent(panel, keyLocationLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); keyLocationField = new JTextField(20); keyLocationField.setEditable(false); addComponent(panel, keyLocationField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel modifiersLabel = new JLabel("Modifiers:"); addComponent(panel, modifiersLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); modifiersField = new JTextField(20); modifiersField.setEditable(false); addComponent(panel, modifiersField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel extModifiersLabel = new JLabel("ExtModifiers:"); addComponent(panel, extModifiersLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); extModifiersField = new JTextField(20); extModifiersField.setEditable(false); addComponent(panel, extModifiersField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel rawCodeLabel = new JLabel("RawCode:"); addComponent(panel, rawCodeLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); rawCodeField = new JTextField(20); rawCodeField.setEditable(false); addComponent(panel, rawCodeField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel primaryLevelUnicodeLabel = new JLabel("PrimaryLevelUnicode:"); addComponent(panel, primaryLevelUnicodeLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); primaryLevelUnicodeField = new JTextField(20); primaryLevelUnicodeField.setEditable(false); addComponent(panel, primaryLevelUnicodeField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel scancodeLabel = new JLabel("Scancode:"); addComponent(panel, scancodeLabel, 0, gridy, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); scancodeField = new JTextField(20); scancodeField.setEditable(false); addComponent(panel, scancodeField, 1, gridy++, 1, 1, normalInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); JLabel extendedKeyCodeLabel = new JLabel("ExtendedKeyCode:"); addComponent(panel, extendedKeyCodeLabel, 0, gridy, 1, 1, bottomInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); extendedKeyCodeField = new JTextField(20); extendedKeyCodeField.setEditable(false); addComponent(panel, extendedKeyCodeField, 1, gridy++, 1, 1, bottomInsets, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL); } private void addComponent(Container container, Component component, int gridx, int gridy, int gridwidth, int gridheight, Insets insets, int anchor, int fill) { GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0); container.add(component, gbc); } public JPanel getPanel() { return panel; } public void setKeyPressed(KeyEvent event) { String s = event.toString(); keyCodeField.setText(getValue("keyCode", s)); keyTextField.setText(getValue("keyText", s)); keyCharField.setText(getValue("keyChar", s)); keyLocationField.setText(getValue("keyLocation", s)); modifiersField.setText(getValue("modifiers", s)); extModifiersField.setText(getValue("extModifiers", s)); rawCodeField.setText(getValue("rawCode", s)); primaryLevelUnicodeField .setText(getValue("primaryLevelUnicode", s)); scancodeField.setText(getValue("scancode", s)); extendedKeyCodeField.setText(getValue("extendedKeyCode", s)); } private String getValue(String key, String line) { int sPos = line.indexOf(key); if (sPos >= 0) { int nPos = sPos + key.length() + 1; int ePos = line.indexOf(",", nPos); if (ePos < 0) { ePos = line.indexOf("]", nPos); } if (ePos >= 0) { return line.substring(nPos, ePos); } } return ""; } } public class KeyPressedListener extends KeyAdapter { private KeySpy keySpyFrame; public KeyPressedListener(KeySpy keySpyFrame) { this.keySpyFrame = keySpyFrame; } @Override public void keyPressed(KeyEvent event) { keySpyFrame.getKeySpyPanel().setKeyPressed(event); } } }