I'm aware this is something that has been asked and I've used some of the solutions/examples provided in the forum but they seem to be unable to work for me.
Essentially I have JInternalFrames which contain JTextAreas and I would like it it that when the JInternalFrame is visible focus i.e. the cursor is placed on the JTextArea as opposed to the user having to manually place the cursor by clicking on the JTextArea.
Below are my attempted solutions:
Solution 1:
textAreaUName.requestFocus(true);
Solution 2:
textAreaUName.requestFocus(true);
textAreaUName.requestFocusInWindow();
Apologies once again if you have seen the question being asked severally.
Thanks for any ideas.
This will set the focus on a JComponent which is not null and focusable.
public final void requestFocus(final JComponent component)
{
Runnable r = new Runnable() {
#Override
public void run() {
while (!component.isFocusOwner()) {
component.requestFocusInWindow();
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(TestFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
if(component!=null&&component.isFocusable())
{
Executors.newCachedThreadPool().execute(r);
}
}
Related
I want to create a JDialog where the text in the textfields is selected but only if the focus is gained from keyboard (TAB, CTRL+TAB). I have found several topics on this matter but had problems with implementing it.
Here is one which I was trying.
And my code:
public class Dialogg extends JDialog implements FocusListener, MouseListener {
private boolean focusFromMouse = false;
public Dialogg() {
JTextField tf1 = new JTextField("text1");
JTextField tf2 = new JTextField("text2");
tf1.addMouseListener(this);
tf2.addMouseListener(this);
tf1.addFocusListener(this);
tf2.addFocusListener(this);
}
#Override
public void focusGained(FocusEvent e) {
if (!focusFromMouse) {
JTextField tf = (JTextField) e.getComponent();
tf.selectAll();
focusFromMouse = true;
}
}
#Override
public void focusLost(FocusEvent e) {
focusFromMouse = false;
}
#Override
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
}
It does not work as intended, it does not matter what is focus source the text always highlights. When I run the code and follow it step by step it turns out that focusGained code happens before mouseClicked code so the flag is not reset when it should. Any hints?
EDIT:
As suggested by M. Prokhorov I have deleted less relevant (for the question) lines from the code.Thank you.
EDIT 2:
I am trying to wrap focus listener as suggested by camickr. It looks like this now:
tf1.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent evt){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (!focusFromMouse){
tf1.selectAll();
focusFromMouse=true;
}
}
});
}
public void focusLost(FocusEvent evt){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
focusFromMouse=false;
}
});
}
});
public void mouseClicked(MouseEvent e) {
focusFromMouse=true;
I am printing line after each event to see the action order and still mouseClicked happens last. What am I doing wrong?
EDIT 3:
OK, I have found a solution which fulfils requirements of my simple Dialog.
I could not find a way of doing this with use of invokeLater or EventQueue. Vladislav's method works but as I understand it restricts the user to only use the keyboard.
I have used the initial approach but I have added an auxiliary variable and few conditions which allow to pass the flag "unharmed" trough Events that should not change the flag at given moment. It may not be subtle or universal but works for my app. Here is the code:
public void focusGained(FocusEvent e) {
if(!focusFromMouse){
if (higlight){
JTextField tf = (JTextField) e.getComponent();
tf.selectAll();
focusFromMouse=false;
}
}
}
public void focusLost(FocusEvent e) {
if (focusFromMouse){
higlight=false;
focusFromMouse=false;
}else{
higlight=true;
}
}
public void mousePressed(MouseEvent e) {
focusFromMouse=true;
}
At the first, by default, focus on JTextField is requested by mouse-press event, not by mouse-click.
So, this method:
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
is useless because the mouse-click event is triggered after the mouse-press event.
One way to solve your problem is to remove all native MouseListeners from JTextField:
...
for( MouseListener ml : tf1.getMouseListeners() ){
tf1.removeMouseListener(ml);
}
for( MouseMotionListener mml : tf1.getMouseMotionListeners() ){
tf1.removeMouseMotionListener(mml);
}
...
Another way is to handle all mouse events and consume those of them, which are triggered by JTextField:
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if( event.getSource() == tf1 ){
((MouseEvent)event).consume();
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
When I run the code and follow it step by step it turns out that focusGained code happens before mouseClicked
Wrap the code in the FocusListener in a SwingUtilities.invokeLater(). The will place the code on the end of the Event Dispatch Thread (EDT), so the code will run after the variable in the MouseListener has been set.
See Concurrency in Swing for more information about the EDT.
Edit:
Just noticed the other answer. You might be able to do something simpler. Istead of listener for mouseClicked, listen for mousePressed. A mouseClicked event is only generated AFTER the mouseReleased event, so by that time the FocusListener logic has already been executed, even when added to the end of the EDT.
Edit 2:
If the above doesn't work then you might be able to use the EventQueue.peek() method to see if a MouseEvent is on the queue. This might even be easier than worrying about using the invokeLater.
What I want is entirely WindowsLookAndFeel, and I have this code in my JFrame.
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception ex) {
ex.printStackTrace();
}
However, what I got it part Windows, part Metal (the cross platform style which looks awful. I think I know where the problem is:
The abnormal part(metal part) is a JPanel, and it is not originally built in the JFrame. I have a button. If pressed, the JPanel will be added to the JFrame.
if (((JToggleButton) e.getSource()).isSelected()) {
getContentPane().add(Console.getInstance(), BorderLayout.EAST);
} else {
remove(Console.getInstance());
}
revalidate();
pack();
But still, I don't know why this happens, and how to solve it.
You need to define the look and feel outside of the EDT. Create a class having a main method. In that method set the LAF and then display the app:
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch(Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jFrame.pack();
jFrame.setVisible(true);
}
});
I am trying to extend JXDatePicker so that it opens up when it gains focus.
Have searched for suggest that I understand without success.
Is there an elegant way of doing this?
Astonishingly, it's not really possible :-(
For once, the JXDatePicker itself has no api to show/hide the popup (only BasicDatePickerUI has). Plus the ui delegate has some internal magic (read: hacks ... cough) that makes a FocusListener even worse to handle than usually in compound components.
A snippet to play with:
final JXDatePicker picker = new JXDatePicker();
FocusListener l = new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
// no api on the picker, need to use the ui delegate
BasicDatePickerUI pickerUI = (BasicDatePickerUI) picker.getUI();
if (!pickerUI.isPopupVisible()) {
pickerUI.toggleShowPopup();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// opening the popup moves the focus to ... ?
// need to grab it back onto the editor
picker.getEditor().requestFocusInWindow();
}
});
}
#Override
public void focusLost(FocusEvent e) {
}
};
// need to register the listener on the editor
picker.getEditor().addFocusListener(l);
JComponent content = new JPanel();
content.add(new JButton("dummy"));
content.add(picker);
Not really satisfying, as automatic closing of the popup on transfering the focus out again doesn't work reliably, needs two tabs (don't know why)
I had the same problem.
This worked for me:
jXDatePicker.getEditor().addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
BasicDatePickerUI pickerUI = (BasicDatePickerUI) jXDatePicker.getUI();
if (!pickerUI.isPopupVisible() && e.getOppositeComponent() != getRootPane() && e.getOppositeComponent() != jXDatePicker.getMonthView()) {
pickerUI.toggleShowPopup();
}
}
#Override
public void focusLost(FocusEvent e) {}
});
This piece of code is used to avoid focus issues:
e.getOppositeComponent() != getRootPane()
I make my game run without mouse so using pointer is not a choice. High Score menu will show when player lose.
this is my code
highScore=new MyTextField("Your Name");
highScore.addKeyListener(this);
highScore.setFont(font);
highScore.requestFocusInWindow();
I have tried
highScore.setFocusable(true);
highScore.requestFocusInWindow();
highScore.requestFocus(true);
highScore.requestFocus();
but still not gained focus on my JTextField.
How to focus it?
If you want your JTextField to be focused when your GUI shows up, you can use this:
in = new JTextField(40);
f.addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
in.requestFocus();
}
});
Where f would be your JFrame and in is your JTextField.
if is there only one Top-Level Container then last lines in GUI constructor would be for example
.
.
.
myFrame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myComponent.grabFocus();
myComponent.requestFocus();//or inWindow
}
});
public void actionPerformed(ActionEvent arg0)
{
if (arg0.getSource()==clearButton)
{
enterText.setText(null);
enterText.grabFocus(); //Places flashing cursor on text box
}
}
Try this one,
myFrame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myComponent.grabFocus();
myComponent.requestFocus();//or inWindow
}
});
If the page contains multiple item and like to set the tab sequence and focus I will suggest to use FocusTraversalPolicy.
grabFocus() will not work if you are using FocusTraversalPolicy.
Sample code
int focusNumber = 0;
Component[] focusList;
focusList = new Component[] { game, move, amount, saveButton,
printButton, editButton, deleteButton, newButton,
settingsButton };
frame.setFocusTraversalPolicy(new FocusTraversalPolicy() {
#Override
public Component getLastComponent(Container aContainer) {
return focusList[focusList.length - 1];
}
#Override
public Component getFirstComponent(Container aContainer) {
return focusList[0];
}
#Override
public Component getDefaultComponent(Container aContainer) {
return focusList[1];
}
#Override
public Component getComponentAfter(Container focusCycleRoot,
Component aComponent) {
focusNumber = (focusNumber + 1) % focusList.length;
if (focusList[focusNumber].isEnabled() == false) {
getComponentAfter(focusCycleRoot, focusList[focusNumber]);
}
return focusList[focusNumber];
}
#Override
public Component getComponentBefore(Container focusCycleRoot,
Component aComponent) {
focusNumber = (focusList.length + focusNumber - 1)
% focusList.length;
if (focusList[focusNumber].isEnabled() == false) {
getComponentBefore(focusCycleRoot, focusList[focusNumber]);
}
return focusList[focusNumber];
}
});
In my case nothing above worked untill I called requestFocus() AFTER my constructor has returned.
MyPanel panel = new MyPanel(...);
frame.add(panel);
panel.initFocus();
MyPanel.initFocus() would have:
myTextField.requestFocus();
And it works.
This code mouse cursor “jtextfield” “Jcombobox” location focused
try {
Robot robot = new Robot();
int x = Jtextfield.getLocationOnScreen().x;
int y= Jtextfield.getLocationOnScreen().y;
JOptionPane.showMessageDialog(null, x+"x< - y>"+y);// for I location see
robot.mouseMove(x, y);
} catch (AWTException ex) {
ex.printStackTrace();
}
It was not working for me when tried to use:
JOptionPane.showConfirmDialog(...)
But -
I found a solution !
Very primitive, but works.
Just jump to the field by java.awt.Robot using key "Tab".
For example:
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
If you should press multiple times on "Tab" to get your Component you can use below method:
GUIUtils.pressTab(3);
Definition:
public static void pressTab(int amountOfClickes)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
Robot robot = new Robot();
int i = amountOfClickes;
while (i-- > 0)
{
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
}
}
catch (AWTException e)
{
System.out.println("Failed to use Robot, got exception: " + e.getMessage());
}
}
});
}
If your Component location is dynamic, you can run over the while loop without limitation, but add some focus listener on the component, to stop the loop once arrived to it.
While yourTextField.requestFocus() is A solution, it is not the best since in the official Java documentation this is discourage as the method requestFocus() is platform dependent.
The documentation says:
Note that the use of this method is discouraged because its behavior is platform dependent. Instead we recommend the use of requestFocusInWindow().
Use yourJTextField.requestFocusInWindow() instead.
How about put jTextField.requestFocusInWindow(); into jTextField FocusLost event?
Works for me
have 5 controls on JPanel
Soon as click on MessageBox, focus lost on jTextField.
Used all the suggested codes but no luck
Only above method works my case.
I created a form using Swing in Java. In the form I have used a JTextField on which I have to set the focus whenever I press a key. How do I set focus on a particular component in Swing?
Would Component.requestFocus() give you what you need?
This would work..
SwingUtilities.invokeLater( new Runnable() {
public void run() {
Component.requestFocus();
}
} );
Now that we've searched the API all we need to do is read the API.
According to the API documentation:
"Because the focus behavior of this
method is platform-dependent,
developers are strongly encouraged to
use requestFocusInWindow when
possible. "
Note that all of the above fails for some reason in a JOptionPane. After much trial and error (more than the above stated 5 minutes, anyway), here is what finally worked:
final JTextField usernameField = new JTextField();
// ...
usernameField.addAncestorListener(new RequestFocusListener());
JOptionPane.showOptionDialog(this, panel, "Credentials", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
public class RequestFocusListener implements AncestorListener {
#Override
public void ancestorAdded(final AncestorEvent e) {
final AncestorListener al = this;
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JComponent component = e.getComponent();
component.requestFocusInWindow();
component.removeAncestorListener(al);
}
});
}
#Override
public void ancestorMoved(final AncestorEvent e) {
}
#Override
public void ancestorRemoved(final AncestorEvent e) {
}
}
You can use also JComponent.grabFocus(); it is the same