java - 获取 JRadioButtons ButtonGroup 中的焦点以转到当前选定的项目而不是第一个

标签 java swing focus jradiobutton buttongroup

我在 ButtonGroup 中有一些 JRadioButtons。这些都在一个容器内,并且该组中还有其他项目。每当我按 Tab 键切换到按钮组时,焦点始终会转到该组中的第一项。但是,我更希望它转到所选的项目。

要重现该问题,请使用下面的代码(添加导入,暂时忽略我懒得将其全部放入 SwingUtilities.invokeLater 调用中的事实)。向下按 Tab 键找到单选按钮,然后使用向下箭头键找到后面的项目之一,例如蓝色。再按 Tab 4 次返回单选按钮,您会发现焦点位于顶部的“红色”单选按钮上。我希望焦点位于“蓝色”单选按钮上。

public static void main(String[] args)
{
    JFrame f = new JFrame("JRadioButton Test");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container parent = f.getContentPane();
    parent.setLayout(new GridBagLayout());

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.gridx = 1;
    gbc.gridy = 1;
    parent.add(new JLabel("Start"), gbc);
    gbc.gridx++;
    parent.add(new JTextField(10), gbc);

    gbc.gridx = 1;
    gbc.gridy++;
    parent.add(new JLabel("End"), gbc);
    gbc.gridx++;
    parent.add(new JTextField(10), gbc);

    gbc.gridx = 1;
    gbc.gridy++;
    parent.add(new JLabel("Colors"), gbc);

    gbc.gridx++;
    final Box buttons = Box.createVerticalBox();
    parent.add(buttons, gbc);
    final ButtonGroup bg = new ButtonGroup();
    for (String s : "Red,Orange,Yellow,Green,Blue,Indigo,Violet".split(","))
    {
        JRadioButton radioBtn = new JRadioButton(s);
        buttons.add(radioBtn);
        radioBtn.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e)
            {
                System.out.printf("Itemstate changed to %s\n",
                    e.getStateChange() == ItemEvent.SELECTED ? "SELECTED" : "DESELECTED");
            }
        });
        radioBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("JRadioButton action listener");
            }
        });
        bg.add(radioBtn);
    }

    gbc.gridx = 1;
    gbc.gridy += 2;
    gbc.gridwidth = 2;
    final JLabel currentValue = new JLabel("none");
    parent.add(currentValue, gbc);
    gbc.gridy--;
    JButton btn = new JButton("Show Button Group Value");
    btn.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            ButtonModel selection = bg.getSelection();
            for (int i = 0; i < buttons.getComponentCount(); i++)
            {
                JRadioButton radioBtn = (JRadioButton)buttons.getComponent(i);
                ButtonModel loopModel = radioBtn.getModel();
                if (loopModel == selection)
                {
                    currentValue.setText(radioBtn.getText());
                    return;
                }
                currentValue.setText("none");
            }
        }
    });
    parent.add(btn, gbc);

    f.pack();
    f.setVisible(true);
}

最佳答案

您也许可以使用FocusTraversalPolicy:

buttons.setFocusTraversalPolicyProvider(true);
buttons.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
  @Override public Component getDefaultComponent(Container focusCycleRoot) {
    ButtonModel selection = bg.getSelection();
    for (Component c: focusCycleRoot.getComponents()) {
      JRadioButton radioBtn = (JRadioButton) c;
      ButtonModel loopModel = radioBtn.getModel();
      if (loopModel == selection) {
        return radioBtn;
      }
    }
    return super.getDefaultComponent(focusCycleRoot);
  }
});
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ButtonGroupFocusTraversalTest {
  public JComponent makeUI() {
    JPanel parent = new JPanel(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.gridx = 1;
    gbc.gridy = 1;
    parent.add(new JLabel("Start"), gbc);
    gbc.gridx++;
    parent.add(new JTextField(10), gbc);

    gbc.gridx = 1;
    gbc.gridy++;
    parent.add(new JLabel("End"), gbc);
    gbc.gridx++;
    JTextField textField = new JTextField(10);
    parent.add(textField, gbc);

    gbc.gridx = 1;
    gbc.gridy++;
    parent.add(new JLabel("Colors"), gbc);

    gbc.gridx++;
    final Box buttons = Box.createVerticalBox();
    parent.add(buttons, gbc);
    final ButtonGroup bg = new ButtonGroup();
    for (String s : "Red,Orange,Yellow,Green,Blue,Indigo,Violet".split(",")) {
      JRadioButton radioBtn = new JRadioButton(s);
      buttons.add(radioBtn);
      bg.add(radioBtn);
    }

    gbc.gridx = 1;
    gbc.gridy += 2;
    gbc.gridwidth = 2;
    final JLabel currentValue = new JLabel("none");
    parent.add(currentValue, gbc);
    gbc.gridy--;
    JButton btn = new JButton("Show Button Group Value");
    parent.add(btn, gbc);

    buttons.setFocusTraversalPolicyProvider(true);
    buttons.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
      @Override public Component getDefaultComponent(Container focusCycleRoot) {
        ButtonModel selection = bg.getSelection();
        for (Component c: focusCycleRoot.getComponents()) {
          JRadioButton radioBtn = (JRadioButton) c;
          ButtonModel loopModel = radioBtn.getModel();
          if (loopModel == selection) {
            return radioBtn;
          }
        }
        return super.getDefaultComponent(focusCycleRoot);
      }
    });
    return parent;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new ButtonGroupFocusTraversalTest().makeUI());
      f.setSize(320, 320);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

关于java - 获取 JRadioButtons ButtonGroup 中的焦点以转到当前选定的项目而不是第一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34820018/

相关文章:

java Runtime.getRuntime().exec() 无法运行命令

java - Spring Boot jpa 中多对一映射中的子表中的外键未更新

java - 使用 Hibernate 复制记录

java - 为什么我的图像没有添加到我的 JButton 中?

android - 当 Activity 在 Android 中启动时,如何阻止 EditText 获得焦点?

java - 对使用 httpclient 的类进行单元测试

java - 切换焦点后模态对话框隐藏在主框架后面

java - 如何在 Swing 中的组件边框外添加边距?

jquery - 当表单字段处于事件状态时使 div 出现

c# - WPF MVVM 根据焦点项目执行不同的操作