(JAVA)通过侦听器移动剪切区域 [英] (JAVA) moving clipping area by keylistener

查看:72
本文介绍了(JAVA)通过侦听器移动剪切区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是使用箭头键一次将剪切区域移动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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆