不可编辑的 JEditorPane 使用 Enter 键
Non-editable JEditorPane consumes Enter key
我有一个 JDialog
包含一个 JEditorPane
用于显示非用户可编辑的 HTML 内容,例如帮助和发行说明。
JDialog
有一个作为默认按钮安装的 "Close" 按钮。
如果 JEditorPane
离开 "focusable",则页面 Up/Down 键将滚动浏览文档,但按 "Enter" 不会触发默认按钮。
另一方面,如果 JEditorPane
设置为不可聚焦,则 Page Up/Down 键不起作用,但按 "Enter" 键会触发默认按钮,关闭对话框。
@SuppressWarnings("serial")
public class NoteViewer extends JFrame {
public static void main(String[] args) throws IOException {
final NoteViewer viewer = new NoteViewer(new URL("http://example.com/"));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
viewer.setVisible(true);
}
});
}
public NoteViewer(URL url) throws IOException {
super("Note Viewer");
setSize(900, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JEditorPane notes = new JEditorPane(url);
notes.setEditable(false);
// notes.setFocusable(false);
getContentPane().add(new JScrollPane(notes), BorderLayout.CENTER);
JButton close = new JButton("Close");
close.addActionListener(EventHandler.create(ActionListener.class, this, "dispose"));
Box box = Box.createHorizontalBox();
box.add(Box.createHorizontalGlue());
box.add(close);
getContentPane().add(box, BorderLayout.PAGE_END);
getRootPane().setDefaultButton(close);
}
}
取消注释 notes.setFocusable(false)
行以查看不同的行为。
我希望 JEditorPane 处理导航击键(例如 Page Up/Down),但忽略(不消耗)"editing" 击键,例如 Enter,这样根窗格将调用默认按钮。
经过大量的黑客攻击和单步执行后,我得到了我正在使用这段代码寻找的行为:
notes.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
"pressed");
但我担心它相当脆弱。所有平台都使用 VK_ENTER 来调用默认按钮吗?是否所有平台都使用 "pressed"
作为调用默认按钮的命令字符串?
最后,它以错误的方式进行处理:而不是 JEditorPane
忽略回车键并让处理发生在祖先中,这是 JEditorPane
明确处理回车键,我认为这是错误的。
不可编辑的 JEditorPane
不应捕获所有编辑击键(A-Z、0-9、Enter、Delete 等)并将它们转换为警告蜂鸣声,而应不处理它们,以便父组件有机会。这如何以通用的、非逐键输入映射方式实现?
Do all platforms use "pressed" as the command-string to invoke the default button?
事实并非如此。
您正在将 Enter 键映射到 JEditorPane 的 "pressed" 操作。但是,没有 "pressed" 操作,因此绑定被忽略,事件向上传递到使用默认按钮的 Enter 键绑定的根窗格。
通常"none"用来表示要ignore/remove绑定。查看 How to Remove Bindings 上的 Swing 教程部分了解更多信息。
所以我会说你的解决方案是正确的,应该适用于所有平台。
您可能想要查看 Key Bindings 的程序,该程序显示每个组件的所有键绑定。您会看到没有 "pressed" 操作。 JEditorPane 实际上使用 "insert-break" 映射到 Action.
A non-editable JEditorPane should not capture all the editing keystrokes (A-Z, 0-9, Enter, Delete, etc.) and transform them into a warning beep,
我对 a-z、0-9 没有 "beeping" 问题。我的删除键和退格键确实有问题。
我在 Windows 7.
上使用 JDK8_45
也许您可以使用 KeyEventDispatcher
来阻止密钥的发送。也许您检查了 KeyEvent 的来源,如果来源是编辑器窗格,您只让 Enter 键通过?可能还需要允许 PageUp/PageDown 事件,这样滚动才会起作用。
查看 Global Event Dispatching 了解更多信息。
我想我找到了一个更好的方法:将 JEditorPane
设置为不可编辑且不可聚焦,将 JScrollPane
设置为可聚焦。
JEditorPane notes = new JEditorPane(url);
notes.setEditable(false);
notes.setFocusable(false);
JScrollPane scroller = new JScrollPane(notes);
scroller.setFocusable(true);
getContentPane().add(scroller, BorderLayout.CENTER);
Enter 键转发到默认按钮。退格键、删除键和好友不会发出任何蜂鸣声。
编辑:
不允许选择和复制任何文本,因此可能不是最佳解决方案。
我有一个 JDialog
包含一个 JEditorPane
用于显示非用户可编辑的 HTML 内容,例如帮助和发行说明。
JDialog
有一个作为默认按钮安装的 "Close" 按钮。
如果 JEditorPane
离开 "focusable",则页面 Up/Down 键将滚动浏览文档,但按 "Enter" 不会触发默认按钮。
另一方面,如果 JEditorPane
设置为不可聚焦,则 Page Up/Down 键不起作用,但按 "Enter" 键会触发默认按钮,关闭对话框。
@SuppressWarnings("serial")
public class NoteViewer extends JFrame {
public static void main(String[] args) throws IOException {
final NoteViewer viewer = new NoteViewer(new URL("http://example.com/"));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
viewer.setVisible(true);
}
});
}
public NoteViewer(URL url) throws IOException {
super("Note Viewer");
setSize(900, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JEditorPane notes = new JEditorPane(url);
notes.setEditable(false);
// notes.setFocusable(false);
getContentPane().add(new JScrollPane(notes), BorderLayout.CENTER);
JButton close = new JButton("Close");
close.addActionListener(EventHandler.create(ActionListener.class, this, "dispose"));
Box box = Box.createHorizontalBox();
box.add(Box.createHorizontalGlue());
box.add(close);
getContentPane().add(box, BorderLayout.PAGE_END);
getRootPane().setDefaultButton(close);
}
}
取消注释 notes.setFocusable(false)
行以查看不同的行为。
我希望 JEditorPane 处理导航击键(例如 Page Up/Down),但忽略(不消耗)"editing" 击键,例如 Enter,这样根窗格将调用默认按钮。
经过大量的黑客攻击和单步执行后,我得到了我正在使用这段代码寻找的行为:
notes.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
"pressed");
但我担心它相当脆弱。所有平台都使用 VK_ENTER 来调用默认按钮吗?是否所有平台都使用 "pressed"
作为调用默认按钮的命令字符串?
最后,它以错误的方式进行处理:而不是 JEditorPane
忽略回车键并让处理发生在祖先中,这是 JEditorPane
明确处理回车键,我认为这是错误的。
不可编辑的 JEditorPane
不应捕获所有编辑击键(A-Z、0-9、Enter、Delete 等)并将它们转换为警告蜂鸣声,而应不处理它们,以便父组件有机会。这如何以通用的、非逐键输入映射方式实现?
Do all platforms use "pressed" as the command-string to invoke the default button?
事实并非如此。
您正在将 Enter 键映射到 JEditorPane 的 "pressed" 操作。但是,没有 "pressed" 操作,因此绑定被忽略,事件向上传递到使用默认按钮的 Enter 键绑定的根窗格。
通常"none"用来表示要ignore/remove绑定。查看 How to Remove Bindings 上的 Swing 教程部分了解更多信息。
所以我会说你的解决方案是正确的,应该适用于所有平台。
您可能想要查看 Key Bindings 的程序,该程序显示每个组件的所有键绑定。您会看到没有 "pressed" 操作。 JEditorPane 实际上使用 "insert-break" 映射到 Action.
A non-editable JEditorPane should not capture all the editing keystrokes (A-Z, 0-9, Enter, Delete, etc.) and transform them into a warning beep,
我对 a-z、0-9 没有 "beeping" 问题。我的删除键和退格键确实有问题。
我在 Windows 7.
上使用 JDK8_45也许您可以使用 KeyEventDispatcher
来阻止密钥的发送。也许您检查了 KeyEvent 的来源,如果来源是编辑器窗格,您只让 Enter 键通过?可能还需要允许 PageUp/PageDown 事件,这样滚动才会起作用。
查看 Global Event Dispatching 了解更多信息。
我想我找到了一个更好的方法:将 JEditorPane
设置为不可编辑且不可聚焦,将 JScrollPane
设置为可聚焦。
JEditorPane notes = new JEditorPane(url);
notes.setEditable(false);
notes.setFocusable(false);
JScrollPane scroller = new JScrollPane(notes);
scroller.setFocusable(true);
getContentPane().add(scroller, BorderLayout.CENTER);
Enter 键转发到默认按钮。退格键、删除键和好友不会发出任何蜂鸣声。
编辑: 不允许选择和复制任何文本,因此可能不是最佳解决方案。