I have a JPanel inside a JFrame. I have registered a KeyListener, based on which I want to update the JPanel. The problem I am having is that I cannot get the focus on the JPanel and therefore my KeyListener won't work. I already know that the KeyListener is functional because I registered it with the JFrame and it worked fine. My code goes something like this at the moment:
myFrame.setFocusable(false);
myPanel.setFocusable(true);
myPanel.addKeyListener(myKL);
myFrame.add(myPanel);
Has anyone encountered a problem like this before? Is there something I am missing in regards to this?
P.S.: I do not have any components inside the JPanel I just draw an Image on the background, so I need the focus to be on the JPanel itself and not on something inside it.
Although you're indicating that the panel can be focusable, the panel isn't asking for focus. Try using myPanel.requestFocus();.
Use setFocusable(true) and then requestFocusInWindow(). But the latter must be done after the window containing the panel is made visible, for which you will likely need to register a window listener and do the requestFocusInWindow() in the window activated handler code.
Note: Specifically after the window is visible, not just after calling setVisible(true).
I sometimes face a similar problem. I've noticed that in some cases it is better to make or request focus on a specific control within the panel that is within the frame (e.g., the input box to which you want keyboard input to go), rather than request focus for the pane itself.
Try
panel.setFocusable(true);
panel.setRequestFocusEnabled(true);
// some code here
panel.grabFocus();
Try something like this:
myFrame.addFocusListener(new FocusAdapter() {
/**
* {#inheritDoc}
*/
#Override
public void focusGained(FocusEvent aE) {
myPanel.requestFocusInWindow();
}
});
Related
I'm trying to set a variable to be a new JPanel and then add it once a button is pressed, but it is not working and I don't know why.
code:
private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {
remove(scriptPanel);
scriptPanel = new GemPanel();
add(scriptPanel);
validate();
repaint();
pack();
}
GemPanel is just a JPanel class I made. When I press the next button, it re-sizes the frame to be as small as possible and nothing actually happens. If I re-size it to normal, the original scriptPanel is still there.
What gives?
Instead of trying to remove and add entire panels, a better, less problem prone approach would be to use a CardLayout that will allow to swap views. You can see more at How to use Cardlayout
Also, by the looks of your method signature, it seems you're using the Netbeans builder too. You may also want to take a look at How to Use CardLayout with Netbeans Gui Builder
Let me first explain the situation,
I have a class with a JPanel called panelclass.
It's method getPanel() returns the JPanel.
In a JFrame class called frameclass, I create a new object of panelclass, got its panel and added it to the frame pane.
What I am trying to achieve is, when a button in paneclass is clicked, It should close this JFrame ie.frameclass.
I donot know how a panelclass can communicate back to the frameclass to close.
I tried this.dispose() and super.dispose() but was not successful even after extending JFrame
Is there a simpler way?
Please do help.
There are a few was to achieve this, but the simplest is probably through the use of SwingUtilities.getWindowAncestor(Component)
This will return the Window that the component was added to or null if it has no parent window. From there you can simply call Window#dispose to close the frame.
when a button in paneclass is clicked, It should close this JFrame
See Closing an Application. I prefer using something like the `ExitAction' described there. The reason is that your application will behave just like the user clicked on the close button of the frame which means that if you have any WindowListeners added to the window they will be invoked.
I have a CardDetailsPanel class which contains several JLabels and JTextFields. This class in contained in a AddCardsPanel and is initialized as follows:
cardDetailsPanel = new CardDetailsPanel(true);
add(cardDetailsPanel, java.awt.BorderLayout.CENTER);
I also have a JLabel that contains instructions. I want to update this label when the CardDetailsPanel first appears and when focus changes to each JTextField. I have found the addFocusListener() method that will work for the later. However, my compenentShown() method isn't working for the former:
addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentShown(java.awt.event.ComponentEvent evt) {
formComponentShown(evt);
}
});
(Okay, I know this is ugly. It was generated by NetBeans.)
private void formComponentShown(java.awt.event.ComponentEvent evt) {
this.frame = (BaseballFrame) this.getParent().getParent().getParent().getParent().getParent().getParent();
}
(Yah, this is even uglier. I'll deal with the chained getParent() calls later. I want to do other things here as well.)
So why doesn't my listener get called? And how do I write a listener that will perform some actions whenever my CardDetailsPanel appears on the screen?
Use an AncestorListener as described in dialog focus.
When a JDialog (or JFrame for that matter) is made visible, focus is placed on the first focusable component by default. There may be times when you want to change this behaviour. The obvious solution would be to invoke the requestFocusInWindow() method on the component you wish to receive focus. The problem is that this doesn’t work all the time.
...
The problem is .. a component can’t request focus unless it has been added to a “realized” dialog. A realized dialog basically means that the Swing JDialog has been added to a peer component that represents a dialog on the underlying OS. This occurs when you invoke the pack() or setVisible(true) methods on the JDialog.
And that is where the ancestor listener comes in handy. For a component in a modal dialog, it will be fired once the component becomes visible, and is realized & focusable.
Edit:
The above comment applies to components in any Swing container, including JFrame and JPanel.
I add my customized panel onto JScrollPane. I also have another set of "tool" that will attach itself to my custom panel. The problem is, in these tool, it invokes attached.addMouseListener(this). Normally, everything would function well, but when I have it inside JScrollPane, it won't function at all. My deduction is JScrollPane never gives window focus to its child component. Is there a way to get this around without having to change my attachment procedure? I want my 'tool' to specifically attach to my custom panel, not the scrollpane.
I hope I have understood the problem.
What about adding a MouseListener to the JScrollPane and then dispatch the event to the JPanel?
Somenthing like this:
//JScrollPane Listener
public void mousePressed(MouseEvent me) {
jpanel.dispatchEvent(me);
}
It's a little bit tricky, but so you don't have to change the JPanel Listener.
I have a small dialog frame that appears, and within this frame are a series of buttons and a textbox.
I need the frame to be able to detect when the user has put focus on something else on the screen (being: anything besides the frame and its components), so I can close down the frame.
Any advice on how to go about this? I've been trying at focus solutions for hours, to no solution!
Try using a WindowStateListener
The WindowEvent parameter it provides can tell you if the window has lost focus through the getNewState() method.
class MyFocusLostListener implements WindowStateListener {
public void windowStateChanged(WindowEvent e) {
if (e.getNewState() == WindowEvent.WINDOW_LOST_FOCUS) {
e.getWindow().setVisible(false);
}
}
}
need the frame to be able to detect when the user has put focus on something else on the screen
Use a WindowListener and listen for windowDeactivated.
listen to property changes of the property "permanentFocusOwner" of the KeyboardFocusManager. On being notified, check if the new focusOwner is in the child hierarchy under the frame, if not - close the frame.
Edit: seeing the answers suggesting a Window/StateListener - they are better than mine for a top-level window :-) Listening to the keyboardFocusManager is a good approach for containers deeper down in the hierarchy, implemented f.i. in the CellEditorRemover of a JTable (to decide if a pending edit should be terminated)