I'm trying to modify this program so that it draws an image of a castle and I am able to scale this image using the up and down arrow keys. I can't manage to get the keylistener to work, the program runs but it isn't responding to key presses. Any help will be appreciated, thanks.
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
import java.net.*;
import java.awt.event.*;
public class DrawImage extends JFrame implements KeyListener {
int scale = 1;
private Image image;
enter code here
public static void main(String[] args) {
new DrawImage();
}
public DrawImage() {
super("DrawImage");
setSize(600,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit tk = Toolkit.getDefaultToolkit();
image = tk.getImage(getURL("castle.png"));
addKeyListener(this);
}
private URL getURL(String filename) {
URL url = null;
try {
url = this.getClass().getResource(filename);
}
catch (Exception e) { }
return url;
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform trans = new AffineTransform();
trans.scale(scale, scale);
System.out.println("scale: " + scale);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, getSize().width, getSize().height);
g2d.setTransform(trans);
g2d.drawImage(image, 0, 40, this);
addKeyListener(this);
}
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) { }
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_UP) {
scale++;
}
if (key == KeyEvent.VK_DOWN) {
scale--;
}
}
}
Yours is a very common problem that is asked here frequently, and almost always the problem is due to lack of focus -- that the component being listened to does not have the current focus, and focus is essential for a KeyListener to work.
The short answer is to give the component that is being listened to the focus.
The longer better answer is to not use KeyListeners and instead to use Key Bindings for such a project.
Edit
Other problems:
paintComponent(Graphics g)
override in your painting JPanel or JComponent.super.paintComponent(g)
inside of yourpaintComponent(Graphics g)
override.Edit 2
You never want to ignore exceptions as your code shows here since this is the programming equivalent of driving blind:
Hopefully this is not how your production code looks, that you only ignored the exceptions in your posted code for the sake of brevity, but understand for many of us seeing this is like hearing nails on a chalk-board.
Edit 3
More on KeyListeners vs. Key Bindings: Assuming that you got your code to work with a KeyListener, then assume that you added any other focusable components to your GUI and they somehow got the focus via user interaction, then your KeyBindings will no longer work. If you had done this correctly with Key Bindings, this would not be an issue.
Edit 4
You really want your scale field to be a double, not an int. And you really don't want to increment and decrement it, but rather you want to multiply it and divide it by some multiplier constant, say 1.2 as an example. You will also want to call
repaint()
whenever you change your scale.Edit 5
Please check out two sample programs, the first, called DrawImagePanelKeyListener.java, uses a KeyListener, while the second, called DrawImagePanelKeyBindings, uses Key Bindings. They both should compile, run, and function as expected: when you press the up or down arrow keys, the displayed image shrinks and grows. The difference in their behavior though can be seen when the JButton both have is pressed. Press the button and see what happens to your key response. When the component that has a KeyListener loses focus, its KeyListener will stop working, but the same is not true for the component that uses Key Bindings.
A kludge that could get around this problem could be to prevent all other components from getting the focus, but that is not practical or desired with most GUI's.
DrawImagePanelKeyListener.java
DrawImagePanelKeyBindings.java