JFrame/JDesktop not receving key focus - java

I would like my top level JFrame as well as the JDesktopPane to listen on key events at all times, no matter what component is currently focused/visible.
Currently, when this program is launched, the JFrame is receving the key events OK. However if a JinternalFrame is clicked, then events no longer reach the JFrame. Even if I do click outside the JInternalFrame, (which is supposed to be the JDesktop component), the events no longer reach the JFrame, like they did in the beginning. Why? Thx.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class focus extends JFrame implements KeyListener {
private focus() {
JDesktopPane desktop = new JDesktopPane();
setContentPane(desktop);
addPane(this, "one");
addPane(this, "two");
addPane(this, "three");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(400, 450);
addKeyListener(this);
}
public static void main(String[] args) {
focus t = new focus();
}
private void addPane(JFrame frame, String name) {
JTextArea textArea = new JTextArea();
textArea.setName(name);
textArea.setEditable(false);
addWindow(frame, textArea, name);
}
private JInternalFrame addWindow(JFrame frame, JComponent component,
String name) {
JScrollPane scrollablePane = new JScrollPane(component);
JInternalFrame iframe = new JInternalFrame(name + " ", true, true,
true, true);
iframe.setSize(300, 300);
iframe.setLocation((int) (100 * Math.random()),
(int) (100 * Math.random()));
iframe.setVisible(true);
iframe.getContentPane().add(scrollablePane);
frame.getContentPane().add(iframe);
return iframe;
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
System.err.println(e.getKeyChar());
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}

Events are dispatched to the component that has focus.
Why would you want the frame to receive events when focus is on the internal frame? What is your actual requirement?
If you want to invoke an Action, then the easiest way is to use menu bars with menu items and then you can assign accelerators to each menu item to the Action can be invoked no matter with component has focus.

Since you would like your JFrame to be able to listen to all the key events no matter what element the focus is on, add that as the key listener to all the elements on which there can be focus. Like so,
textArea.setEditable(false);
**textArea.addKeyListener(this);**
and
iframe.getContentPane().add(scrollablePane);
**iframe.addKeyListener(this);**
frame.getContentPane().add(iframe);

You might be interested in the java.awt.KeyboardFocusManager class. I believe it is the class that, among other things, dispatches KeyEvents to the focused component. It seems that the methods addKeyEventDispatcher and addKeyEventPostProcessor could be used to get KeyEvents before and after being sent to the focused component, respectively.
I have not ever used this class before, so I do not know if it does what I expect it to do.

Related

There is a cardlayout error in my code which states that i have an issue with mouse clicked [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I have an issue with the card layout. It sates that (at GameWindow$2.mouseClicked(GameWindow.java:80)) There's an error. My card layout looks like this
((CardLayout) getContentPane().getLayout()).show(getContentPane(), "game");
Can someone please help me figure the issue out. I have two frames one that contains the game and the other contains the button to get the game stage. Can someone please do this one thing for me.
The layout is Null for the card layout
// Import necessary GUI classes
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JLabel;
import javax.swing.Timer;
// "Extend" the JFrame class so we can customize it but still keep all its features
public class GameWindow extends JFrame implements ActionListener, KeyListener {
// Serial version UIDs are used to differentiate between different object
// versions--don't worry about it!
private static final long serialVersionUID = 1L;
JLabel Player = new JLabel();
int playerSpeed = 1;
int FPS = 30;
// The keys set holds the keys being pressed
private final Set<Integer> keys = new HashSet<>();
// This main method runs when the program is executed
public static void main(String[] args) {
// This method runs a new "runnable" program after a brief pause that allows the
// main program to exit
EventQueue.invokeLater(new Runnable() {
public void run() {
// The try/catch block prevents errors from crashing the program
try {
GameWindow window = new GameWindow(); // Create and setup the main game window
window.setVisible(true); // show the new window
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Constructor: runs when a GameWindow object is created (instantiated)
*/
public GameWindow() {
// Run the parent class constructor
super();
// Allow the panel to get focus
setFocusable(true);
// Don't let keys change the focus
setFocusTraversalKeysEnabled(false);
setBounds(100, 100, 250, 360); // the window will appear at (100, 100) and 250w by 260h
setTitle("Banana Jumper 1.0"); // the window will have this title
setResizable(false); // the window can't be resized
setLocationRelativeTo(null); // the window will move to the centre of the screen
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // when the window is closed, the program will exit
getContentPane().setLayout(new CardLayout()); // the window can swap between "stages" added as JPanels
// Make a new screen with a button and put it in the window
JPanel startStage = new JPanel(); // Create a new JPanel and add it to the card layout
startStage.setSize(getWidth(), getHeight()); // make the new JPanel fit the window
startStage.setBackground(Color.BLUE); // set the JPanel background to blue
JButton playButton = new JButton("Play"); // Add a button to the panel
playButton.addMouseListener(new MouseAdapter() { // Set the button to switch to the game stage
#Override
public void mouseClicked(MouseEvent arg0) {
((CardLayout) getContentPane().getLayout()).show(getContentPane(), "game");
setLayout(null);
}
});
startStage.add(playButton); // add the button to the stage
add(startStage, "start"); // add the stage to the window
// Create a second JPanel with band add it to the card layout
JPanel gameStage = new JPanel();
gameStage.setSize(getWidth(), getHeight());
gameStage.setVisible(true);
gameStage.setBackground(Color.RED);
// Add a button to the panel
JButton mainButton = new JButton("Back to Main Menu");
// Set the button to switch to the start stage
mainButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
((CardLayout) getContentPane().getLayout()).show(getContentPane(), "start");
}
});
gameStage.add(mainButton);
// Put the stages in the window
add(startStage, "start");
add(gameStage, "game"); // put the stage in the window
// Setup the movable box
Player.setBounds(10, 10, 10, 10);
Player.setVisible(true);
Player.setBackground(Color.BLUE);
// Opaque makes the background visible
Player.setOpaque(true);
// Setup the key listener
addKeyListener(this);
// Null layout allows moving objects!!!
setLayout(null);
add(Player);
// Set the timer
Timer tm = new Timer(1000 / FPS, this);
tm.start();
}
#Override
public void actionPerformed(ActionEvent arg0) {
// Move up if W is pressed
if (keys.contains(KeyEvent.VK_W)) {
Player.setLocation(Player.getX(), Player.getY() - playerSpeed);
}
// Move right if D is pressed
if (keys.contains(KeyEvent.VK_D)) {
Player.setLocation(Player.getX() + playerSpeed, Player.getY());
}
// Move down if S is pressed
if (keys.contains(KeyEvent.VK_S)) {
Player.setLocation(Player.getX(), Player.getY() + playerSpeed);
}
// Move left if A is pressed
if (keys.contains(KeyEvent.VK_A)) {
Player.setLocation(Player.getX() - playerSpeed, Player.getY());
}
}
#Override
public void keyPressed(KeyEvent e) {
// Add the key to the list
// of pressed keys
if (!keys.contains(e.getKeyCode())) {
keys.add(e.getKeyCode());
}
}
#Override
public void keyReleased(KeyEvent e) {
// Remove the key from the
// list of pressed keys
keys.remove((Integer) e.getKeyCode());
}
#Override
public void keyTyped(KeyEvent e) {
}
}
You've set the layout to null - setLayout(null);, which is the equivalent of saying getContentPane().setLayout(null)
Observations...
Avoid things like startStage.setSize(getWidth(), getHeight()); // make the new JPanel fit the window - let the layout manager do it's job
startStage.setVisible(true); // show the JPanel is pointless, as Swing components are visible by default
Avoid extending from JFrame. Theres lots of reasons (your problem is a highlight of one), but you're not actually adding a new/re-usable functionality to the class and you're locking your self into a single use case. Better to start with a JPanel and add it to what ever container you want.
Don't use KeyListener, use the Key Bindings API instead. It will solve all the issues related to KeyListener, reliably
I would also avoid using "components" (like JLabel) as a game entity. You will have better luck and greater flexibility following a custom painting route

Passing containers between JFrame and JDialog causing missing panels?

As for testing-reasons I tried to open a JDialog window with the panel and its contents of the main application frame. As I already had anything in there I wanted to see if I could simply set the JDialogs contentPane to the one I passed over. So in simplyfied form this came together:
testsforSO.java :
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testsforSO frame = new testsforSO();
frame.setSize(300, 300);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("I am the Frame");
getContentPane().setLayout(new BorderLayout(0, 0));
JPanel panel = new JPanel();
panel.setLayout(null);
JButton btnRestart = new JButton("Restart");
btnRestart.setBounds(10, 10, 50, 50);
btnRestart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
testsforSO.main(null);
dispose();
}
});
panel.add(btnRestart);
getContentPane().add(panel);
repaint();
// -----------DELETE These comments-------------
// JDialog myDialg = new JDialog(this);
// myDialg.setContentPane(panel);
// myDialg.setVisible(true);
// myDialg.setSize(300,300);
// myDialg.setLocation(new Point(250, 250));
// myDialg.setTitle("I am Dialog from within the script");
myDialog.main(panel);
}
}
and myDialog.java :
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.JDialog;
public class myDialog extends JDialog {
private static final long serialVersionUID = 7079322237622743228L;
public static void main(Container myContainer) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
myDialog frame = new myDialog(myContainer);
frame.setVisible(true);
frame.setContentPane(myContainer);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public myDialog(Container myContainer) {
setContentPane(myContainer);
getContentPane().setLayout(null);
setBounds(200,200,200,200);
}
}
When starting the main frame I assumed it would contain the restarting button as well as the dialog does. But interestingly it was only the dialog with the button.
However when hitting it, the main frame properly restarted, a second dialog was set up and it contained the button again. This time however the main frame had the button as well, just without any function. Clicking on it does absolutely nothing.
Then I tried further and checked if that behaviour would change if I added the dialog directly into the main applications code (see the commented lines) and, starting the application once again only the dialog in its own class showed the button. Even hitting this one now restarted properly but the button won't show up on any other window except the lonely declared dialog.
What am I missing here and how could I refactor my code to work properly if even at all in this manner?
Understand that Swing components can only be present in one container, and while you may see the visual residue of a component in a container, the actual component is only present in the last container added to.
Myself, if I wanted dialog and jframe to have the same content pane components, I'd create a factory method to create the contentPane, and then use it to create two unique but identical contentPanes.
Also, I'd be remiss if I didn't mention something about your use of null layouts. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
For instance, when I ran your code, this is the dialog that I saw:
You hard coded the button's size to be too small to show its text on my platform. If you had used layout managers, and called pack() on the top-level window, the button would show appropriately.

Updating JPanel content in JFrame by using a frame state variable

I'm trying to find a way how to update a panel content after changing a state variable.
Concretely in the example below, there is simple JPanel inside JFrame with two buttons. When the app starts, its state variable ("window") equals "home" so home button should be invisible. After clicking on the page button the state variable change and so both buttons visibility should change after frame repainting. (i.e. the page button should disappear and the home button should appear).
In this case, it is possible to solve it without the state variable just using setVisibility() method for buttons. But in my app, I would like to have more JComponetns connected to the state variable. Is there a way how to do it?
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class JPanelUpdateTest {
private JFrame frame;
private String window = "home";
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JPanelUpdateTest window = new JPanelUpdateTest();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public JPanelUpdateTest() {
initialize();
}
private void initialize() {
frame = new JFrame("JPanelUpdateTest");
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
JButton btnHome = new JButton("home");
btnHome.setVisible(window == "home" ? false : true);
btnHome.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
window = "page";
panel.revalidate();
frame.repaint();
}
});
panel.add(btnHome);
JButton btnPage = new JButton("page");
btnPage.setVisible(window == "page" ? false : true);
btnPage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
window = "home";
panel.revalidate();
frame.repaint();
}
});
panel.add(btnPage);
}
}
The problem is that initialize is only being called once, at object creation, and it should only be called once, and because of this the setVisible(...) code is not being called from the ActionListeners. Instead you need to put the mechanisms for changing the views within the ActionListeners themselves, not just changing state, not unless you are using a "bound property" and PropertyChangeListeners.
Myself, I'd recommend using a CardLayout to assist you in your swapping, and rather than directly changing Strings, call a public method of your class -- planning for when and if the ActionListener (controller) code is ever removed from the view class.
Also, regarding:
btnPage.setVisible(window == "page" ? false : true);
don't compare Strings using == or !=. Use the equals(...) or the equalsIgnoreCase(...) method instead. Understand that == checks if the two object references are the same which is not what you're interested in. The methods on the other hand check if the two Strings have the same characters in the same order, and that's what matters here.
Also, if all you want to do is change the text and behavior that a JButton is doing, then you can change this easily by using setText(...) to change only the text, and for a deeper change, call setAction(Action action) to change text and state.

Why can't I get KeyEvent.VK_TAB when I use Key Binding for a JPanel

I will print related info if users focus on current window and press a key. However, it works for some keys like 'a' but not for 'tab'. Here is a simple demo:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class KeyBindingTest {
public static void main(String[] args) {
KeyBindingTest test = new KeyBindingTest();
test.createUI();
}
public void createUI(){
JFrame frame = new JFrame("KeyBinding Test");
MainPanel mainPanel = new MainPanel();
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#SuppressWarnings("serial")
class MainPanel extends JPanel{
public MainPanel(){
setPreferredSize(new Dimension(200, 200));
//========================key binding============================
requestFocusInWindow();
String aString = "aStr";
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), aString);
getActionMap().put(aString, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("a is typed");
}
});
String tabString = "tabStr";
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
getActionMap().put(tabString, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("tab is typed");
}
});
}
}
}
What can I do to reach it? Thanks in advance.
Quote from How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features) (suggested by #alex2410(link to #camickr post) and #mKorbel):
In most Look and Feel models, components are navigated using the Tab and Shift-Tab keys. These keys are the default focus traversal keys and can be changed programmatically.
...
Tab shifts the focus in the forward direction. Shift-Tab moves the focus in the backward direction. Tabbing moves the focus through the buttons into the text area. Additional tabbing moves the cursor within the text area but not out of the text area because, inside a text area, Tab is not a focus traversal key. However, Control-Tab moves the focus out of the text area and into the first text field. Likewise, Control-Shift-Tab moves the focus out of the text area and into the previous component.
...
The Control key is used by convention to move the focus out of any component that treats Tab in a special way, such as JTable.
You have just received a brief introduction to the focus architecture. If you want more details, see the specification for the Focus Subsystem.
So if you want to make the Tab KeyBinding action work in the panel, you need to remove the Tab key focus navigation from the panel.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
//http://stackoverflow.com/q/24800417/714968
public class KeyBindingTest3 {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame("KeyBinding Test");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new MainPanel());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class MainPanel extends JPanel {
public MainPanel() {
super();
//#see JTable constructor
Set<KeyStroke> forwardKeys = new HashSet<KeyStroke>(1);
forwardKeys.add(KeyStroke.getKeyStroke(
KeyEvent.VK_TAB, InputEvent.CTRL_MASK));
setFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardKeys);
Set<KeyStroke> backwardKeys = new HashSet<KeyStroke>(1);
backwardKeys.add(KeyStroke.getKeyStroke(
KeyEvent.VK_TAB, InputEvent.SHIFT_MASK | InputEvent.CTRL_MASK));
setFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, backwardKeys);
setPreferredSize(new Dimension(200, 200));
String aString = "aStr";
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), aString);
getActionMap().put(aString, new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
System.out.println("a is typed");
}
});
String tabString = "TAB";
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
getActionMap().put(tabString, new AbstractAction() {
#Override public void actionPerformed(ActionEvent e) {
System.out.println("tab is typed");
}
});
}
}
interesting issue with TAB, looks like as bug, because isn't possible to get, capture the KeyChar from TAB without using Shift_TAB before, event from TAB is somehow consumed elsewhere, no idea whats happened
my view - there is an issue with Focus because key TAB is used by Native OS and as built_in KeyBindings in Swing,
opposite issue with TAB and Shift_TAB in question Java Swing: how to stop unwanted shift-tab keystroke action
maybe someone has explanation how to catch a TAB event
TAB is used as KeyBindings (built_in in API) for many JComponents or navigations inside Container contains more than one JComponent
funny output from AWTEventListener (win8_64b/Java7_xxx)
is typed //tab is pressed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed //shift is pressed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed
is typed // tab is pressed again
is typed
is typed
is typed
is typed //:-) nobody knows something from milky way
is typed
is typed
shift tab is typed //now is tab event unlocked for Container in Swing
shift tab is typed
shift tab is typed
ctrl tab is typed
ctrl tab is typed
ctrl tab is typed
tab is typed // now is possible, finally TAB is unlocked and firing an event
tab is typed
tab is typed
from code
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
//https://stackoverflow.com/q/24800417/714968
public class KeyBindingTest {
public static void main(String[] args) {
KeyBindingTest test = new KeyBindingTest();
test.createUI();
}
public void createUI() {
JFrame frame = new JFrame("KeyBinding Test");
MainPanel mainPanel = new MainPanel();
frame.add(mainPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof KeyEvent) {
KeyEvent ke = (KeyEvent) event;
System.out.println(ke.getKeyChar() + " is typed");
}
}
}, AWTEvent.KEY_EVENT_MASK);
}
#SuppressWarnings("serial")
class MainPanel extends JPanel {
public MainPanel() {
setPreferredSize(new Dimension(200, 200));
//========================key binding============================
//requestFocusInWindow();
String aString = "aStr";
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), aString);
getActionMap().put(aString, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("a is typed");
}
});
String tabString = "TAB";
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(tabString), tabString);
//getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
this.getActionMap().put(tabString, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("tab is typed");
}
});
String tabShiftString = "shift TAB";
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(tabShiftString), tabShiftString);
//getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
this.getActionMap().put(tabShiftString, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("shift tab is typed");
}
});
String ctrlShiftString = "ctrl TAB";
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(ctrlShiftString), ctrlShiftString);
//getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tabString);
this.getActionMap().put(ctrlShiftString, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("ctrl tab is typed");
}
});
}
}
}
I think it should work if you put
setFocusTraversalKeysEnabled(false);
in your MainPanel constructor. At least it works for e.g. addKeyListener(...);

Displaying a TextField on user interaction

I want to display a TextField only when user has entered a value in Input field
Here is my code:
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class PlayingAround {
JFrame frame;
JTextField display;
JTextField input;
public static void main(String[] args) {
PlayingAround obj = new PlayingAround();
obj.create();
}
private void create() {
frame = new JFrame();
display = new JTextField();
input = new JTextField();
display.setEditable(false);
display.setVisible(false);
input.addKeyListener(new Listener());
frame.add(BorderLayout.NORTH, display);
frame.add(BorderLayout.SOUTH, input);
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class Listener implements KeyListener {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
display.setVisible(true);
display.setText(input.getText());
}
}
}
But my problem is that the Display JTextField doesn't becomes visible until there are some events like Resizing the Window, Minimizing and maximizing the Window.
I tried calling frame.repaint() in the keyReleased Method but even it has not helped.
You should call revalidate() and repaint() on the container that holds the JTextField after placing the text field component in the container. The revalidate() call sends a request to the container's layout managers to re-layout its components. The repaint() then requests that the JVM request of the paint manager to redraw the newly laid out container and its child components. The repaint() is not always needed but is usually a good idea.
Also, don't use a KeyListener for this, but rather a DocumentListener on the first text component's Document. This way, if the user empties the first text component, you can make the second text component disappear if desired. Also, text can be entered without key presses, and you want to allow for that.

Categories

Resources