Java 如何通过将方法传递给showMessageDialog,使JRadioButton在弹出式窗体中具有焦点?

Java 如何通过将方法传递给showMessageDialog,使JRadioButton在弹出式窗体中具有焦点?,java,swing,focus,traversal,Java,Swing,Focus,Traversal,编辑--提供必需的类 编辑#2——必需的类来自,因此不需要调试,尽管我确实将Vector更改为ArrayList 我使用showMessageDialog并将方法(popup)传递给对象消息参数,创建了这个弹出(模式)表单。我添加了遍历策略,该策略扩展为允许光标键移动焦点,除了以下情况外,效果非常好 我唯一不能解决的问题是如何使光标键立即工作。“确定”按钮最初具有焦点,唯一移动焦点的键是选项卡。一旦JRadioButton具有焦点,光标键就可以很好地移动焦点 // LOSE THIS!! im

编辑--提供必需的类

编辑#2——必需的类来自,因此不需要调试,尽管我确实将
Vector
更改为
ArrayList

我使用
showMessageDialog
并将方法(
popup
)传递给
对象消息
参数,创建了这个弹出(模式)表单。我添加了遍历策略,该策略扩展为允许光标键移动焦点,除了以下情况外,效果非常好

我唯一不能解决的问题是如何使光标键立即工作。“确定”按钮最初具有焦点,唯一移动焦点的键是
选项卡
。一旦
JRadioButton
具有焦点,光标键就可以很好地移动焦点

// LOSE THIS!! import Main.MyFocusTraversalPolicy;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.*;
import static java.awt.event.KeyEvent.*;
import java.util.HashSet;
import java.util.Set;
import javax.swing.*;

public class NewMain {
  static JPanel pnlPopup;
  static MyFocusTraversalPolicy ftPolicy;
  static JRadioButton rbtAsShown    = new JRadioButton();
  static JRadioButton rbtRandomly   = new JRadioButton();
  static JRadioButton rbtUser       = new JRadioButton();
  static JLabel lblAvailableDefinitionMethod = new JLabel();

  private static int popup() {
    pnlPopup = new JPanel(new GridLayout(4, 1));
    ButtonGroup buttonGroup1  = new ButtonGroup();
    buttonGroup1.add(rbtAsShown);
    rbtAsShown.setSelected(false);
    rbtRandomly.setSelected(true);
    rbtUser.setSelected(false);
    rbtAsShown.setText("As already shown above");

    rbtAsShown.addFocusListener(new FocusAdapter(){
      public void focusGained(FocusEvent e){
        rbtAsShown.setSelected(true);
      }});

    rbtRandomly.addFocusListener(new FocusAdapter(){
      public void focusGained(FocusEvent e){
        rbtRandomly.setSelected(true);
      }});

    rbtUser.addFocusListener(new FocusAdapter(){
      public void focusGained(FocusEvent e){
        rbtUser.setSelected(true);
      }});

    rbtAsShown.addItemListener(new ItemListener(){
      public void itemStateChanged(ItemEvent evt){
        rbtRandomly.setSelected(false);
        rbtUser.setSelected(false);
      }});

    buttonGroup1.add(rbtRandomly);
    rbtRandomly.setText("Randomly");

    rbtRandomly.addItemListener(new ItemListener(){
      public void itemStateChanged(ItemEvent evt){
        rbtAsShown.setSelected(false);
        rbtUser.setSelected(false);
      }});

    buttonGroup1.add(rbtUser);
    rbtUser.setText("I'll type them");
    rbtUser.addItemListener(new java.awt.event.ItemListener(){
      public void itemStateChanged(java.awt.event.ItemEvent evt){
        rbtRandomly.setSelected(false);
        rbtAsShown.setSelected(false);
      }});

    lblAvailableDefinitionMethod.setText("How should 'Available letters' be defined?");
    rbtUser.setMnemonic(VK_I);
    rbtRandomly.setMnemonic(VK_R);
    rbtAsShown.setMnemonic(VK_A);
    pnlPopup.add(lblAvailableDefinitionMethod);
    pnlPopup.add(rbtRandomly);
    pnlPopup.add(rbtUser);
    pnlPopup.add(rbtAsShown);

    Set downKeys;
    downKeys = pnlPopup.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
    Set newDownKeys = new HashSet(downKeys);
    newDownKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0));
    pnlPopup.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newDownKeys);    

    Set upKeys;
    upKeys = pnlPopup.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
    Set newUpKeys = new HashSet(upKeys);
    newUpKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0));
    pnlPopup.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, newUpKeys);    

    pnlPopup.setFocusTraversalPolicy(ftPolicy);
    rbtRandomly.requestFocusInWindow();
    pnlPopup.setFocusCycleRoot(true);

    return JOptionPane.showConfirmDialog(null, 
                                         pnlPopup, 
                                         "Define Available letters", 
                                         JOptionPane.OK_CANCEL_OPTION, 
                                         JOptionPane.PLAIN_MESSAGE);
  }

  public static void main(String[] args){
    if(popup() == -1) JOptionPane.showMessageDialog(null,"Cancelled");
    else              JOptionPane.showMessageDialog(null,"OK");
  }
}
这里是class
MyFocusTraversalPolicy
。对不起,我忘了

import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.util.ArrayList;

    public class MyFocusTraversalPolicy extends FocusTraversalPolicy
    {
        ArrayList<Component> order;  // class var 

        public MyFocusTraversalPolicy(ArrayList<Component> o) {
            this.order = new ArrayList<>            (o.size());
            this.order.addAll                       (o);
        }
        public Component getComponentAfter(Container focusCycleRoot,
                                           Component aComponent)
        {
            int idx = (order.indexOf(aComponent) + 1) % order.size();
            return order.get(idx);
        }

        public Component getComponentBefore(Container focusCycleRoot,
                                            Component aComponent)
        {
            int idx = order.indexOf(aComponent) - 1;
            if (idx < 0) {
                idx = order.size() - 1;
            }
            return order.get(idx);
        }

        public Component getDefaultComponent(Container focusCycleRoot) {
            return order.get(0);
        }

        public Component getLastComponent(Container focusCycleRoot) {
            return order.get(order.size());
        }

        public Component getFirstComponent(Container focusCycleRoot) {
            return order.get(0);
        }
    }
导入java.awt.Component;
导入java.awt.Container;
导入java.awt.FocusTraversalPolicy;
导入java.util.ArrayList;
公共类MyFocusTraversalPolicy扩展了FocusTraversalPolicy
{
ArrayList顺序;//类变量
公共MyFocusTraversalPolicy(ArrayList o){
this.order=newarraylist(o.size());
此.order.addAll(o);
}
公共组件getComponentAfter(容器焦点),
组件(组件)
{
intidx=(order.indexOf(aComponent)+1)%order.size();
退货订单.get(idx);
}
公共组件getComponentBefore(容器焦点),
组件(组件)
{
int idx=订单indexOf(组件)-1;
if(idx<0){
idx=order.size()-1;
}
退货订单.get(idx);
}
公共组件getDefaultComponent(容器focusCycleRoot){
退货订单。获取(0);
}
公共组件getLastComponent(容器焦点Cycleroot){
returnorder.get(order.size());
}
公共组件getFirstComponent(容器焦点Cycleroot){
退货订单。获取(0);
}
}
我假设
rbtRandomly.requestFocusInWindow()showOptionDialog
的工作方式,code>不会将焦点转移到按钮
rbtRandomly

我可以做些什么,以便在窗体弹出时,光标键可以在按钮之间移动光标

附言。 我使用弹出式表单是因为我需要
OK
Cancel
按钮来确认用户选择或希望不继续。我想要一个带有按钮的弹出式表单,因为否则UI看起来和感觉都很粗糙


当@Aqua用一个链接发表评论时,我几乎已经解决了我的问题。按照“我的方式”做这件事需要比实际工作多得多的工作,所以我打算跟随链接。以下是产生此窗口的原因,光标键在3个按钮之间移动焦点,并增加了
Esc
Enter
执行
Cancel
OK
操作。它还基于@hovercraftfullofels提供的答案,该答案建议使用
JDialog
而不是
JOptionPane.showMessageDialog

  static JDialog dialog = null;
  static boolean retval ;
  static MyFocusTraversalPolicy ftPolicy;
  static JRadioButton rbtAsShown    = new JRadioButton();
  static JRadioButton rbtRandomly   = new JRadioButton();
  static JRadioButton rbtUser       = new JRadioButton();

  private static boolean popup() {
    JLabel lblAvailableDefinitionMethod = new JLabel();
    KeyBoundButton btnOK;
    JPanel pnlPopup;
    ButtonGroup buttonGroup1  = new ButtonGroup();
    buttonGroup1.add(rbtAsShown);
    rbtAsShown.setSelected(false);
    rbtRandomly.setSelected(false);
    rbtUser.setSelected(false);
    rbtAsShown.setText("As already shown above");

    rbtAsShown.addFocusListener(new FocusAdapter(){
      public void focusGained(FocusEvent e){
        rbtAsShown.setSelected(true);
      }});

    rbtRandomly.addFocusListener(new FocusAdapter(){
      public void focusGained(FocusEvent e){
        rbtRandomly.setSelected(true);
      }});

    rbtUser.addFocusListener(new FocusAdapter(){
      public void focusGained(FocusEvent e){
        rbtUser.setSelected(true);
      }});

    rbtAsShown.addItemListener(new ItemListener(){
      public void itemStateChanged(ItemEvent evt){
        rbtRandomly.setSelected(false);
        rbtUser.setSelected(false);
      }});

    buttonGroup1.add(rbtRandomly);
    rbtRandomly.setText("Randomly");

    rbtRandomly.addItemListener(new ItemListener(){
      public void itemStateChanged(ItemEvent evt){
        rbtAsShown.setSelected(false);
        rbtUser.setSelected(false);
      }});

    buttonGroup1.add(rbtUser);
    rbtUser.setText("I'll type them");
    rbtUser.addItemListener(new java.awt.event.ItemListener(){
      public void itemStateChanged(java.awt.event.ItemEvent evt){
        rbtRandomly.setSelected(false);
        rbtAsShown.setSelected(false);
      }});

    lblAvailableDefinitionMethod.setText("How should 'Available letters' be defined?");
    rbtUser.setMnemonic(VK_I);
    rbtRandomly.setMnemonic(VK_R);
    rbtAsShown.setMnemonic(VK_A);

    btnOK = new KeyBoundButton("OK", VK_ENTER, 0){
      @Override public void action(ActionEvent e){
        retval = true;
        dialog.dispose();
      }};

    KeyBoundButton btnCancel = new KeyBoundButton("Cancel", VK_ESCAPE, 0){
      @Override public void action(ActionEvent e){
        retval = false;
        dialog.dispose();
      }};

    pnlPopup = new JPanel(new GridBagLayout());
    pnlPopup.add(lblAvailableDefinitionMethod, new GBConstraints(0,0));
    pnlPopup.add(rbtRandomly, new GBConstraints(0,1));
    pnlPopup.add(rbtUser,     new GBConstraints(0,2));
    pnlPopup.add(rbtAsShown,  new GBConstraints(0,3));
    pnlPopup.add(btnOK,       new GBConstraints(0,4).anchor(WEST));
    pnlPopup.add(btnCancel,   new GBConstraints(0,4).anchor(EAST));

    Set downKeys; 
    downKeys = pnlPopup.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
    Set newDownKeys = new HashSet(downKeys);
    newDownKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0));
    pnlPopup.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newDownKeys);    

    Set upKeys;
    upKeys = pnlPopup.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
    Set newUpKeys = new HashSet(upKeys);
    newUpKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0));
    pnlPopup.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, newUpKeys);    

    ArrayList<Component> order1 = new ArrayList<>(3);
      order1.add(rbtRandomly);
      order1.add(rbtUser);
      order1.add(rbtAsShown);
    ftPolicy = new MyFocusTraversalPolicy(order1);    
    pnlPopup.setFocusTraversalPolicy(ftPolicy);
    pnlPopup.setFocusCycleRoot(true);
    dialog = new JDialog(null, "Dialog Title", Dialog.ModalityType.APPLICATION_MODAL);
    dialog.getContentPane().add(pnlPopup);
    dialog.pack();
    dialog.setLocationRelativeTo(null);
    dialog.setVisible(true);    
    return retval && (rbtAsShown.isSelected() || rbtUser.isSelected() || rbtRandomly.isSelected());
  }

  public static void main(String[] args){
    if(popup()){
      if(rbtAsShown.isSelected()) JOptionPane.showMessageDialog(null,"As shown");
      if(rbtRandomly.isSelected())JOptionPane.showMessageDialog(null,"Random");
      if(rbtUser.isSelected())    JOptionPane.showMessageDialog(null,"User");
    }
    else
      JOptionPane.showMessageDialog(null,"Cancelled");
  }


由于camickr,有一个优雅的解决方案

修改原始代码所需的全部内容是:

(a) 从中获取类
RequestFocusListener

(b) 添加一行代码:
rbtRandomly.addAncestorListener(newrequestfocuslistener())


camickr在上面链接中的解释非常好。

一个解决方案是使用
AncestorListener
。有关示例,请参见@camickr@Aqua--谢谢。如果我只是直接跳到你的链接上,我很快就完成了。
import java.awt.event.ActionEvent;
import javax.swing.*;
import static javax.swing.KeyStroke.getKeyStroke;

public abstract class KeyBoundButton extends JButton{

  public abstract void action(ActionEvent e);

  public KeyBoundButton(String buttonText, char acc, int key, int mask){
    Action myAction = new AbstractAction()
    {
      @Override public void actionPerformed(ActionEvent e)
      {
        action(e);
      }
    };  

    setAction(myAction);
    setText(buttonText);
    setMnemonic(acc);
    getInputMap(WHEN_IN_FOCUSED_WINDOW)
                  .put(getKeyStroke(key, mask),buttonText);
    getActionMap().put(                        buttonText, myAction);

  }

  public KeyBoundButton(String buttonText, int key, int mask)
  {
    this(buttonText, buttonText.charAt(0), key, mask );
  }
}