Capturar aventos do mouse fora da GUI

Bom dia, boa tarde e boa noite.

Segue um problema que ainda não consegui a solução.

Estou tentando capturar eventos do mouse fora da GUI do java. Tipo, eu quero transformar a tela do meu monitor em um plano cartesiano e a partir daí controlar meu mouse através da aplicação java uma vez iniciada. Não sei se fui bem claro más, o que quero com isso? Quero limitar o movimento do meu cursor baseado na resolução da tela de meu monitor, definir uma área nessa tela onde o monitor só poderá ser movimentar nessa área.

Isso é possível com java, pois com C sei que é, só que quero implementar isso no java mesmo.

Estou bem perto, já consigo capturar as coordenadas do mouse fora da GUI, agora preciso manipular os eventos para que eu possa controlar o cursor.

Obrigado aqueles que se interessarem pelo tópico.

Ola,

De uma pesquisada sobre a class java.awt.Robot.

1 curtida

Ok, vou dar uma olhada. Se servir pra mim posto aqui o código.

Parece que esse é o caminho! :slight_smile:

Com Robot você consegue mover o mouse programaticamente, mas não consegue interceptar eventos do mouse que ocorram fora de uma GUI java.
Isso você só consegue em linguagem nativa.
O que você pode fazer é gerar uma biblioteca em código nativo e usar ela a partir do Java utilizando JNA.

1 curtida

Olá amigo, não sei se você conhece más acho que essa biblioteca pode ser a solução para o que quero. JnativeHook

Vou implementar um teste aqui e postarei o resultado.

Obg.

Boa noite amigos. Então, vou mostrar aqui o que estou querendo fazer e desde já peço a ajudo dos amigos para que possamos clarear as ideias.

Seque abaixo o código onde consegui limitar o movimento do mouse no centro da tela a um quadrado imaginário, más o que eu queria mesmo era que o mouse se movimenta-se dentro de um círculo imaginário.

Acredito que estou mais perto dessa solução do que longe .

@ViniGodoy, você que é muito ativo no forum e sempre tem ótimas soluções, o que me diz desse desafio?

/**
 *
 * @author Josimar Batista Gomes
 * 
 */
public class MouseMotion implements NativeMouseInputListener, NativeMouseMotionListener, NativeKeyListener {
    
    private int mouseX;
    private int mouseY;
    private Point pontoOrigem;
    private static final int RAIO = 100;
    private static final double PI = Math.PI;

    public static void main(String[] args) {

        try {
            GlobalScreen.registerNativeHook();
        } catch (NativeHookException ex) {
            System.exit(1);
        }
        
        MouseMotion captureMouse = new MouseMotion();

        GlobalScreen.addNativeMouseListener(captureMouse);
        GlobalScreen.addNativeMouseMotionListener(captureMouse);
        GlobalScreen.addNativeKeyListener(captureMouse);

    }
    
    public MouseMotion() {
        init();
    }

    /**
     * Centraliza cursor na tela
     */
    private void centralizaCursor() {
        try {
            Robot robot = new Robot();
            robot.mouseMove(getScreenSize().width / 2, getScreenSize().height / 2);
        } catch (AWTException ex) {
            Logger.getLogger(MouseMotion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private double getAreaCircunferencia() {
        return PI * Math.pow(RAIO, 2);
    }

    /**
     * retorna o centro da tela no eixo x
     *
     * @return
     */
    private int getCenterScreenX() {
        return getScreenSize().width / 2;
    }

    private double getCumprimentoCircunferencia() {
        return PI * RAIO;
    }

    /**
     * retorno o centro da tela no eixo y
     *
     * @return
     */
    private int getCenterScreenY() {
        return getScreenSize().height / 2;
    }

    /**
     * Obtem as coordenadas dos eixos x e y do centro da tela
     *
     * @return
     */
    private Point getPontoCentral() {
        Point p = new Point(getCenterScreenX(), getCenterScreenY());
        return p;
    }

    /**
     * Inicializa componentes
     */
    private void init() {
        
        this.pontoOrigem = getPontoCentral();
        centralizaCursor();
        
    }

    private int getDiametro() {
        return RAIO * 2;
    }

    /**
     * Obtem as dimensões do monitor
     *
     * @return
     */
    private Dimension getScreenSize() {
        return Toolkit.getDefaultToolkit().getScreenSize();
    }

    @Override
    public void nativeMouseMoved(NativeMouseEvent nme) {

        try {
            Robot robot = new Robot();
            
            this.mouseX = nme.getX();
            this.mouseY = nme.getY();

            System.out.println("mouse x " + this.mouseX + " mouse y " + this.mouseY);

            if (this.mouseX < (getCenterScreenX() - RAIO)) {
                robot.mouseMove(this.pontoOrigem.x, this.pontoOrigem.y);
            } else if (this.mouseX > (getCenterScreenX() + RAIO)) {
                robot.mouseMove(this.pontoOrigem.x, this.pontoOrigem.y);
            } else if (this.mouseY < (getCenterScreenY() - RAIO)) {
                robot.mouseMove(this.pontoOrigem.x, this.pontoOrigem.y);
            } else if (this.mouseY > (getCenterScreenY() + RAIO)) {
                robot.mouseMove(this.pontoOrigem.x, this.pontoOrigem.y);
            } else {
                this.pontoOrigem = nme.getPoint();
            }
        } catch (AWTException ex) {
            Logger.getLogger(MouseMotion.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    @Override
    public void nativeMouseDragged(NativeMouseEvent nme) {

    }

    @Override
    public void nativeMouseClicked(NativeMouseEvent nme) {

    }

    @Override
    public void nativeMousePressed(NativeMouseEvent nme) {

    }

    @Override
    public void nativeMouseReleased(NativeMouseEvent nme) {

    }

    @Override
    public void nativeKeyPressed(NativeKeyEvent nke) {
        //sai do programa quando a tecla ESC é precionada liberando o movimento do mouse para toda a tela
        if (nke.getKeyCode() == 1) {
            System.exit(0);
        }
    }

    @Override
    public void nativeKeyReleased(NativeKeyEvent nke) {

    }

    @Override
    public void nativeKeyTyped(NativeKeyEvent nke) {

    }

}

Altere sua lógica para usar a distância euclidiana:

double x = mouseX - centerX;
double y = mouseY - centerY;
double dist = Math.sqrt(x*x+y*y);

if (dist <= RADIUS) {
    //o mouse está no circulo
}

As variáveis centerX e centerY representam o centro da area circular onde o mouse deve ficar

2 curtidas

O que seria da tecnologia se um Arquimedes ou um Euclides fossem programadores?
:joy:

1 curtida

Muito obrigado @ViniGodoy

Olá @ViniGodoy, más um probleminha pra mim que não sei se chega ao certo a ser um problema.

Alterei meu método para

public void nativeMouseMoved(NativeMouseEvent nme) {

    try {
        Robot robot = new Robot();

        double x = nme.getX() - getCenterScreenX();
        double y = nme.getY() - getCenterScreenY();

        double dist = Math.sqrt(x * x + y * y);

        if (dist <= RAIO) { //o mouse está no circulo
            this.mouseX = nme.getX();
            this.mouseY = nme.getY();
        } else { //o mouse está fora do circulo
            robot.mouseMove(this.mouseX, this.mouseY);
        }

    } catch (AWTException ex) {
        Logger.getLogger(MouseMotion.class.getName()).log(Level.SEVERE, null, ex);
    }

} 

De fato, está muito melhor, pois o mouse agora está limitado a se movimentar em uma área circular no centro do meu monitor. O problema é que o movimento não fui como eu estava precisando.

O que você pode me sugerir sobre essa questão?

O problema é que o movimento não fui como eu estava precisando.

Depende. O que acontece agora e o que você estava precisando?

O movimento do cursor não flui como eu queria com o código citado acima.

Tipo, quando o cursor sai fora do raio

} else { //o cursor está fora do circulo
        robot.mouseMove(this.mouseX, this.mouseY //defino a posição do mouse para
                                                 //a última posição onde ele se encontrava
                                                 //quando estava dentro do raio
}

O problema é que o cursor do mouse não fica fluído quando eu o movimento.

Tipo, eu quero simular o analógico do joystick

Olá pessoal, não me abandonem agora.

@ViniGodoy, @staroski, @campelo.m

:pray:

A classe Robot é um quebra-galho. Duvido muito que isso vá funcionar do jeito que vc quer.

Esse tipo de coisa geralmente só fica fluida mesmo se vc usar uma linguagem que consiga utilizar recursos do SO para esse tipo de tarefa, como o C++.

Olá @ViniGodoy, faz muito tempo que trabalhei com C/C++ e C#, más vou jogar um óleo pra ver de desenferruja. Obrigado pela contribuição de todos.