我的目标是使用箭头键一次移动10个像素的裁剪区域。我在面板上得到了图像,剪贴区也在那里,但问题是剪贴区不会移动。以下是我的代码,我希望了解它的问题所在。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class clipping_area extends JFrame{
clipping_area(){
setTitle("OpenChallenge");
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,500);
add(new panelOC());
}
class panelOC extends JPanel{
int xAxis=0;
int yAxis=0;
public void paintComponent(Graphics g){
super.paintComponent(g);
Image img=(new ImageIcon("images/image1.jpg")).getImage();
g.setClip(100+10*xAxis,100+10*yAxis,50,50);
g.drawImage(img,0,0,getWidth(),getHeight(),this);
}
panelOC(){
requestFocus();
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent KE){
if(KE.getKeyCode()==KeyEvent.VK_UP){
yAxis-=1;
repaint();
}
else if(KE.getKeyCode()==KeyEvent.VK_DOWN){
yAxis+=1;
repaint();
}
else if(KE.getKeyCode()==KeyEvent.VK_LEFT){
xAxis-=1;
repaint();
}
else if(KE.getKeyCode()==KeyEvent.VK_RIGHT){
xAxis+=1;
repaint();
}
}
});
}
}
public static void main(String[] args){
new clipping_area();
}
}发布于 2015-01-29 12:28:30
KeyListener在焦点领域是一个真正的痛处。如果它附加到的组件不可聚焦,并且具有键盘焦点,它将不会触发事件,这就是它的设计方式。取而代之的是,使用为克服这一问题而设计的密钥绑定API。
有关详细信息,请参阅How to Use Key Bindings
修改Graphics上下文的clip时要小心,Graphics上下文是共享资源,这意味着它将传递给其他组件。你也可以,如果你不小心,调整剪辑的大小,使其超出组件的范围,从而导致一些奇怪的图形故障,个人而言,我远离它。
如果改为使用ImageIO.read,则可以获取对BufferedImage的引用,并使用getSubImage来“伪造”它
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import static javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ClippingArea extends JFrame {
ClippingArea() {
setTitle("OpenChallenge");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new PanelOC());
pack();
setVisible(true);
}
class PanelOC extends JPanel {
int xAxis = 0;
int yAxis = 0;
private BufferedImage img;
@Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
int width = 50;
if (xAxis + width > img.getWidth()) {
width = img.getWidth() - xAxis;
}
int height = 50;
if (yAxis + height > img.getHeight()) {
height = img.getHeight() - yAxis;
}
if (width > 0 && height > 0) {
BufferedImage subImage = img.getSubimage(xAxis, yAxis, width, height);
g.drawImage(subImage, xAxis, yAxis, this);
}
}
}
protected void registerKeyBinding(String name, KeyStroke keyStroke, Action action) {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(keyStroke, name);
am.put(name, action);
}
public PanelOC() {
try {
img = ImageIO.read(new File("C:\\hold\\thumbnails\\_cg_836___Tilting_Windmills___by_Serena_Clearwater.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
registerKeyBinding("moveClip.up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), new YKeyAction(-10));
registerKeyBinding("moveClip.down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), new YKeyAction(10));
registerKeyBinding("moveClip.left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), new XKeyAction(-10));
registerKeyBinding("moveClip.right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), new XKeyAction(10));
}
public class XKeyAction extends AbstractAction {
private int delta;
public XKeyAction(int delta) {
this.delta = delta;
}
@Override
public void actionPerformed(ActionEvent e) {
xAxis += delta;
if (yAxis > getWidth()) {
yAxis = getWidth() - 50;
} else if (yAxis < 0) {
yAxis = 0;
}
repaint();
}
}
public class YKeyAction extends AbstractAction {
private int delta;
public YKeyAction(int delta) {
this.delta = delta;
}
@Override
public void actionPerformed(ActionEvent e) {
yAxis += delta;
if (yAxis > getHeight()) {
yAxis = getHeight() - 50;
} else if (yAxis < 0) {
yAxis = 0;
}
repaint();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
ClippingArea ca = new ClippingArea();
}
});
}
}有关更多详细信息,请查看Reading/Loading an Image
您还应该在事件分派线程的上下文中创建和修改UI,有关详细信息,请参阅Initial Threads
发布于 2015-01-29 12:25:02
不使用面板上的按键侦听器,而是使用AWTEventListener (它将捕获特定类型的所有事件
java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
toolkit.addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent ae) {
if (ae instanceof KeyEvent) {
KeyEvent KE = (KeyEvent) ae;
if (KE.getID() == KeyEvent.KEY_PRESSED) {
switch(KE.getKeyCode()) {
case KeyEvent.VK_UP:
yAxis -= 1;
break;
case KeyEvent.VK_DOWN:
yAxis += 1;
break;
case KeyEvent.VK_LEFT:
xAxis -= 1;
break;
case KeyEvent.VK_RIGHT:
xAxis += 1;
break;
}
repaint();
}
}
}
}, AWTEvent.KEY_EVENT_MASK);在第二次编辑中,我用一个switch替换了if语句(它的可读性更好,以后也更容易修改。
https://stackoverflow.com/questions/28206950
复制相似问题