如何在创建时将焦点设置在特定的JTextField内的JOptionPane中?

5
我希望将焦点设置在一个特定的JTextField上,该JTextField作为Object Message传递给JOptionPane。这是我的代码(我希望焦点在txt2上,但焦点总是在txt1上):
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class TextArea extends JPanel
{
    private JTextArea txt1 = new JTextArea();
    private JTextArea txt2 = new JTextArea();
    public TextArea()
    {
        setLayout(null);
        setPreferredSize(new Dimension(200,100));
        txt1.setBounds (20, 20, 220, 20);
        txt2.setBounds (20, 45, 220, 20);
        txt1.setText("Text Field #1");
        txt2.setText("Text Field #2");
        add(txt1);
        add(txt2);
        txt2.requestFocus();
    }
    private void display()
    {
        Object[] options = {this};
        JOptionPane pane = new JOptionPane();
        pane.showOptionDialog(null, null, "Title", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, txt2);
    }
    public static void main(String[] args)
    {
        new TextArea().display();
    }
}

1
我从未见过这种类型的JOptionPane以这种方式使用,我不确定这是否是正确的方法。为什么不使用JDialog呢? - Hovercraft Full Of Eels
1
这种方法没有任何问题。它通过完全创建自定义对话框来节省重新发明轮子的时间。您只需要创建自定义面板即可。 - camickr
1
@Eng Fouad,我很失望你采用了基于发布的代码的解决方案。这表明你只是复制解决方案,而不是花时间去理解其他给出的解决方案。我为你提供了一个简单的一行解决方案,你可以在不子类化组件的情况下使用它。可重用的解决方案通常比自定义解决方案更受欢迎。你不是通过复制解决方案学习,而是通过理解给出的建议来学习。 - camickr
@中文 Fouad,我的评论不是针对SSCCE(你发布的SSCCE很好)。我的评论是关于花时间理解提供的不同解决方案。 - camickr
@camickr:我同意将JPanel作为JOptionPane的对象参数的一般技术,没有问题,但他对它的使用似乎是对JOptionPane的歪曲,并阻止了选择选项的能力,而这正是使用showOptionDialog的全部原因。 - Hovercraft Full Of Eels
显示剩余4条评论
4个回答

6

当您重写addNotify时,可以让txt2组件请求焦点,如下所示:

private JTextArea txt2 = new JTextArea() {
    public void addNotify() {
        super.addNotify();
        requestFocus();
    }
};

这是一个完整的、经过测试的程序版本:

注意:以下翻译仅供参考,具体技术术语可能根据上下文有所不同。

import java.awt.Dimension;
import javax.swing.*;
public class Test extends JPanel {
    private JTextArea txt1 = new JTextArea();
    private JTextArea txt2 = new JTextArea() {
        public void addNotify() {
            super.addNotify();
            requestFocus();
        }
    };

    public Test() {
        setLayout(null);
        setPreferredSize(new Dimension(200, 100));
        txt1.setBounds(20, 20, 220, 20);
        txt2.setBounds(20, 45, 220, 20);
        txt1.setText("Text Field #1");
        txt2.setText("Text Field #2");
        add(txt1);
        add(txt2);
    }

    private void display() {
        Object[] options = { this };
        JOptionPane pane = new JOptionPane();
        pane.showOptionDialog(null, null, "Title", JOptionPane.DEFAULT_OPTION,
                JOptionPane.PLAIN_MESSAGE, null, options, txt2);
    }

    public static void main(String[] args) {
        new Test().display();
    }
}

而且你还将JPanel添加到JOptionPane showOptionDialog方法的选项参数中。这看起来对你来说不奇怪吗? - Hovercraft Full Of Eels
同意。这可能不是实现对话框的最佳方式。把它看作是一个快速、"最小化"的修复。 - aioobe

3

我在你上一个问题的答案中给了你答案(https://dev59.com/Zmw15IYBdhLWcg3wpNcB

如果你仍然不明白建议,请参见DialogFocus以获取可重复使用的代码。


+1 这个也可以,但是aioobe先回答了问题,所以我接受他的答案。无论如何,谢谢 :) - Eng.Fouad
5
@Eng Fouad,您指的是什么?我在3分钟前已经提供了答案!此外,昨天我还向您介绍了这个概念。无论如何,答案应该根据可重用性和其他设计考虑因素选择。您不能仅仅因为某人发布了代码就接受答案。您需要花时间理解代码的含义,以便在其他情况下使用代码或其概念。 - camickr

2
为什么不使用JDialog或JFrame来实现此目的?
   public void display2() {
      JDialog dialog = new JDialog(null, "Title", ModalityType.APPLICATION_MODAL);
      dialog.getContentPane().add(this);
      dialog.pack();
      dialog.setLocationRelativeTo(null);
      txt2.requestFocusInWindow();
      dialog.setVisible(true);
   }

0

您可以使用JDK-5018574 bug report中提出的解决方法。

而不是

txt2.requestFocus();

使用

txt2.addHierarchyListener(e -> {
    if(e.getComponent().isShowing() && (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0)
        SwingUtilities.invokeLater(e.getComponent()::requestFocusInWindow);
});

我修改了解决方案,使用了Java 8的特性。针对旧版本Java,请参见原始解决方法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接