自Java 1.7起的助记符行为(仍存在于1.8.0.121中) - java

我们有一个可以在Java 1.6上运行的旧版软件。当我们终于可以将其升级到Java 1.8时,出现了以下问题。

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

看起来像个错误,在这种情况下,我一直在考虑通过“使用” ALT版本来编写变通办法,但也许有人有更好的主意吗?不能使用其他外观,也不能在UI Manager中关闭标准的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)。

因此,如果我们保存最后按下的键的值,除非最后按下的键也是一个Alt,否则我们将消耗最后一个事件(keyReleased(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());
    }
}

Java Double与BigDecimal - java

我正在查看一些使用双精度变量来存储(360-359.9998779296875)结果为0.0001220703125的代码。 double变量将其存储为-1.220703125E-4。当我使用BigDecimal时,其存储为0.0001220703125。为什么将它双重存储为-1.220703125E-4? 参考方案 我不会在这里提及精度问题,而只会提及数字…

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

Java-父类正在从子类中调用方法? - java

抱歉,我还是编码的新手,可能还没有掌握所有术语。希望您仍然能理解我的问题。我想得到的输出是:"Cost for Parent is: 77.77" "Cost for Child is: 33.33" 但是,我得到这个:"Cost for Parent is: 33.33" "Cost f…

Java Map,如何将UTF-8字符串正确放置到地图? - java

我有一个地图,LinkedHashMap更确切地说。我想在上面放一个字符串对象。然后,我读取此值以查看实际存储的内容。字符串本身具有非ASCII字符(西里尔文,韩文等)。将其放到地图上然后阅读后,这些字符将替换为??? s。一些代码:Map obj = new LinkedHashMap(); System.out.println("name: &…

在小数点后三位显示秒。 -Java - java

我在Java程序中使用毫秒,并将其转换为秒。我的方法执行完此操作后,它将以长格式返回秒。System.out.println("[" + threadID + "]" + " " + "SeqSum res=" + grandTotal + " secs=" …