image - Java KeyListener isn't detecting keyboard input -
i'm trying modify program draws image of castle , able scale image using , down arrow keys. can't manage keylistener work, program runs isn't responding key presses. 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--; } } }
i can't manage keylistener work, program runs isn't responding key presses.
yours common problem asked here frequently, , problem due lack of focus -- component being listened not have current focus, , focus essential keylistener work.
the short answer give component being listened focus.
the longer better answer not use keylisteners , instead use key bindings such project.
edit
other problems:
- in code above, you're adding keylistener jframe, , shouldn't done, if had reason use keylisteners.
- you're drawing directly in jframe in opinion bigger problem, since risk unwanted side effects.
- you're adding listener inside of paint method, bigger problem. paint method should not overridden (in general), , if did have override it, should never used program logic, adding or removing listeners, or doing non-painting activities. should painting , painting only.
- instead should draw directly in jpanel or jcomponent.
- instead should drawing in
paintcomponent(graphics g)
override in painting jpanel or jcomponent. - just described above, method should painting , painting , should fast possible.
- you should call
super.paintcomponent(g)
inside ofpaintcomponent(graphics g)
override. - again drawing component should listen key strokes using key bindings (tutorial here). tutorial explain why distinction (keylistener vs. key bindings) important.
edit 2
never want ignore exceptions code shows here since programming equivalent of driving blind:
try { url = this.getclass().getresource(filename); } catch (exception e) { }
hopefully not how production code looks, ignored exceptions in posted code sake of brevity, understand many of seeing hearing nails on chalk-board.
edit 3
more on keylisteners vs. key bindings: assuming got code work keylistener, assume added other focusable components gui , somehow got focus via user interaction, keybindings no longer work. if had done correctly key bindings, not issue.
edit 4
want scale field double, not int. , don't want increment , decrement it, rather want multiply , divide multiplier constant, 1.2 example. want call repaint()
whenever change scale.
edit 5
please check out 2 sample programs, first, called drawimagepanelkeylistener.java, uses keylistener, while second, called drawimagepanelkeybindings, uses key bindings. both should compile, run, , function expected: when press or down arrow keys, displayed image shrinks , grows. difference in behavior though can seen when jbutton both have pressed. press button , see happens key response. when component has keylistener loses focus, keylistener stop working, same not true component uses key bindings.
a kludge around problem prevent other components getting focus, not practical or desired gui's.
drawimagepanelkeylistener.java
import java.awt.*; import javax.imageio.imageio; import javax.swing.*; import java.io.ioexception; import java.net.*; import java.awt.event.*; @suppresswarnings("serial") public class drawimagepanelkeylistener extends jpanel implements keylistener { public static final string image_path = "https://duke.kenai.com/" + "nyanya/.midsize/nyanya.jpg.png"; private static final double multiplier = 1.2; double scale = 1.0; private image image; private dimension initialsize = new dimension(0, 0); public static void main(string[] args) { swingutilities.invokelater(new runnable() { public void run() { drawimagepanelkeylistener drawimage = new drawimagepanelkeylistener(); drawimage.add(new jbutton("foo")); jframe frame = new jframe("draw image"); frame.setdefaultcloseoperation(jframe.exit_on_close); frame.add(drawimage); frame.pack(); frame.setlocationrelativeto(null); frame.setvisible(true); } }); } public drawimagepanelkeylistener() { setfocusable(true); requestfocusinwindow(); url imgurl; try { imgurl = new url(image_path); image = imageio.read(imgurl); initialsize = new dimension(image.getwidth(this), image.getheight(this)); addkeylistener(this); setvisible(true); } catch (malformedurlexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } } @override public dimension getpreferredsize() { return initialsize; } @override protected void paintcomponent(graphics g) { super.paintcomponent(g); g.setcolor(color.black); g.fillrect(0, 0, getsize().width, getsize().height); graphics2d g2d = (graphics2d) g.create(); g2d.scale(scale, scale); g2d.drawimage(image, 0, 0, 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 *= multiplier; } if (key == keyevent.vk_down) { scale /= multiplier; } repaint(); } }
drawimagepanelkeybindings.java
import java.awt.*; import javax.imageio.imageio; import javax.swing.*; import java.io.ioexception; import java.net.*; import java.awt.event.*; @suppresswarnings("serial") public class drawimagepanelkeybindings extends jpanel { public static final string image_path = "https://duke.kenai.com/" + "nyanya/.midsize/nyanya.jpg.png"; private static final double multiplier = 1.2; double scale = 1.0; private image image; private dimension initialsize = new dimension(0, 0); public static void main(string[] args) { swingutilities.invokelater(new runnable() { public void run() { drawimagepanelkeybindings drawimage = new drawimagepanelkeybindings(); drawimage.add(new jbutton("foo")); jframe frame = new jframe("draw image"); frame.setdefaultcloseoperation(jframe.exit_on_close); frame.add(drawimage); frame.pack(); frame.setlocationrelativeto(null); frame.setvisible(true); } }); } public drawimagepanelkeybindings() { setbindings(); url imgurl; try { imgurl = new url(image_path); image = imageio.read(imgurl); initialsize = new dimension(image.getwidth(this), image.getheight(this)); setvisible(true); } catch (malformedurlexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } } private void setbindings() { int condition = when_in_focused_window; inputmap inputmap = getinputmap(condition); actionmap actionmap = getactionmap(); final keystroke[] keystrokes = { keystroke.getkeystroke(keyevent.vk_up, 0), keystroke.getkeystroke(keyevent.vk_down, 0) }; (final keystroke keystroke : keystrokes) { inputmap.put(keystroke, keystroke.tostring()); actionmap.put(keystroke.tostring(), new abstractaction() { @override public void actionperformed(actionevent evt) { mykeypressed(keystroke.getkeycode()); } }); } } @override public dimension getpreferredsize() { return initialsize; } @override protected void paintcomponent(graphics g) { super.paintcomponent(g); g.setcolor(color.black); g.fillrect(0, 0, getsize().width, getsize().height); graphics2d g2d = (graphics2d) g.create(); g2d.scale(scale, scale); g2d.drawimage(image, 0, 0, this); } public void mykeypressed(int key) { if (key == keyevent.vk_up) { scale *= multiplier; } if (key == keyevent.vk_down) { scale /= multiplier; } repaint(); } }
Comments
Post a Comment