getFocusOwner with a custom class - java

I need help working getFocusOwner(). I have a Sudoku game that I made in Java and I want to add arrow key navigation to the program. I did some research and found that using the focus system would be the best way (If it's not, please give me a better way and I can research that).
Okay, so for testing purposes, I'm trying to set focus to SetField, a custom class extending JTextField(Custom because I wanted to disable any inputs that weren't numbers). It has been set to focusable. I called requestFocusInWindow() on the SetField in the middle of the grid, and the focus is set to that component. The problem arises when I try and retrieve the component that has focus.
This is what I'm doing to test the getFocusOwner() method:
sGrid[40].requestFocusInWindow();
try{
System.out.println(this.getFocusOwner().getClass().getSimpleName());
} catch(NullPointerException e){
e.printStackTrace();
}
No matter what component I try this on, I always get the null pointer exception. I tried it with the JButtons, JLabels, and even on JPanels in my program. The focus is set to the component though. I can see the caret blinking in the intended SetField. Is there something I'm doing wrong? Thanks in advance for any help.

Instead of a custom component to only allow numbers, just us a JFormattedTextField.
Do you need to even determine which component has focus, why not add a KeyListener, MouseListener? I am not exactly sure what you doing with the focus but it seems strange.

I want to add arrow key navigation to the program.
You should be using Key Bindings. Create a basic "ChangeFocusAction". You will need 4 instance of this class that you can map to a KeyStroke.
Assuming you have a array of 81 text fields your Action could be created with an integer value that tells the Action how to change focus. For example:
right = -1
left = 1
up = -9
down = 9
The source of the ActionEvent will contain the text field that has focus. Then you search the arry to find the offset of that text field. Then you add the int value from above to the index and request focus on that component.

Just found out the problem. For anyone else that's having a problem with this, try using (Window).getMostRecentFocusOwner(). This worked for me.

Related

Remove/disable/override Swing's focus traversal keys

Note: see the edit (save some time reading)
I'm trying to make my mind-mapping program respond to shortcuts like CTRL+RIGHT (reordering nodes) and TAB (insert child at next indent level). I have a JPanel that handles all of the keystrokes. It resides inside of a JTabbedPane that might be the cause for Key Bindings not working. I've chickened out and decided to just use KeyListener.
The problem is that with the aforementioned key combinations, Swing automatically shifts the focus to some other component. I'd rather not manually put setFocusable(false) everywhere. How can I disable these shortcuts altogether in such a way that the focus will not be shifted, and the relevant KeyEvents will still be sent to my JPanel?
Edit:
I used the following code:
for (int id : new int[] {KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS})
setFocusTraversalKeys(id, Collections.EMPTY_SET);
to disable the default traversal keys (particularly TAB.)
Now the issue is actually why CTRL+UP causes a loss of focus. When pressing CTRL+DOWN, for instance, it's fine. The component behaves as expected. But with CTRL+UP, it works as expected and then focus is shifted/lost somehow. Can anyone say what CTRL+UP means and how to disable it wherever it is? Google isn't helping.
KeyBinding are used for all KeyEvents implemented in Swing APIs, maybe there is/are conflict
is required to override required KeyBindings, change used Keys, set to null, e.i. depends of your requirements
list of KeyBindings by #camickr

Java swing - creating text field on button's place

When specific action is performed, I want to replace button with text field. I know that I have to call button1.setVisible(false); but I don't know how to create text field on the exact same place. I am using NetBeans designer, if you can give me a hint, how to add 2 components at same place, and switch between then, something like switching between layers in photoshop, if something like that is possible, would be great. Thanks
For many components in one space, use a CardLayout as see in this short example.

Swing - Changing the content of a panel using UpdateUI

I am going through a legacy application which is using Swing and i am struggling to figure out how the screens are changing when a user clicks a button. One of the reasons i cant figure this out is because this is the first time i am using Swing. I have read a book and got the basics but still struggling.
Basically, the screen i am looking at has a JSplitPane which has a number of shortcut buttons on the left and an empty pane on the right. When i click on the button, the right side pane is populated with a different screen depending on the button pressed.
Going through the code, i was expecting somewhere that there will be something that calls a setVisible() method depending on which button is pressed.
The actionPerformed method for each of the shortcut buttons looks something like this:
void shortCutBtn_actionPerformed(ActionEvent e) {
propertyChangeListeners.firePropertyChange("selectedShortCut", previousShortCutSel, currentShortCutSel);
mainPanel.updateUI();
}
I have gone through most of the code and came to a conclusion that the above code is what is causing the frame switching but i dont understand how that is happening.
Each screen is identified by a numeric constant. In the above code example, previousShortCutSel and previousShortCutSel refer to a numeric value that represents individual screens screen.
I have tried to look for documentation of how updateUI() works but i am lost. How does the above cause the content of the right panel of the JSplitPanel to be updated with a new screen?
This is not an appropriate use of updateUI(), which "Resets the UI property to a value from the current look and feel." As the example itself may be unreliable, consider studying another. GoogleOlympiad, for example, sets a label's icon using a (cached) image.
ImageIcon image = getImage(index);
imageLabel.setIcon(image);
(source: drjohnbmatthews at sites.google.com)
As per comments by ziggy (glad it helped)
Have a look at the PropertyChangeListeners that appear to be added in the code. In particular the propertyChange(PropertyChangeEvent e) method is where the code which changes the content will be present.
+1 to trashgod nice example/advice as always

How do I keep keyboard focus on a single component?

I need to keep keyboard input focus on a single component inside a JPanel. It's for an application with a on-screen-keyboard.
Not sure I really understand the question. But you can try something like:
otherComponents.setFocusable( false );
You also might need to use a custom FocusTraversalPolicy.
If you need more help then post a SSCCE that demonstrates the problem.
You better put the focus back to the component (component.grabFocus()) after pressing a button on the on-screen keyboard.
Or you could set focus listener (component.addFocusListener(FocusListener l)) and never let go of the focus by calling grabFocus() in the focusLost() method of FocusListener.
This will give you focus on your singleComponent when opening your Frame, without having to change the focus policy of enything else: singleComponent.requestFocusInWindow(); Since the focus will not freeze, you will need to setFocusable(false) for the other components like camicr suggests.
Just a guess: take a look at the InputVerifier.

How to remove text above JSlider

I have a JSlider in my GUI that goes from 0 to 100. For some reason, there is text above the slider position that displays the current value of the slider and it follows my slider around. I.e., if I move my slider halfway, "50" appears above where my slider currently is. However, I can't figure out what that text field is called, all I know is its part of the slider.
I want to either remove it or be able to change it to something else, how would I do that?
I would have just commented on Etaoin's answer, but I don't have the reputation for it yet.
At any rate, call this before instantiating the JSlider:
UIManager.put("Slider.paintValue", false);
Note the capital 'V' in paintValue.
Furthermore, to print all of the fun things that are currently set by your UIManager, enter this code anywhere after the UIManager has been instantiated:
Iterator<Entry<Object, Object>> it = UIManager.getDefaults().entrySet().iterator();
while(it.hasNext())
System.out.println(it.next());
This bothered me on a project once, and I found the following workaround. Call this once before instantiating your JSlider -- I put it in a static block in my JPanel subclass:
UIManager.put("Slider.paintValue", false);
That'll take care of it.
Do you mean a tooltip? Is it a little box that appears over the slider control and follows your mouse around if you grab the slider?
If this is the case, you can disable it simply by calling setToolTipText( null ), or override the text with setToolTipText( "My Text" ).
As I see there is a setLabelTable method in JSlider with a Dictionary parameter.
I have not used it but I guess that if you set it to an empty dictionary (or empty labels for every possible value) then no labels will appear.
A better solution is the usage of setPaintLabels with a false value.

Categories