(JAVA)通过侦听器移动剪切区域 [英] (JAVA) moving clipping area by keylistener
问题描述
我的目标是使用箭头键一次将剪切区域移动10个像素.我在面板上看到了图像,剪切区域也在那里,但是问题是剪切区域不会移动.这是我的代码,我希望了解它的问题.
My goal is moving clipping area 10 pixels at a time using arrow keys. I got the image on the panel and the clipping area is there too, but the thing is that the clipping area won't move. Here is my code, and I hope to learn what's wrong with it.
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();
}
}
推荐答案
KeyListener
是重点领域的真正难题.如果它所连接的组件不可聚焦并且具有键盘焦点,则它不会触发事件,这就是它的设计方式.相反,请使用旨在解决此问题的Key Bindings API.
KeyListener
is a real pain in the, well, focus area. If the component it is attached to is not focusable AND has keyboard focus, it won't trigger events, that's the way it's designed. Instead, use the Key Bindings API which has been designed to overcome this.
有关更多详细信息,请参见如何使用键绑定
See How to Use Key Bindings for more details
当心修改Graphics
上下文的clip
时,Graphics
上下文是共享资源,这意味着它将被传递给其他组件.如果您不小心,还可以调整剪辑的大小,以使其超出组件的范围绘画,从而导致一些奇怪的图形故障,就我个人而言,我应该远离它.
Be wary of modifying the clip
of a Graphics
context, a Graphics
context is shared resource, meaning that it will be past to other components. You could also, if you're not careful, size the clip in such away as to paint beyond the range of the component, causing some weird graphics glitches, personally, I stay away from it.
如果您改用ImageIO.read
,则可以获取对BufferedImage
的引用,并使用getSubImage
对其进行伪造"
If you use ImageIO.read
instead, you can get a reference to a BufferedImage
and use getSubImage
to "fake" it instead
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();
}
});
}
}
看看读取/加载图像更多详情
您还应该在事件调度线程的上下文中创建和修改UI,请参见初始线程了解更多详情
You should also be creating and modiying your UI from within the context of the Event Dispatching Thread, see Initial Threads for more details
这篇关于(JAVA)通过侦听器移动剪切区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!