views:

159

answers:

3

(Problem occur in Ubuntu only. Works fine in Windows. I don't know in other Linux environments)

I have used the approach of the ComponentListener to call focus in JTextField within a dialog, but for this case is just not working, I don't know why. It shows the focus in the text field and fast change to the button. Run and see:

import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class User {

    private String username = "";
    private String password = "";

    public User() {
    // default constructor
    }

    public User(String username, String password) {
    this.username = username;
    this.password = password;
    }

    /** Create a panel containing the componet and tha label. */
    public JPanel createLabeledComponent(JLabel label, Component comp) {
    GridLayout layout = new GridLayout(2, 1);
    JPanel panel = new JPanel(layout);
    panel.add(label);
    panel.add(comp);
    label.setLabelFor(comp);
    return panel;
    }

    public void showEditDialog() {

    JLabel usernameLbl = new JLabel(username);
    final JTextField usernameField = new JTextField();
    usernameField.setText(username);
    JPanel usernamePnl = createLabeledComponent(usernameLbl, usernameField);

    JLabel passwordLbl = new JLabel(password);
    JPasswordField passwordField = new JPasswordField(password);
    JPanel passwordPnl = createLabeledComponent(passwordLbl, passwordField);

    Object[] fields = { "User:", usernamePnl, "Password:", passwordPnl };

    JOptionPane optionPane = new JOptionPane(fields, JOptionPane.PLAIN_MESSAGE,
        JOptionPane.OK_CANCEL_OPTION, null, null);
    JDialog dialog = optionPane.createDialog("User Data");

    dialog.addComponentListener(new ComponentAdapter() {
        @Override
        public void componentShown(ComponentEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
            usernameField.requestFocusInWindow();
            }
        });
        }
    });

    dialog.setVisible(true);
    }

    public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
        new User().showEditDialog();
        }
    });
    }

}

Any idea how to solve this?

--update

Everything running on EDT now. Sadly with the same behavior.

By the way, either using the last argument (Object initialValue) of the JOptionPane constructor doesn't work.

A: 

Maybe this Dialog Focus solution will work on Ubuntu (I can't test it).

It shows the focus in the text field and fast change to the button.

Or you could try wrapping the requestFocusInWindow() method call in a SwingUtilities.invokeLater() to place your requrest on the end of the EDT.

camickr
question updated
Tom Brito
So you are saying this solution doesn't work in your environment? It would be nice to know so I can update the above link if it doesn't work in all environments. If my solution doesn't work as posted then the next step would be to wrap the focus code in a Swing utilities.invokeLater() so it gets added to the end of the EDT and presumably executes after the code that resets the focus to the first field.
camickr
+1  A: 

I remember having a similar problem, I used the solution found at the bottom of this page:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5018574

darri
Looks like the timer is the only working workaround here. Sad not a consistent solution (may work in a computer, but not in another, and may depends on computer speed). Anyway, thanks for the link.
Tom Brito
I'm using the Timer inside the windowActivated method. Not sure if will work everywhere, but looks like the best answer for now.
Tom Brito
A: 

From How to Use the Focus Subsytem:

Exactly how a window gains the focus depends on the windowing system. There is no foolproof way, across all platforms, to ensure that a window gains the focus.

Furthermore, from Component.requestFocusInWindow:

Every effort will be made to honor the request; however, in some cases it may be impossible to do so. Developers must never assume that this Component is the focus owner until this Component receives a FOCUS_GAINED event.

Your components may not be realized before you are calling requestFocusInWindow. Have you tried putting a dialog.pack(); before the setVisible(true)?

eaolson
dialog.pack() makes no difference.
Tom Brito
using focus listener doesn't solve either..
Tom Brito