This is the MainApplication which creates a Frame and holds the class which implements Graphics.
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();
}
}
This class creates all the Graphical shapes and implements the KeyListener too.
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");
}
}
My console output clearly shows that my Key Listener works but its not executing the task which I intend it to do.
Console Output
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
OUTPUT:
The Output which am getting now.. (IMAGE 1)
The output I expect when I press DOWN ARROW Button (IMAGE 2)
The Output I expect when I press UP ARROW Button (IMAGE 3)
First, you shouldn't add a KeyListener
from inside the paint
method, since it will register an additional one each time paint
is called.
Then, don't rely on storing a Graphics
object of a Component
and painting things on it, because many things can happen to it that are outside of your control (for instance it may get cleared by other occuring AWT UI operations).
The only relevant Graphics
object is the instance you receive in paint
, and only in the scope of the paint
method.
So in the following code :
addKeyListener
has been moved outside of paint
. move
with the index of the Shape
to move. move
method
now only registers the Shape
to highlight depending on the index received, and calls repaint
. Graphics2D
object is set as a local variable to paint
, since it
isn't relevant outside.paintHighlightedShape
is responsible for painting the highlighted Shape
, on a Graphics2D
object received as a parameterpaint
method now calls paintHighlightedShape
with its Graphics2D
object passed as a parameter.Note that a main
method has been added to KeyTest
for testing purpose, its content should go in your main class.
Also if you plan on having more Shapes to highlight, you may use an array of Shape
, and the index passed to move
could be the array index of the Shape
to highlight.
Finally, to optimize things, we shouldn't draw the regular shape if it is a highlighted one, since it will be hidden by the green shape anyway.
Consider creating a drawShape(Graphics2D, Shape)
method that will draw the regular shape or the green shape, depending on the shape being highlighted or not.
You would call this method from the paint
method, looping on all shapes.
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");
}
}