In my program a JPanel component which is operated by listener using KeyBindings (changed that from KeyListeners already after reading about issues with focusing) is added to a JFrame. Task of this app is to simply move drawn figure around using arrow keys. This works perfectly until i add another component before drawing board (JPanel with three buttons). I tested both Keybindings and KeyListener and both methods have the same issue. If I add components after drawing board keybindings starts to work again.
Here is my UI class where i add components.
EDIT: removed uncleaned code
I would like to understand Java a bit more so any answer is very appreciated.
Edit: I cleaned my code and created "minimal" example of the problem. Thank you Andrew for heads up.
Program should print "movingup" in console after pressing arrow up.
The problem occurs here:
container.add(buttons); //after adding this Key Bindings stops working
container.add(board);
And the question is: Why order of adding components makes Key Bindings to stop working? If i add buttons after board Key Binding is working.
Class with the problem (used for creating frame and adding components)
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.WindowConstants;
public class UserInterface implements Runnable {
private static final String MOVE_UP = "moveUP";
private JFrame frame;
public UserInterface() {
}
@Override
public void run() {
frame = new JFrame("Board");
frame.setPreferredSize(new Dimension(500, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout());
createComponents(frame.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void createComponents(Container container) {
DrawingBoard board = new DrawingBoard();
container.add(new JButton()); //after adding this figure stops moving - arrow keys doesn't work
container.add(board);
MovingUpwards up = new MovingUpwards(board);
board.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
board.getInputMap().put(KeyStroke.getKeyStroke("UP"), MOVE_UP);
board.getActionMap().put(MOVE_UP, up);
}
public JFrame getFrame() {
return frame;
}
}
Rest of the used classes for testing purposes:
import javax.swing.SwingUtilities;
public class Main {
public static void main (String[] args) {
UserInterface ui = new UserInterface();
SwingUtilities.invokeLater(ui);
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawingBoard extends JPanel {
public DrawingBoard() {
super.setBackground(Color.WHITE);
}
@Override
protected void paintComponent (Graphics graphics) {
super.paintComponent(graphics);
}
}
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public class MovingUpwards extends AbstractAction {
private Component component;
public MovingUpwards(Component component) {
this.component = component;
}
@Override
public void actionPerformed(ActionEvent a) {
System.out.println("movingup");
}
}
The key bindings work fine for me. Check out the Motion Using Key Bindings
example found in Motion Using the Keyboard.
I changed the code:
frame.add( content );
frame.add(left, BorderLayout.NORTH);
to:
frame.setLayout(new GridLayout());
frame.add(left);
frame.add( content );
to better simulate your logic.
If you need more help then read Andrew's comment above. Simplify your code to demonstrate the problem so we can "easily" test it by copying and compiling a single source file, the way you can test the code found in the link above.