簡體   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