(JAVA) перемещение области отсечения по кейлисту
Моя цель - перемещать область отсечения на 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();
}
}
2 ответа
KeyListener
настоящая боль в, ну, в фокусе. Если компонент, к которому он присоединен, не фокусируется и имеет фокус клавиатуры, он не будет вызывать события, как он спроектирован. Вместо этого используйте API Key Bindings, который был разработан, чтобы преодолеть это.
См. Как использовать привязки клавиш для более подробной информации.
Будьте осторожны с изменением clip
из Graphics
контекст, а 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();
}
});
}
}
Посмотрите на Чтение / Загрузка изображения для более подробной информации
Вы также должны создавать и изменять свой пользовательский интерфейс в контексте потока диспетчеризации событий, см. Исходные потоки для получения дополнительной информации.
Вместо использования списка ключей на панели используйте 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);
И во втором редактировании я заменил ваши операторы if переключателем (его значительно удобнее читать и позже легче изменить).