Java 为JOptionPane对话框设置助记符和热键
是否可以为JOptionPane对话框中的按钮分配热键和助记符?我希望能够在JOptionPane生成的消息对话框中,选择Yes、No和Cancel,按Y键点击Yes按钮,按N键点击No按钮,按escape键激活escape按钮。类似地,在带有“确定”和“取消”按钮的对话框中,我希望能够使用enter和escape来激活它们 我已经尝试将JButtons传递到JOptionPane的按钮对象数组中,并且已经设置了助记符。助记符工作,按钮在对话框中正确显示,但是,当它们被激活时,它们不能正常工作。最明显的是,它们没有处理对话框Java 为JOptionPane对话框设置助记符和热键,java,jbutton,hotkeys,joptionpane,mnemonics,Java,Jbutton,Hotkeys,Joptionpane,Mnemonics,是否可以为JOptionPane对话框中的按钮分配热键和助记符?我希望能够在JOptionPane生成的消息对话框中,选择Yes、No和Cancel,按Y键点击Yes按钮,按N键点击No按钮,按escape键激活escape按钮。类似地,在带有“确定”和“取消”按钮的对话框中,我希望能够使用enter和escape来激活它们 我已经尝试将JButtons传递到JOptionPane的按钮对象数组中,并且已经设置了助记符。助记符工作,按钮在对话框中正确显示,但是,当它们被激活时,它们不能正常工作。
向JOptionPane对话框的按钮添加热键和助记符的正确方法是什么?您可以创建
JOptionPane
,然后循环浏览窗格的组件(子组件等),检查是否有组件是JButton的实例,如果是,请检查文本,并设置正确的助记符
JOptionPane p = new JOptionPane();
Component[] c = p.getComponents();
按如下方式使用UIManager:
UIManager.put("OptionPane.okButtonMnemonic", "79"); // for Setting 'O' as mnemonic
UIManager.put("OptionPane.cancelButtonMnemonic", "67"); // for Setting 'C' as mnemonic
将按钮作为参数而不是字符串发送进来
JButton button1 = new JButton( "<html>" + nextQuestion1 + "</html>");
button1.setMnemonic('a');
JButton button2 = new JButton(nextQuestion2 + "VUHU");
JButton button3 = new JButton(abort);
Object[] possibleValues = new Object[]{button1,button2,button3};
int selectedValue = showOptionDialog(owner, question, possibleValues);
JButton button1=新的JButton(“+nextQuestion1+”);
按钮1.设置助记符('a');
JButton button2=新JButton(nextQuestion2+“VUHU”);
JButton button3=新JButton(中止);
对象[]可能值=新对象[]{button1,button2,button3};
int selectedValue=showOptionDialog(所有者、问题、可能值);
您可以通过Swing Worker在父窗口中查找新窗口。然后检查它是否是JDialog并提取按钮区域。然后为按钮指定键。这适用于JOptionPane的静态方法
这是Swing Worker类-只需实例化它并在调用之前执行它即可显示JOptionPane:
import java.awt.Component;
import java.awt.Window;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.swing.FocusManager;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class HotKeyWorker extends SwingWorker<JComponent, Integer>
{
private static final long TIMEOUT = 30000; //Don't wait forever for the JOptionPane
private final String buttonAreaName;
private final Map<String, ButtonData> buttonDataMap;
private final Window owner;
public HotKeyWorker(Component owner, Map<String, ButtonData> buttonDataMap)
{
this.buttonDataMap = buttonDataMap;
if(owner instanceof Window)
this.owner = (Window)owner;
else if(owner != null)
this.owner = SwingUtilities.windowForComponent(owner);
else
this.owner = null;
buttonAreaName = getButtonAreaName();
}
@Override
public JComponent doInBackground()
{
if(owner == null) return null;
if(buttonAreaName == null) return null;
long timeout = System.currentTimeMillis() + TIMEOUT;
Window dialog = null;
while(dialog == null && System.currentTimeMillis() < timeout)
{
dialog = FocusManager.getCurrentManager().getFocusedWindow();
if(dialog != null)
if(dialog.getOwner() != owner)
dialog = null;
}
if(dialog instanceof JDialog)
return getButtonArea(((JDialog)dialog).getRootPane());
return null;
}
@Override
public void done()
{
try
{
JComponent buttonArea = get();
if(buttonArea != null)
for(Component c : buttonArea.getComponents())
if(c instanceof JButton)
setHotKey((JButton)c);
}
catch(InterruptedException | ExecutionException ex) { /* Failed */ }
}
private JComponent getButtonArea(JComponent component)
{
JComponent result = null;
if(component.getName() != null)
if(component.getName().equals(buttonAreaName) && component.getParent() instanceof JOptionPane)
return component;
for(Component c : component.getComponents())
if(c instanceof JComponent)
if((result = getButtonArea((JComponent)c)) != null)
return result;
return result;
}
private void setHotKey(JButton button)
{
if(button.getText().isEmpty()) return;
ButtonData data = buttonDataMap.get(button.getText());
if(data == null) return;
button.setText(data.updatedButtonText);
button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(data.hotKeyCode, 0), data.actionKey);
button.getActionMap().put(data.actionKey, new ButtonPress(button));
}
private String getButtonAreaName()
{
JButton trace = new JButton();
Object[] options = { trace };
JOptionPane temp = new JOptionPane();
temp.setOptions(options);
Component buttonArea = trace.getParent();
if(buttonArea != null)
return buttonArea.getName();
return null;
}
}
及
以下是您将如何使用它:
ButtonData yesData = new ButtonData("<html><span style=\"color:Blue;\">Y</span>es</html>", KeyEvent.VK_Y, "yes");
ButtonData noData = new ButtonData("<html><span style=\"color:Blue;\">N</span>o</html>", KeyEvent.VK_N, "no");
ButtonData cancelData = new ButtonData("<html><span style=\"color:Blue;\">C</span>ancel</html>", KeyEvent.VK_C, "cancel");
Map<String, ButtonData> map = new HashMap<>();
map.put("Yes", yesData);
map.put("No", noData);
map.put("Cancel", cancelData);
HotKeyWorker worker = new HotKeyWorker(component, map);
worker.execute();
int result = JOptionPane.showConfirmDialog(component, "Just a text", "Confirm", JOptionPane.YES_NO_CANCEL_OPTION);
以下是您将如何使用它们:
import javax.swing.JComponent;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.JLabel;
import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;
public class Test
{
public static void main(String[] args)
{
Frame frame = new Frame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static class Frame extends JFrame
{
public Frame()
{
init();
}
private void init()
{
setSize(300,100);
setTitle("Hot Key Test");
add(new Panel());
}
private class Panel extends JPanel
{
private final JButton testButton;
private final JLabel resultLabel;
public Panel()
{
String testKey = "test";
testButton = new JButton("<html><span style=\"color:Blue;\">T</span>est</html>");
testButton.addActionListener((event) -> { test(this); });
testButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0), testKey);
testButton.getActionMap().put(testKey, new ButtonPress(testButton));
resultLabel = new JLabel("No Result");
init();
}
private void init()
{
add(testButton);
add(resultLabel);
}
private void test(Component component)
{
HotKey yesOption = new HotKey("<html><span style=\"color:Blue;\">Y</span>es</html>", KeyEvent.VK_Y);
HotKey noOption = new HotKey("<html><span style=\"color:Blue;\">N</span>o</html>", KeyEvent.VK_N);
HotKey cancelOption = new HotKey("<html><span style=\"color:Blue;\">C</span>ancel</html>", KeyEvent.VK_C);
HotKey[] options = { yesOption, noOption, cancelOption };
int result = HotKeyOptionPane.showOptionDialog(component, "Just a test", "Testing", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, 0);
switch(result)
{
case 0 : resultLabel.setText("Yes Pressed"); break;
case 1 : resultLabel.setText("No Pressed"); break;
case 2 : resultLabel.setText("Cancel Pressed"); break;
default: resultLabel.setText("OptionPane Closed");
}
}
}
}
}
import javax.swing.JComponent;
导入java.awt.Component;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JOptionPane;
导入javax.swing.JLabel;
导入java.awt.event.KeyEvent;
导入javax.swing.KeyStroke;
公开课考试
{
公共静态void main(字符串[]args)
{
框架=新框架();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
私有静态类框架扩展了JFrame
{
公共框架()
{
init();
}
私有void init()
{
设置大小(300100);
setTitle(“热键测试”);
添加(新面板());
}
私有类面板扩展了JPanel
{
私有最终JButton测试按钮;
私人最终JLabel结果标签;
公共事务委员会()
{
字符串testKey=“test”;
testButton=新的JButton(“测试”);
addActionListener((事件)->{test(this);});
testButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_T,0),testKey);
getActionMap().put(testKey,newbuttonpress(testButton));
resultLabel=新的JLabel(“无结果”);
init();
}
私有void init()
{
添加(测试按钮);
添加(结果标签);
}
专用空隙试验(组件)
{
热键是选项=新热键(“是”,KeyEvent.VK_Y);
热键noOption=新热键(“否”,KeyEvent.VK\N);
热键取消选项=新热键(“取消”,KeyEvent.VK_C);
热键[]选项={yesOption,noOption,cancelOption};
int result=HotKeyOptionPane.showOptionDialog(组件,“只是一个测试”,“测试”,JOptionPane.DEFAULT\u选项,JOptionPane.QUESTION\u消息,null,选项,0);
开关(结果)
{
案例0:resultLabel.setText(“按Yes”);中断;
案例1:resultLabel.setText(“未按下”);中断;
案例2:resultLabel.setText(“按下取消”);中断;
默认值:resultLabel.setText(“OptionPane Closed”);
}
}
}
}
}
“就数学定律所指的现实而言,它们是不确定的;就它们所确定的而言,它们并不指现实。”
Albert Einstein这些是使用JOptionPane.showDialog()函数创建的对话框。它们返回一个整数值,据我所知,无法访问它们的实例。遗留代码。听起来您需要重写JOptionPane类,然后添加助记符。或者创建JOptionPane组件,自己将其放入一个对话框中,然后您可以包装这些组件,或者更好的是,只需创建您自己的对话框或选项对话框来满足您的需要,听起来这可能是您最好的选择,让您完全控制对话框。一旦你创建了一次对话框,你就可以在任何你需要的地方使用它。是的,问题是试图使用遗留代码将助记符强制输入到JOptionPane中,而无需进行很多重构。我做的研究越多,它看起来就越不可能。唯一的方法似乎是选择A)制作自己的JDialog或选择B)扩展JOptionPane。这两种方法都不适用于这种情况。另请参见:
ButtonData yesData = new ButtonData("<html><span style=\"color:Blue;\">Y</span>es</html>", KeyEvent.VK_Y, "yes");
ButtonData noData = new ButtonData("<html><span style=\"color:Blue;\">N</span>o</html>", KeyEvent.VK_N, "no");
ButtonData cancelData = new ButtonData("<html><span style=\"color:Blue;\">C</span>ancel</html>", KeyEvent.VK_C, "cancel");
Map<String, ButtonData> map = new HashMap<>();
map.put("Yes", yesData);
map.put("No", noData);
map.put("Cancel", cancelData);
HotKeyWorker worker = new HotKeyWorker(component, map);
worker.execute();
int result = JOptionPane.showConfirmDialog(component, "Just a text", "Confirm", JOptionPane.YES_NO_CANCEL_OPTION);
import javax.swing.JComponent;
import java.awt.Window;
import javax.swing.FocusManager;
import javax.swing.JDialog;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.JLabel;
import javax.swing.AbstractAction;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
public class Test
{
public static void main(String[] args)
{
Frame frame = new Frame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static class Frame extends JFrame
{
public Frame()
{
init();
}
private void init()
{
setSize(300,100);
setTitle("Hot Key Test");
add(new Panel());
}
private class Panel extends JPanel
{
private final JButton testButton;
private final JLabel resultLabel;
public Panel()
{
String testKey = "test";
testButton = new JButton("<html><span style=\"color:Blue;\">T</span>est</html>");
testButton.addActionListener((event) -> { test(this); });
testButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0), testKey);
testButton.getActionMap().put(testKey, new ButtonPress(testButton));
resultLabel = new JLabel("No Result");
init();
}
private void init()
{
add(testButton);
add(resultLabel);
}
private void test(Component component)
{
String anotherTestKey = "Test";
JButton anotherTestButton = new JButton("<html><span style=\"color:Blue;\">T</span>est</html>");
anotherTestButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0), anotherTestKey);
anotherTestButton.getActionMap().put(anotherTestKey, new ButtonPress(anotherTestButton));
JLabel anotherTestLabel = new JLabel("No Result has been selected");
JPanel testPanel = new JPanel();
testPanel.add(anotherTestButton);
testPanel.add(anotherTestLabel);
anotherTestButton.addActionListener((event) -> { anotherTest(testPanel, anotherTestLabel); });
ButtonData yesData = new ButtonData("<html><span style=\"color:Blue;\">Y</span>es</html>", KeyEvent.VK_Y, "yes");
ButtonData noData = new ButtonData("<html><span style=\"color:Blue;\">N</span>o</html>", KeyEvent.VK_N, "no");
ButtonData cancelData = new ButtonData("<html><span style=\"color:Blue;\">C</span>ancel</html>", KeyEvent.VK_C, "cancel");
Map<String, ButtonData> map = new HashMap<>();
map.put("Yes", yesData);
map.put("No", noData);
map.put("Cancel", cancelData);
HotKeyWorker worker = new HotKeyWorker(component, map);
worker.execute();
int result = JOptionPane.showConfirmDialog(component, testPanel, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION);
switch(result)
{
case 0 : resultLabel.setText("Yes Pressed"); break;
case 1 : resultLabel.setText("No Pressed"); break;
case 2 : resultLabel.setText("Cancel Pressed"); break;
default: resultLabel.setText("OptionPane Closed");
}
}
public void anotherTest(Component component, JLabel label)
{
ButtonData fredData = new ButtonData("<html><span style=\"color:Blue;\">F</span>red</html>", KeyEvent.VK_F, "fred");
ButtonData wilmaData = new ButtonData("<html><span style=\"color:Blue;\">W</span>ilma</html>", KeyEvent.VK_W, "wilma");
ButtonData barneyData = new ButtonData("<html>B<span style=\"color:Blue;\">a</span>rney</html>", KeyEvent.VK_A, "barney");
ButtonData bettyData = new ButtonData("<html>B<span style=\"color:Blue;\">e</span>tty</html>", KeyEvent.VK_E, "betty");
Map<String, ButtonData> map = new HashMap<>();
map.put("Fred", fredData);
map.put("Wilma", wilmaData);
map.put("Barney", barneyData);
map.put("Betty", bettyData);
HotKeyWorker worker = new HotKeyWorker(component, map);
worker.execute();
String[] options = {"Fred", "Wilma", "Barney", "Betty" };
int result = JOptionPane.showOptionDialog(component, "Who do you like?", "Confirm", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, 0);
switch(result)
{
case 0 : label.setText("I like Fred"); break;
case 1 : label.setText("I like Wilma"); break;
case 2 : label.setText("I like Barney"); break;
case 3 : label.setText("I like Betty"); break;
default: label.setText("I decline to answer");
}
}
private class HotKeyWorker extends SwingWorker<JComponent, Integer>
{
private static final long TIMEOUT = 30000; //Don't wait forever for the JOptionPane
private final String buttonAreaName;
private final Map<String, ButtonData> buttonDataMap;
private final Window owner;
public HotKeyWorker(Component owner, Map<String, ButtonData> buttonDataMap)
{
this.buttonDataMap = buttonDataMap;
if(owner instanceof Window)
this.owner = (Window)owner;
else if(owner != null)
this.owner = SwingUtilities.windowForComponent(owner);
else
this.owner = null;
buttonAreaName = getButtonAreaName();
}
@Override
public JComponent doInBackground()
{
if(owner == null) return null;
if(buttonAreaName == null) return null;
long timeout = System.currentTimeMillis() + TIMEOUT;
Window dialog = null;
while(dialog == null && System.currentTimeMillis() < timeout)
{
dialog = FocusManager.getCurrentManager().getFocusedWindow();
if(dialog != null)
if(dialog.getOwner() != owner)
dialog = null;
}
if(dialog instanceof JDialog)
return getButtonArea(((JDialog)dialog).getRootPane());
return null;
}
@Override
public void done()
{
try
{
JComponent buttonArea = get();
if(buttonArea != null)
for(Component c : buttonArea.getComponents())
if(c instanceof JButton)
setHotKey((JButton)c);
}
catch(InterruptedException | ExecutionException ex) { /* Failed */ }
}
private JComponent getButtonArea(JComponent component)
{
JComponent result = null;
if(component.getName() != null)
if(component.getName().equals(buttonAreaName) && component.getParent() instanceof JOptionPane)
return component;
for(Component c : component.getComponents())
if(c instanceof JComponent)
if((result = getButtonArea((JComponent)c)) != null)
return result;
return result;
}
private void setHotKey(JButton button)
{
if(button.getText().isEmpty()) return;
ButtonData data = buttonDataMap.get(button.getText());
if(data == null) return;
button.setText(data.updatedButtonText);
button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(data.hotKeyCode, 0), data.actionKey);
button.getActionMap().put(data.actionKey, new ButtonPress(button));
}
private String getButtonAreaName()
{
JButton trace = new JButton();
Object[] options = { trace };
JOptionPane temp = new JOptionPane();
temp.setOptions(options);
Component buttonArea = trace.getParent();
if(buttonArea != null)
return buttonArea.getName();
return null;
}
}
private class ButtonData
{
public String updatedButtonText;
public int hotKeyCode;
public String actionKey;
public ButtonData(String updatedButtonText, int hotKeyCode, String actionKey)
{
this.updatedButtonText = updatedButtonText;
this.hotKeyCode = hotKeyCode;
this.actionKey = actionKey;
}
}
private class ButtonPress extends AbstractAction
{
private final JButton button;
public ButtonPress(JButton button) { this.button = button; }
@Override
public void actionPerformed(ActionEvent event) { button.doClick(); }
}
}
}
}
import java.awt.Component;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.JDialog;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.AbstractAction;
import javax.swing.Action;
import java.awt.event.ActionEvent;
public class HotKeyOptionPane
{
public static int showOptionDialog(Component parentComponent,
Object message, String title,
int optionType, int messageType,
Icon icon, HotKey[] options,
Object initialValue)
{
JButton[] buttons = new JButton[options.length];
for(int i = 0; i < options.length; i++)
buttons[i] = new JButton(options[i].text);
JOptionPane pane = new JOptionPane(message, messageType, optionType, icon, buttons, initialValue);
for(int option = 0; option < buttons.length; option++)
setButtonAction(buttons[option], options[option].keyCode, option, pane);
JDialog dialog = pane.createDialog(parentComponent, title);
dialog.setVisible(true);
if (pane.getValue() instanceof Integer)
return (Integer)pane.getValue();
return -1;
}
private static void setButtonAction(JButton button, int hotKey, Integer option, JOptionPane pane)
{
Action action = new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent event)
{
pane.setValue(option);
pane.firePropertyChange(JOptionPane.VALUE_PROPERTY, JOptionPane.DEFAULT_OPTION, option);
}
};
button.addActionListener(action);
button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(hotKey, 0), button.getText());
button.getActionMap().put(button.getText(), action);
}
}
public class HotKey
{
public String text;
public int keyCode;
public HotKey(String text, int keyCode)
{
this.text = text;
this.keyCode = keyCode;
}
}
import javax.swing.JComponent;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.JLabel;
import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;
public class Test
{
public static void main(String[] args)
{
Frame frame = new Frame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static class Frame extends JFrame
{
public Frame()
{
init();
}
private void init()
{
setSize(300,100);
setTitle("Hot Key Test");
add(new Panel());
}
private class Panel extends JPanel
{
private final JButton testButton;
private final JLabel resultLabel;
public Panel()
{
String testKey = "test";
testButton = new JButton("<html><span style=\"color:Blue;\">T</span>est</html>");
testButton.addActionListener((event) -> { test(this); });
testButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0), testKey);
testButton.getActionMap().put(testKey, new ButtonPress(testButton));
resultLabel = new JLabel("No Result");
init();
}
private void init()
{
add(testButton);
add(resultLabel);
}
private void test(Component component)
{
HotKey yesOption = new HotKey("<html><span style=\"color:Blue;\">Y</span>es</html>", KeyEvent.VK_Y);
HotKey noOption = new HotKey("<html><span style=\"color:Blue;\">N</span>o</html>", KeyEvent.VK_N);
HotKey cancelOption = new HotKey("<html><span style=\"color:Blue;\">C</span>ancel</html>", KeyEvent.VK_C);
HotKey[] options = { yesOption, noOption, cancelOption };
int result = HotKeyOptionPane.showOptionDialog(component, "Just a test", "Testing", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, 0);
switch(result)
{
case 0 : resultLabel.setText("Yes Pressed"); break;
case 1 : resultLabel.setText("No Pressed"); break;
case 2 : resultLabel.setText("Cancel Pressed"); break;
default: resultLabel.setText("OptionPane Closed");
}
}
}
}
}