如何取消焦点JTextField

当我的应用程序加载(使用netbeans)时,第一个JTextField会自动聚焦,在这个JTextField中,我写了“输入你的用户名”,当用户点击这个字段时,它会消失,但是当加载应用程序时,这个领域是重点,意味着我看不到“输入你的用户名”,如何在启动时不重点?

登录最好在modal dialog中完成,但是这会引入一些问题,因为必须在组件可见之后调用requestFocusInWindow()方法,但是对话框是模态的,这会阻止它!

此示例使用Rob Camick的RequestFocusListener (如Dialog Focus中所示 )在对话框可见后管理焦点。

使用重点密码字段登录

注意:这是在用户执行任何操作之前的显示方式。 密码字段默认为焦点。

 package test.t100.t001; import java.awt.BorderLayout; import java.awt.GridLayout; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; public class LoginRequired { LoginRequired() { JFrame f = new JFrame("Login Required"); f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); f.setSize(400, 300); f.setResizable(false); f.setLocationByPlatform(true); f.setVisible(true); showLogin(f); } private void showLogin(JFrame frame) { JPanel p = new JPanel(new BorderLayout(5,5)); JPanel labels = new JPanel(new GridLayout(0,1,2,2)); labels.add(new JLabel("User Name", SwingConstants.RIGHT)); labels.add(new JLabel("Password", SwingConstants.RIGHT)); p.add(labels, BorderLayout.WEST); JPanel controls = new JPanel(new GridLayout(0,1,2,2)); JTextField username = new JTextField("Joe Blogs"); controls.add(username); JPasswordField password = new JPasswordField(); password.addAncestorListener(new RequestFocusListener(false)); controls.add(password); p.add(controls, BorderLayout.CENTER); //LayoutManager l = new GroupLayout(p); //p.setLayout(l); JOptionPane.showMessageDialog( frame, p, "Log In", JOptionPane.QUESTION_MESSAGE); } /** * @param args none */ public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { new LoginRequired(); } }); } } /** * Convenience class to request focus on a component. * * When the component is added to a realized Window then component will * request focus immediately, since the ancestorAdded event is fired * immediately. * * When the component is added to a non realized Window, then the focus * request will be made once the window is realized, since the * ancestorAdded event will not be fired until then. * * Using the default constructor will cause the listener to be removed * from the component once the AncestorEvent is generated. A second constructor * allows you to specify a boolean value of false to prevent the * AncestorListener from being removed when the event is generated. This will * allow you to reuse the listener each time the event is generated. */ class RequestFocusListener implements AncestorListener { private boolean removeListener; /* * Convenience constructor. The listener is only used once and then it is * removed from the component. */ public RequestFocusListener() { this(true); } /* * Constructor that controls whether this listen can be used once or * multiple times. * * @param removeListener when true this listener is only invoked once * otherwise it can be invoked multiple times. */ public RequestFocusListener(boolean removeListener) { this.removeListener = removeListener; } @Override public void ancestorAdded(AncestorEvent e) { JComponent component = e.getComponent(); component.requestFocusInWindow(); if (removeListener) component.removeAncestorListener( this ); } @Override public void ancestorMoved(AncestorEvent e) {} @Override public void ancestorRemoved(AncestorEvent e) {} } 

使用requestFocusInWindow()将焦点设置在某个其他组件上,而不是先设置JTextfield

但是我建议不要constructor调用initComponents()之后改变原生焦点系统,而不是改变 JTextField上的setText(String s) (假设是在netbeans中)。

进一步可选阅读: 如何使用Focus子系统

我认为将键盘焦点放在用户名字段是正确的行为,假设这是用户首先需要做的事情。 而不是清除焦点,为什么不在用户输入内容后清除?:

 import java.awt.*; import javax.swing.*; import javax.swing.text.Document; public class PlaceholderTextField extends JTextField { public static void main(final String[] args) { final PlaceholderTextField tf = new PlaceholderTextField(""); tf.setColumns(20); tf.setPlaceholder("All your base are belong to us!"); final Font f = tf.getFont(); tf.setFont(new Font(f.getName(), f.getStyle(), 30)); JOptionPane.showMessageDialog(null, tf); } private String placeholder; public PlaceholderTextField() { } public PlaceholderTextField( final Document pDoc, final String pText, final int pColumns) { super(pDoc, pText, pColumns); } public PlaceholderTextField(final int pColumns) { super(pColumns); } public PlaceholderTextField(final String pText) { super(pText); } public PlaceholderTextField(final String pText, final int pColumns) { super(pText, pColumns); } public String getPlaceholder() { return placeholder; } @Override protected void paintComponent(final Graphics pG) { super.paintComponent(pG); if (placeholder.length() == 0 || getText().length() > 0) { return; } final Graphics2D g = (Graphics2D) pG; g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(getDisabledTextColor()); g.drawString(placeholder, getInsets().left, pG.getFontMetrics() .getMaxAscent() + getInsets().top); } public void setPlaceholder(final String s) { placeholder = s; } } 

如果你真的只想删除焦点,可以选择一些选项:

  • component.setFocusable(false);
  • KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
  • KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
 textField.setFocusable(false); textField.setFocusable(true); 

如果且仅当textField具有焦点时,TAB顺序中的下一个组件将自动获得焦点。 效果与TAB印刷机相同。

(没有在只有一个可聚焦组件的GUI中测试:))