我正在寻找一种在窗口进入窗口后捕获或捕获鼠标的方法,就像鼠标被困在虚拟机窗口中一样,直到用户按下CTRL + ALT + DEL或在某些窗口中释放鼠标其他方式。我如何在Java中实现这一目标?全屏不是一个选择。
编辑:
这是你的一些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;
}
}
答案 0 :(得分:4)
我猜你可以使用Global Event Listener来监听框架的鼠标输入事件。然后在鼠标退出事件上,我想你可以使用机器人在鼠标离开框架时重置鼠标的位置。
答案 1 :(得分:2)
好吧,我不假装是一名游戏开发者,但链接中提供的代码很糟糕(据我所知)可用于简单的“乒乓游戏”。我复制了代码并使其运行,以便球反弹。
在我的计算机上,CPU为50%,因为无限循环浪费了CPU时间来为球运动提供动画。使用休眠5ms的线程而不是将CPU占用5ms的简单更改会导致CPU使用率下降到大约18%。
然后我更改了代码以在Swing面板上执行球动画。代码更容易编写,CPU使用率下降到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;
}
}
}
答案 2 :(得分:1)
正如camickr所提到的,你可以使用机器人来做到这一点。这通常是人们会推荐的东西,但这是一个非常好的机器人入门,可以帮助你入门: