Off topic: (kinda)
The fact that you are doing Main.mainp.getLayout();, calling the panel statically tells me you have poor design and should be looking into other options like an Model-view-controller pattern, an Observer pattern, or at the very least passing a reference of of the Main to the panel, instead of using static objects/calls.
Back on topic
Sounds like a common KeyListener problem. Generally to gain focus you call requestFocusInWindow(). But you still have to worry about other components stealing the focus way after the fact.
I would instead recommend using Key Bindings instead of KeyListener. You have more control over the focus. For instance, by using
InputMap im = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("SPACE"), "hitSpace");
panel.getActionMap().put("hitSpace", new AbstractAction(){
public void actionPerformed(ActionEvent e) {
// do something.
}
});
The panel will have immediate access to the action once you show it from the CardLayout. If you happen to use any other components that would steal the focus away from the panel, the action is still accessible because of the WHEN_IN_FOCUSED_WINDOW input map
Here's a simple example. Type A if it is on panel A, you will see it print. If you type B, it won't print because panel A is in the window. Also if you try and press the button in the panel to steal the focus, you can still type and it will still print. Same goes for panel B
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Main {
CardLayout layout = new CardLayout();
JPanel panel = new JPanel(layout);
JPanel p1 = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
JPanel p2 = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
JButton b1 = new JButton("panelA");
JButton b2 = new JButton("panelB");
public Main() {
addKeyBind(p1, "pressA", "A");
addKeyBind(p2, "pressB", "B");
p1.add(new JButton("Button for Panel A"));
p2.add(new JButton("Button for Panel B"));
panel.add(p1, "panelA");
panel.add(p2, "panelB");
b1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
show("panelA");
}
});
b2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
show("panelB");
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(b1);
buttonPanel.add(b2);
JFrame frame = new JFrame();
frame.add(panel);
frame.add(buttonPanel, BorderLayout.PAGE_END);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void show(String panelName) {
layout.show(panel, panelName);
}
private void addKeyBind(JComponent comp, String name, final String stroke) {
InputMap im = comp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(stroke), name);
comp.getActionMap().put(name, new AbstractAction(){
public void actionPerformed(ActionEvent e) {
System.out.println(stroke + " pressed");
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new Main();
}
});
}
}
Take some time to go over the link I gave you for Key Bindings to learn more.
Back off-topic
Take a look at @AndrewThompson's comment about the null layouts. Learn how to use the LayoutManagers