繁体   English   中英

自Java 1.7以来的助记符行为(仍然存在于1.8.0.121中)

[英]Mnemonic behavior since Java 1.7 (still present in 1.8.0.121)

我们有一个在Java 1.6上运行的遗留软件。 当我们最终获得绿灯将其升级到Java 1.8时,出现以下问题。

我们有一组带加速键的单选按钮。 如果任何类型的JTextComponent具有焦点,并且您点击其中一个单选按钮加速器(例如,ALT-s),并且在释放ALT之前释放“s”,则UIManager将激活菜单栏。 (这只发生在Windows的外观和感觉上)

看起来像一个错误,我一直在考虑通过在这些情况下“消费”ALT版本来编写解决方法,但也许有人有更好的想法? 使用不同的外观不是一种选择,也不是在UI管理器中关闭标准的Alt行为。

这是一个简短的代码示例。 请注意,没有任何类型的加速器/助记符冲突。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.UIManager;

public class MnemonicTest extends JFrame {  

public MnemonicTest() {
    super("MnemonicTest");
    init();
}

public static void main(String[] args) throws Exception {
    MnemonicTest test = new MnemonicTest();
    test.setVisible(true);
}

private void init() {
    try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e1) {
        e1.printStackTrace();
    }

    setSize(new Dimension(500,400));
    JButton stopButton = new JButton("Stop");
    stopButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {        
            System.exit(0);         
        }});

    this.getContentPane().setLayout(new BorderLayout());

    this.getContentPane().add(stopButton, BorderLayout.SOUTH);

    JMenuBar jMenuBar = new JMenuBar(); 
    JMenu menu = new JMenu("XXX");  

    JMenuItem a1 = new JMenuItem("a1", 'A');
    JMenuItem b1 = new JMenuItem("b1", 'B');
    JMenuItem c1 = new JMenuItem("c1", 'C');

    menu.add(a1);
    menu.add(b1);
    menu.add(c1);

    jMenuBar.add(menu);
    this.setJMenuBar(jMenuBar);

    JPanel p = new JPanel();
    ButtonGroup group = new ButtonGroup();
    p.add(new JTextField("XXXXXXXXXX"), BorderLayout.CENTER);
    JRadioButton but1 = new JRadioButton("test");
    but1.setMnemonic('s');
    JRadioButton but2 = new JRadioButton("2222");
    p.add(but1);
    p.add(but2);
    group.add(but1);
    group.add(but2);

    getContentPane().add(p, BorderLayout.CENTER);
}
}

我确实找到了一个有效的解决方案,即使它不是一个美容大赛冠军。 如果你有一个更好的,请发布!!

问题似乎是KeyEvent被发送到单选按钮而不是窗格或文本字段。 当系统发现ALT键已被释放时,它会调用默认操作。

当然,当单选按钮具有焦点时,普通的香草色Alt应该仍然​​可以执行它应该执行的操作:激活菜单栏。

如果你按下Alt-S(我们的加速器),单选按钮将收到:keyPressed(Alt) - > keyPressed(“S”) - > keyReleased(“S”) - > keyReleased(Alt)。

因此,如果我们保存按下的最后一个键的值,我们将消耗最后一个事件(keyReleased(Alt)),除非按下的最后一个键也是Alt。

这是一种解决方法,而不是一个漂亮的解决方案,但它确实有效。 代码如下(我在代码中留下了我的调试语句):

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.UIManager;

public class MnemonicTest extends JFrame {  
    int codeLast = 0;

    private final class RadioButtonKeyAdapter extends KeyAdapter {
        private static final int NO_CODE = 0;
        private int lastCode = 0;

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("pressed source: " + e.getSource() + "\n" + e.getKeyCode());
            this.setLastCode(e.getKeyCode());
        }

        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("released source: " + e.getSource() + "\n" + e.getKeyCode());
            if (e.getKeyCode() == KeyEvent.VK_ALT && this.getLastCode() != e.getKeyCode()) {
                e.consume();
            }

            this.setLastCode(NO_CODE);
        }

        private int getLastCode() {
            return lastCode;
        }

        private void setLastCode(int lastCode) {
            this.lastCode = lastCode;
        }
    }

    private static final long serialVersionUID = 1L;

    public MnemonicTest() {
        super("MnemonicTest");
        init();
    }

    public static void main(String[] args) throws Exception {
        MnemonicTest test = new MnemonicTest();
        test.setVisible(true);
    }

    private void init() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        setSize(new Dimension(500,400));
        JButton stopButton = new JButton("Stop");
        stopButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {        
                System.exit(0);         
            }});

        this.getContentPane().setLayout(new BorderLayout());

        this.getContentPane().add(stopButton, BorderLayout.SOUTH);

        JMenuBar jMenuBar = new JMenuBar(); 
        JMenu menu = new JMenu("XXX");  

        JMenuItem a1 = new JMenuItem("a1", 'A');
        JMenuItem b1 = new JMenuItem("b1", 'B');
        JMenuItem c1 = new JMenuItem("c1", 'C');

        menu.add(a1);
        menu.add(b1);
        menu.add(c1);

        jMenuBar.add(menu);
        this.setJMenuBar(jMenuBar);

        JPanel p = new JPanel();
        ButtonGroup group = new ButtonGroup();
        JTextField textField = new JTextField("XXXXXXXXXX");
        p.add(textField, BorderLayout.CENTER);
        JRadioButton but1 = new JRadioButton("test");
        but1.setMnemonic('s');
        JRadioButton but2 = new JRadioButton("2222");
        p.add(but1);
        p.add(but2);
        group.add(but1);
        group.add(but2);

        getContentPane().add(p, BorderLayout.CENTER);

        but1.addKeyListener(new RadioButtonKeyAdapter());
        but2.addKeyListener(new RadioButtonKeyAdapter());
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM