截至目前,我只能让我的一个键绑定一次一个地工作。它通常是第一个创建的。当我按下按键时,每个人都有自己的课程,所以我不明白为什么我的所有按键都不起作用。是因为他们都共享同一个小组吗?目前我有三个动作类,UpAction,PlusAction和MinusAction。 UpAction向上移动矩形,另外两个增加/减小矩形的大小。我遇到的另一个问题是当我向上移动矩形时,当我点击我的增加/减少按钮时,我的向上命令将不再起作用。我是否必须为我的代码写一些内容以重新获得向上箭头键上的焦点?
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;
import javax.swing.Icon;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
public class Rectangle extends JPanel {
private int height;
private int width;
private int x;
private int y;
private Graphics2D g2;
private Action plusAction;
private Action minusAction;
private Action up;
private static JButton buttonIncrease;
private static JButton buttonDecrease;
public Rectangle(int width, int height,int x, int y)
{
this.height = height;
this.width = width;
this.x = x;
this.y = y;
JLabel label = new JLabel();
buttonIncrease = new JButton(" Increase Size ");
buttonDecrease = new JButton(" Decrease Size ");
buttonIncrease.addActionListener(new ButtonListener());
buttonDecrease.addActionListener(new ButtonListener());
buttonIncrease.setActionCommand("1");
buttonDecrease.setActionCommand("2");
up = new UpAction();
getInputMap().put(KeyStroke.getKeyStroke("UP"), "doUpAction");
getActionMap().put("doUpAction", up);
plusAction = new PlusAction();
minusAction = new MinusAction();
buttonIncrease.getInputMap().put(KeyStroke.getKeyStroke(" released Q"), "doPlusAction");
buttonIncrease.getActionMap().put("doPlusAction", plusAction);
buttonDecrease.getInputMap().put(KeyStroke.getKeyStroke(" released A"), "doMinusAction");
buttonDecrease.getActionMap().put("doMinusAction", minusAction);
add(buttonIncrease);
add(buttonDecrease);
label.addKeyListener(new LabelListener());
label.setFocusable(true);
label.setOpaque(true);
this.add(label);
//label.requestFocusInWindow();
setVisible(true);
}
public Dimension getPreferredSize() {
return new Dimension(500,500);
}
static class PlusAction extends AbstractAction
{
//When the plus key is pressed, the increase button
//will be pressed
public void actionPerformed(ActionEvent arg0) {
buttonIncrease.doClick();
}
}
static class MinusAction extends AbstractAction
{
//When the minus key is pressed, the decrease button
//will be pressed
public void actionPerformed(ActionEvent arg0) {
buttonDecrease.doClick();
}
}
class UpAction extends AbstractAction
{
public void actionPerformed(ActionEvent e) {
y = y - 5;
repaint();
}
}
// Listener for increasing/decreasing size buttons
class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
int action = Integer.parseInt(e.getActionCommand());
switch(action){
case 1:
height = height + 5;
width = width + 5;
repaint();
break;
case 2:
height = height - 5;
width = width - 5;
repaint();
break;
}
}
}
class LabelListener implements KeyListener {
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
y = y + 5;
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
x = x - 5;
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_UP)
{
y = y - 5;
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
{
x = x + 5;
repaint();
}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.g2 = (Graphics2D) g;
g2.drawString("X: " + x,10,20);
g2.drawString("Y: " + y,10,35);
g2.drawString("Width: " + width,10,55);
g2.drawString("Height: " + height,10,70);
g2.drawRect(x, y, width, height);
}
}
测试类:
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame f = new JFrame("Rectangle");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Rectangle(40,20,250,250));
f.pack();
f.setVisible(true);
}
}
答案 0 :(得分:4)
结帐Motion Using the Keyboard。 KeyboardAnimation
示例显示了如何让多个KeyStrokes一次工作以提供对角线运动。
基本上你需要跟踪按下了哪些键,然后将每个键的动作加在一起以获得组合动作。
您的代码显然会有所不同,因为您可能需要为每次击键设置不同类型的操作,以保留两个不同的击键图,一个用于运动,另一个用于尺寸更改。然后,每次Timer触发时,您都会分别查询两个映射以确定组合的更改。
答案 1 :(得分:4)
您没有正确设置输入地图的条件:
private static final int INPUT_CONDITION = JComponent.WHEN_IN_FOCUSED_WINDOW;
private int height;
private int width;
//...
public Rectangle(int width, int height, int x, int y) {
// .....
up = new UpAction();
// ******** note difference to the getInputMap method below
getInputMap(INPUT_CONDITION).put(KeyStroke.getKeyStroke("UP"),
"doUpAction");
getActionMap().put("doUpAction", up);
plusAction = new PlusAction();
minusAction = new MinusAction();
buttonIncrease.getInputMap(INPUT_CONDITION).put(
KeyStroke.getKeyStroke("released Q"), "doPlusAction");
buttonIncrease.getActionMap().put("doPlusAction", plusAction);
buttonDecrease.getInputMap(INPUT_CONDITION).put(
KeyStroke.getKeyStroke("released A"), "doMinusAction");
默认的InputMap条件是JComponent.WHEN_FOCUSED,并且键绑定仅在被侦听组件具有焦点时才起作用。在您的情况下,最好将其明确设置为JComponent.WHEN_IN_FOCUSED_WINDOW,现在只要组件位于具有焦点的窗口中,它就会起作用。
您在致电getInputMap
时进行了设置。而不是以默认方式getInputMap()
调用它,我建议您将其称为getInputMap(INPUT_CONDITION)
,设置适当的常量。
你在代码中也有KeyListeners - 为什么?拥有Graphics2D或Graphics类字段可能会导致灾难。我将摆脱Graphics2D字段,只需在paintComponent方法或paintComponent调用的方法中使用它。
修改强>
你问:
为什么全局使用Graphics2D会是一件坏事? -
因为拥有变量会使它很有诱惑力,并且如果你在paintComponent之外使用它,你可能会遇到NullPointerException,因为以这种方式从JVM获取的Graphics对象是一个非常短暂的事情。相信我,摆脱那个变量。