Захват (ловушка) курсора мыши в окне на Java - PullRequest
3 голосов
/ 20 марта 2010

Я ищу способ захвата или захвата мыши в окне после того, как оно вошло в это окно, так же, как мышь попадает в окно виртуальной машины, пока пользователь не нажмет CTRL + ALT + DEL или не отпустит мышь в каком-либо окне. другой способ. Как я могу сделать это в Java? Переход на полный экран не возможен.

EDIT:

Вот немного SSCCE для тебя. Этот код будет ловить вашу мышь в окне. Чтобы выйти, вам нужно просто сгенерировать кадр и перейти непосредственно к кнопке закрытия. Если вы заметите, когда ваша мышь пытается выйти, она автоматически вернется к (0,0). Что мне нужно знать, так это как заставить его вернуться к координатам, откуда он вышел. Я пробовал getX () и getY () вместо (0,0), но робот там не возвращает мышь (я думаю, что время отклика слишком медленное). Я также заставил робота переместить мышь обратно в crosshair.x и crosshair.y, но это (как и другие) по-прежнему позволяет мыши убежать, если пользователь щелкнет в нужный момент. Какие-нибудь мысли?

Основной класс:

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;
import java.awt.image.MemoryImageSource;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import javax.swing.JFrame;

public class Game extends JFrame implements MouseMotionListener, MouseListener{

    private int windowWidth = 640;
    private int windowHeight = 480;
        private Crosshair crosshair;

    public static void main(String[] args) {
        new Game();
    }

    public Game() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(windowWidth, windowHeight);
        this.setResizable(false);
        this.setLocation(0,0);
        this.setVisible(true);

        this.createBufferStrategy(2);
                addMouseMotionListener(this);
                addMouseListener(this);
        initGame();

        while(true) {
            long start = System.currentTimeMillis();
            gameLoop();
            while(System.currentTimeMillis()-start < 5) {
                            //empty while loop
            }
        }
    }

    private void initGame() {
            hideCursor();
            crosshair = new Crosshair (windowWidth/2, windowHeight/2);
    }

        private void gameLoop() {
            //game logic
            drawFrame();
        }

        private void drawFrame() {

            BufferStrategy bf = this.getBufferStrategy();
            Graphics g = (Graphics)bf.getDrawGraphics();
            try {
                g = bf.getDrawGraphics();
                Color darkBlue = new Color(0x010040);
                g.setColor(darkBlue);
                g.fillRect(0, 0, windowWidth, windowHeight);
                drawCrossHair(g);
            } finally {
                g.dispose();
            }
            bf.show();
            Toolkit.getDefaultToolkit().sync();
        }

        private void drawCrossHair(Graphics g){
            Color yellow = new Color (0xEDFF62);
            g.setColor(yellow);
            g.drawOval(crosshair.x, crosshair.y, 40, 40);

            g.fillArc(crosshair.x + 10, crosshair.y + 21 , 20, 20, -45, -90);
            g.fillArc(crosshair.x - 1, crosshair.y + 10, 20, 20, -135, -90);
            g.fillArc(crosshair.x + 10, crosshair.y - 1, 20, 20, -225, -90);
            g.fillArc(crosshair.x + 21, crosshair.y + 10, 20, 20, -315, -90);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
        //empty method
        }

        @Override
        public void mouseMoved(MouseEvent e) {
        crosshair.x = e.getX();
        crosshair.y = e.getY();
        }

        private void hideCursor() {
            int[] pixels = new int[16 * 16];
            Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
            Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "invisiblecursor");
            getContentPane().setCursor(transparentCursor);
    }

        public void mouseExited(MouseEvent e) {
            System.out.println("Event: " + e);
            try {
                Robot robot = new Robot();
                robot.mouseMove(0, 0);// When I use (getX(),getY()) instead of (0,0) the robot will not move the mouse at all even though getX() and getY() are the coordinates I want the mouse to be moved to.  Also the mouse can still escape, even when crosshair.x and crosshair.y are used as the coordinates.  It seems that robot is too slow.
            }
            catch (AWTException ex) {
                ex.printStackTrace();
            }
        }

        public void mouseEntered(MouseEvent e){
        }

        public void mousePressed(MouseEvent e) {
        }

        public void mouseReleased(MouseEvent e) {
        }

        public void mouseClicked(MouseEvent e) {
        }
}

Другой класс:

public class Crosshair{
        public int x;
    public int y;
    public Crosshair(int x, int y) {
        this.x = x;
        this.y = y;
        }
}

Ответы [ 3 ]

4 голосов
/ 20 марта 2010

Полагаю, вы могли бы использовать Global Event Listener для прослушивания введенных мышью событий для кадра. Затем, при событии выхода из мыши, я полагаю, вы можете использовать робота, чтобы сбросить расположение мыши, когда она покидает рамку.

2 голосов
/ 21 марта 2010

Ну, я не притворяюсь разработчиком игры, но код, представленный в ссылке, ужасен (насколько я могу судить) для простой "игры в понг".Я скопировал код и запустил его, чтобы мяч подпрыгивал.

На моем компьютере ЦП составляет 50% из-за бесконечного цикла while, который тратит время ЦП на анимацию движения шара.Простое изменение использования потока, который спит в течение 5 мс, а не загружает процессор в течение 5 мс, приводит к снижению загрузки ЦП примерно до 18%.

Затем я изменил код, чтобы сделать анимацию шара на Swingпанель.Код легче написать, загрузка ЦП упала до 1%, а анимация шаров стала намного быстрее.

Вот моя последняя версия.Вы сможете вернуться к использованию буферизованной стратегии, не добавляя панель к фрейму, а затем снова вызвав метод drawFrame ().

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;

import javax.swing.*;

public class Game3 extends JFrame {

    /**
     * @author Georgi Khomeriki
     */

    private Ball ball;

    // added this
    private JPanel gamePanel;

    private int windowWidth = 800;
    private int windowHeight = 600;


    public static void main(String[] args) {
        new Game3();
    }

    public Game3() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(windowWidth, windowHeight);
        this.setResizable(false);
        this.setLocation(100, 100);
        this.setVisible(true);

        this.createBufferStrategy(2);

        initGame3();
/*
        while(true) {
            long start = System.currentTimeMillis();
            gameLoop();
            while(System.currentTimeMillis()-start < 5) {
                 //do nothing
            }
        }
*/

        Thread thread = new Thread(new Runnable()
        {
            public void run()
            {
                while(true)
                {
                    gameLoop();
                    try { Thread.sleep(5); }
                    catch(Exception e) {}
                }
            }
        });
        thread.start();

    }

    private void initGame3() {
        // all you're game variables should be initialized here
        ball = new Ball(windowWidth/2, windowHeight/2, 5, 5);

        // added these lines

        gamePanel = new GamePanel();
        gamePanel.setBackground(Color.BLACK);
        add(gamePanel);
    }

    private void gameLoop() {
        // your game logic goes here

// move the ball
    ball.x = ball.x + ball.dx;
    ball.y = ball.y + ball.dy;

    // change the direction of the ball if it hits a wall
    if(ball.x <= 0 || ball.x >= windowWidth-40)
        ball.dx = -ball.dx;
    if(ball.y <= 0 || ball.y >= windowHeight-40)
        ball.dy = -ball.dy;


        // changed to following to use Swing instead of buffer strategy
//      drawFrame();
        gamePanel.repaint();
    }

    private void drawFrame() {
        // code for the drawing goes here
        BufferStrategy bf = this.getBufferStrategy();
        Graphics g = null;

        try {
            g = bf.getDrawGraphics();

            // clear the back buffer (just draw a big black rectangle over it)
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, windowWidth, windowHeight);

drawBall(g);


        } finally {
            // It is best to dispose() a Graphics object when done with it.
            g.dispose();
        }

        // Shows the contents of the backbuffer on the screen.
        bf.show();

        //Tell the System to do the Drawing now, otherwise it can take a few extra ms until
        //Drawing is done which looks very jerky
        Toolkit.getDefaultToolkit().sync();
    }

    private void drawBall(Graphics g) {

        g.setColor(Color.GREEN);
        g.fillOval(ball.x, ball.y, 40, 40);
    }

    // added this

    class GamePanel extends JPanel
    {
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            drawBall(g);
        }
    }


    class Ball {

        public int x;
        public int y;
        public int dx;
        public int dy;

        public Ball(int x, int y, int dx, int dy) {
            this.x = x;
            this.y = y;
            this.dx = dx;
            this.dy = dy;
        }
    }



}
1 голос
/ 20 марта 2010

Как упоминает camickr, вы можете сделать это с помощью робота. Обычно это то, против чего люди рекомендуют, но вот довольно хороший учебник для роботов, с которого можно начать:

http://www.developer.com/java/other/article.php/2212401/Introduction-to-the-Java-Robot-Class-in-Java.htm

...