JApplet & KeyListener
Posted
技术标签:
【中文标题】JApplet & KeyListener【英文标题】: 【发布时间】:2012-11-02 00:39:29 【问题描述】:我正在为我的计算机科学课程开发一个应用程序。任务是编写一个计算器,但不使用JTextField
s 或JTextArea
s。我想出了一个实现KeyListener
的想法,它在appletviewer 和JFrame
中都很好用,但在Google Chrome 中根本不起作用(可能还有其他浏览器)。
这是我的代码 sn-ps。
//- BinaryCalc.java
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class BinaryCalc extends JApplet implements KeyListener
private JPanel panel;
public BinaryCalc()
super();
panel = new JPanel();
this.add(panel);
panel.addKeyListener(this);
panel.requestFocusInWindow();
@Override
public void init()
JOptionPane.showMessageDialog(this, "applet");
panel.setFocusable(true);
panel.requestFocus();
public void keyPressed(KeyEvent e)
JOptionPane.showMessageDialog(this, (char) e.getKeyCode());
public void keyReleased(KeyEvent e)
public void keyTyped(KeyEvent e)
public JPanel getPanel() return panel;
public static void main(String args[])
JFrame frame = new JFrame("Binary Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(320, 240));
BinaryCalc kalkulator = new BinaryCalc();
frame.add(kalkulator);
frame.pack();
frame.setVisible(true);
kalkulator.getPanel().requestFocusInWindow();
还有包含我的小程序的 html 文件。
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Kalkulator binarny</title>
</head>
<body>
<div style="text-align: center; border-bottom: 1px solid black">
<h1>Kalkulator Binarny</h1>
</div>
<br/>
<object style="display: block; margin: auto;" type="application/x-java-applet" >
<param name="code" value="BinaryCalc.class" />
<!--- <param name="archive" value="Liczba.jar" /> -->
What a terrible failure: applet failed to load!
</object>
<br/>
</body>
</html>
有什么想法吗?
【问题讨论】:
@DavidKroukamp 只是“应该”还是“必须”?顺便说一句,我的 sn-ps 是 SSCCE :) 必须!KeyListener
很旧,并且在焦点等方面存在问题。我建议仅在您期望键盘上的任何键发生事件时才使用 KeyListener
,甚至始终确保您要求关注 keylistener 所在的组件附上以避免更多问题
@DavidKroukamp 你的想法和我的 KeyListener 一样,意味着它在浏览器中不起作用。
你看到我的回答了吗?导致您的 sn-ps anamolies 的代码有很多问题
如果你把JPanel
换成JFrame
看看效果会更好。
【参考方案1】:
使用KeyBindings
而不是KeyListener
不要为JApplet
创建自己的JFrame
,只需在applet 实例上调用getContentPane()
并将所有组件添加到那里。
所有组件都应在 JApplet
覆盖 init()
方法中创建,并包裹在 SwingUtilities#invokeAndWait(..)
块中
JApplet
s 和 Applet
s 没有 main(..)
方法(除了测试目的)
使用requestFocusInWindow()
而不是requestFocus()
我强烈建议您阅读:
How to Make Applets JApplet tutorial这是一个适合我的例子。它只是将不可编辑的JTextField
添加到JPanel
,然后将KeyBinding
s 添加到KeyEvent.VK_0
和KeyEvent.VK_1
到JPanel
。如果用户键入 0 或 1,它将显示在不可编辑的 JTextField
:
import java.awt.BorderLayout;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class BinaryCalc extends JApplet
private JTextField jtf;
@Override
public void init()
try
SwingUtilities.invokeAndWait(new Runnable()
@Override
public void run()
JPanel panel = new JPanel();
setKeyBindings(panel);
jtf = new JTextField(10);
//so we cant edited it without pressing a key
jtf.setEditable(false);
panel.add(jtf);
getContentPane().add(panel, BorderLayout.CENTER);
panel.requestFocusInWindow();//incase we lost focus
);
catch (InterruptedException ex)
Logger.getLogger(BinaryCalc.class.getName()).log(Level.SEVERE, null, ex);
catch (InvocationTargetException ex)
Logger.getLogger(BinaryCalc.class.getName()).log(Level.SEVERE, null, ex);
private void setKeyBindings(final JPanel panel)
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_0,0), "0");
panel.getActionMap().put("0", new AbstractAction()
@Override
public void actionPerformed(ActionEvent ae)
String tmp = jtf.getText();
jtf.setText(tmp + "0");
);
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_1,0), "1");
panel.getActionMap().put("1", new AbstractAction()
@Override
public void actionPerformed(ActionEvent ae)
String tmp = jtf.getText();
jtf.setText(tmp + "1");
);
【讨论】:
如果您将 JTextField(我不能使用)更改为 JLabel,上面的代码似乎不起作用。此外,即使使用 JTextField 它也不起作用。 @Robin92 不确定问题出在哪里,编辑了我的代码 sn-p。前面的观点仍然存在 +1 用于键绑定; hybrid 在开发过程中可能会更容易。 问题似乎是由 IcedTea 造成的。无论如何感谢您的帮助:) @Robin92:David 的代码似乎适用于JLabel
,如here 所示。你得到了不同的结果吗?【参考方案2】:
我冒昧地将@David 的有用示例转换为使用标签和数字键盘。
更新:这个hybrid 在 Ubuntu/OpenJDK 上工作,它可以通过Java Web Start 部署。
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.*;
import javax.swing.*;
/**
* @see https://***.com/a/13363349/230513
*/
public class BinaryCalc extends JApplet
private static BinaryCalc bc = new BinaryCalc();
private JLabel label = new JLabel("0000000000");
public static void main(String[] args)
EventQueue.invokeLater(new Runnable()
@Override
public void run()
JFrame frame = new JFrame();
frame.setTitle("BinaryCalc");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initContainer(frame);
frame.pack();
bc.label.setText("");
frame.setVisible(true);
);
// Common initialization for either JApplet or JFrame
private static void initContainer(Container container)
JPanel panel = new JPanel();
bc.setKeyBindings(panel);
panel.add(bc.label);
container.add(panel, BorderLayout.CENTER);
panel.requestFocusInWindow();
@Override
public void init()
SwingUtilities.invokeLater(new Runnable()
@Override
public void run()
initContainer(BinaryCalc.this);
);
private void setKeyBindings(final JPanel panel)
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_0, 0), "0");
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD0, 0), "0");
panel.getActionMap().put("0", new AbstractAction()
@Override
public void actionPerformed(ActionEvent ae)
String tmp = label.getText();
label.setText(tmp + "0");
);
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "1");
panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD1, 0), "1");
panel.getActionMap().put("1", new AbstractAction()
@Override
public void actionPerformed(ActionEvent ae)
String tmp = label.getText();
label.setText(tmp + "1");
);
【讨论】:
请考虑accepting @David Kroukamp 的answer,因为它先于我自己的。 +1 很棒,我不知何故无法让标签工作,只有 JTextField,因为我忘了打电话给requestFocusInWindow()
。感谢您修复它,我已经绞尽脑汁好几个小时了 :)
JApplet
- init()
的覆盖方法应将其代码包装在 invokeAndWait
块中。 (请参阅我的回答)以上是关于JApplet & KeyListener的主要内容,如果未能解决你的问题,请参考以下文章