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
时注册一个额外的。
然后,不要依赖于存储 Component
的 Graphics
对象并在其上绘制东西,因为它可能会发生许多超出您控制范围的事情(例如它可能会被其他发生的 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");
}
}
这是 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
时注册一个额外的。
然后,不要依赖于存储 Component
的 Graphics
对象并在其上绘制东西,因为它可能会发生许多超出您控制范围的事情(例如它可能会被其他发生的 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");
}
}