Keylistener 工作但未执行预期的操作。为什么?

Keylistener works but is not executing the intended operation. Why?

这是 MainApplication,它创建一个 Frame 并包含实现 Graphics 的 class。

MainApplication.java

import java.awt.*;  

public class MainApplication 
{  
    public MainApplication()  
    {
        Frame frame= new Frame("Test App");
        frame.add(new KeyTest());
        frame.setBackground(Color.RED);
        frame.setLayout(null);  
        frame.setSize(700,750);  
        frame.setVisible(true); 
    } 
    public static void main(String args[])  
    {  

        new MainApplication();

    }
}  

这 class 创建所有图形形状并实现 KeyListener。

KeyTest.java

import java.awt.BasicStroke;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.RoundRectangle2D;

public class KeyTest extends Canvas {


    /**
     * 
     */
    private static final long serialVersionUID = 3L;
    Graphics2D graphics2D;
    Color color = Color.BLACK;
    private static float borderThickness = 5;
    Shape firstShape = new RoundRectangle2D.Double(20,40,300,50,10,10);
    Shape secondShape = new RoundRectangle2D.Double(20,150,300,50,10,10);
    public KeyTest()
    {
        setBackground(Color.RED);
        setSize(700,750);               
    }
    public void paint(Graphics graphics)  
    {  

        graphics2D = (Graphics2D)graphics; //TypeCasting to 2D
        System.out.println("I am inside paint");

        //      Smoothening the corners
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        //      Apple border color
        Stroke oldStroke = graphics2D.getStroke();
        graphics2D.setStroke(new BasicStroke(borderThickness));
        graphics2D.setColor(Color.WHITE);

        //      Drawing a RoundedRectangle for Apple    
        graphics2D.draw(firstShape);
        graphics2D.setStroke(oldStroke);

        //      Setting the Background Color
        graphics2D.setColor(Color.BLACK); 
        graphics2D.fill(firstShape);


        //      Setting the font inside the shape
        Font firstFont = new Font("Serif", Font.BOLD,35);
        graphics2D.setFont(firstFont);
        graphics2D.setColor(Color.WHITE);
        graphics2D.drawString("Apple",30,80);


        //      Pineapple border color 
        graphics2D.setStroke(new BasicStroke(borderThickness));
        graphics2D.setColor(Color.WHITE);

        //      Drawing a RoundedRectangle for Pineapple    
        graphics2D.draw(secondShape);
        graphics2D.setStroke(oldStroke);

        //      Setting the Background Color
        graphics2D.setColor(Color.BLACK); 
        graphics2D.fill(secondShape);

        //      Setting the font inside the shape
        Font secondFont = new Font("Serif", Font.BOLD,35);
        graphics2D.setFont(secondFont);
        graphics2D.setColor(Color.WHITE);
        graphics2D.drawString("Pineapple",30,190);

        addKeyListener(new KeyListener(){

            @Override
            public void keyTyped(KeyEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();

                System.out.println(keyCode);
                System.out.println(KeyEvent.VK_UP);
                if(keyCode==KeyEvent.VK_UP){
                    System.out.println("Going to move up");
                    move(firstShape);

                }
                if(keyCode==KeyEvent.VK_DOWN){
                    System.out.println("Going to move down");
                    move(secondShape);

                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub

            }});
    }
    public void move(Shape s){

        System.out.println("Check:"+s.getBounds2D());
        graphics2D.setColor(Color.GREEN);
        graphics2D.fill(s);
        System.out.println("moving out");
    }
}

我的控制台输出清楚地表明我的 Key Listener 可以工作,但它没有执行我想要它执行的任务。

控制台输出

I am inside paint Going to move up

Check:java.awt.geom.Rectangle2D$Double[x=20.0,y=40.0,w=300.0,h=50.0]

moving out Going to move down

Check:java.awt.geom.Rectangle2D$Double[x=20.0,y=150.0,w=300.0,h=50.0]

moving out

输出:

现在得到的输出..(图像 1)

按下向下箭头按钮时我期望的输出(图像 2)

当我按下向上箭头按钮时我期望的输出(图像 3)

首先,你不应该在 paint 方法中添加一个 KeyListener,因为它会在每次调用 paint 时注册一个额外的。

然后,不要依赖于存储 ComponentGraphics 对象并在其上绘制东西,因为它可能会发生许多超出您控制范围的事情(例如它可能会被其他发生的 AWT UI 操作清除)。

唯一相关的 Graphics 对象是您在 paint 中收到的实例,并且仅在 paint 方法的范围内。

所以在下面的代码中:

  • addKeyListener 已移至 paint 之外。
  • 关键的倾听者 使用要移动的 Shape 的索引调用 move
  • move方法 现在只根据收到的索引注册 Shape 以突出显示,并调用 repaint
  • Graphics2D 对象被设置为 paint 的局部变量,因为它 与外面无关。
  • paintHighlightedShape 负责在作为参数接收的 Graphics2D 对象上绘制突出显示的 Shape
  • paint 方法现在调用 paintHighlightedShape 并将其 Graphics2D 对象作为参数传递。

请注意,main 方法已添加到 KeyTest 用于测试目的,其内容应放在您的主 class.

此外,如果您计划有更多形状要突出显示,您可以使用 Shape 的数组,传递给 move 的索引可以是 Shape 的数组索引突出显示。

最后,为了优化,如果是高亮的规则形状,我们不应该绘制它,因为它无论如何都会被绿色形状隐藏。 考虑创建一个 drawShape(Graphics2D, Shape) 方法来绘制常规形状或绿色形状,具体取决于突出显示或未突出显示的形状。 您可以从 paint 方法调用此方法,在所有形状上循环。

import java.awt.BasicStroke;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.RoundRectangle2D;

public class KeyTest extends Canvas {

    /**
     *
     */
    private static final long serialVersionUID = 3L;
    Color color = Color.BLACK;
    private static float borderThickness = 5;
    Shape firstShape = new RoundRectangle2D.Double(20, 40, 300, 50, 10, 10);
    Shape secondShape = new RoundRectangle2D.Double(20, 150, 300, 50, 10, 10);

    Shape highlightedShape;

    public KeyTest() {
        setBackground(Color.RED);
        setSize(700, 750);
    }

    public static void main(final String[] args) {
        Frame frame = new Frame("Test App");
        final KeyTest keyTest = new KeyTest();
        keyTest.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(final KeyEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void keyPressed(final KeyEvent e) {
                int keyCode = e.getKeyCode();

                System.out.println(keyCode);
                System.out.println(KeyEvent.VK_UP);
                if (keyCode == KeyEvent.VK_UP) {
                    System.out.println("Going to move up");
                    keyTest.move(1);

                }
                if (keyCode == KeyEvent.VK_DOWN) {
                    System.out.println("Going to move down");
                    keyTest.move(2);

                }
            }

            @Override
            public void keyReleased(final KeyEvent e) {
                // TODO Auto-generated method stub

            }
        });
        frame.add(keyTest);
        frame.setBackground(Color.RED);
        frame.setLayout(null);
        frame.setSize(700, 750);
        frame.setVisible(true);
    }

    public void paint(final Graphics graphics) {

        Graphics2D graphics2D = (Graphics2D) graphics; //TypeCasting to 2D
        System.out.println("I am inside paint");

        //      Smoothening the corners
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        //      Apple border color
        Stroke oldStroke = graphics2D.getStroke();
        graphics2D.setStroke(new BasicStroke(borderThickness));
        graphics2D.setColor(Color.WHITE);

        //      Drawing a RoundedRectangle for Apple
        graphics2D.draw(firstShape);
        graphics2D.setStroke(oldStroke);

        //      Setting the Background Color
        graphics2D.setColor(Color.BLACK);
        graphics2D.fill(firstShape);

        //      Setting the font inside the shape
        Font firstFont = new Font("Serif", Font.BOLD, 35);
        graphics2D.setFont(firstFont);
        graphics2D.setColor(Color.WHITE);
        graphics2D.drawString("Apple", 30, 80);

        //      Pineapple border color
        graphics2D.setStroke(new BasicStroke(borderThickness));
        graphics2D.setColor(Color.WHITE);

        //      Drawing a RoundedRectangle for Pineapple
        graphics2D.draw(secondShape);
        graphics2D.setStroke(oldStroke);

        //      Setting the Background Color
        graphics2D.setColor(Color.BLACK);
        graphics2D.fill(secondShape);

        //      Setting the font inside the shape
        Font secondFont = new Font("Serif", Font.BOLD, 35);
        graphics2D.setFont(secondFont);
        graphics2D.setColor(Color.WHITE);
        graphics2D.drawString("Pineapple", 30, 190);

        paintHighlightedShape(graphics2D);

    }

    private void paintHighlightedShape(final Graphics2D graphics2D) {

        if (highlightedShape != null) {

            graphics2D.setColor(Color.GREEN);
            graphics2D.fill(highlightedShape);

        }
    }

    public void move(final int shapeNumber) {

        switch (shapeNumber) {
        case 1:
            highlightedShape = firstShape;
            break;
        case 2:
            highlightedShape = secondShape;
            break;
        default:

        }

        System.out.println("Check:" + highlightedShape.getBounds2D());
        System.out.println("Moving shape : " + highlightedShape);
        repaint();

        System.out.println("moving out");

    }
}