Keyboard events java - java

I have recently started learning java.I want to make a game like https://sites.google.com/site/millseagles/home/Games/multiplayer/tron
I have made it in c++ once using a simple graphics lib. I have the graphics part down i plan to use small images and use http://horstmann.com/sjsu/graphics/ this basic graphics lib.I can't figure out keyboard input i want it so if you press an arrow the picture adds a small green square(I have a green.png).I can't figure out to use keyboard listeners.I get all these errors.I just need a simple lib that i can say getKey() or something and i can use if() to figure out the action.this is the code I have.I was messing with the key event but don't understand it.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.*;
public class game implements KeyListener
{
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
public game()//snake like game
{
}
public void test()
{
int x=30,y=30;//middle total 60x60
tile[] map=new tile[3600];//tile is a class i made that is a picture and some int and bool using the simple lib i linked 60 by 60 tiles
for(int i=0;i<3600;i++)
{
map[i]=new tile();
}
}
public void keyPressed(KeyEvent e)//this does not work i want it to work when a key is clicked
{
while(x>0)//this part works when it is not in the keypressed function
{
map[(y*60)+x].load(4);//4 refrences a green rectangle image
map[(y*60)+x].draw(x,y,10);//draw it based on x and y 10 pixels sized tiles
x--;//make a line going left
}
}
}
I know this may be messy.I have tested my code it works it just breaks when i try to implement keyboard events.If you can point me to a much more beginner friendly lib that would be great.

You simply have to add the listener to something (e.g. the window where the game is being played).
I will give you an example, where we will simply display the code of the key being stroked.
This is the class where you produce the interface:
import java.awt.Dimension;
import javax.swing.JFrame;
public class Game {
public static void main(String[] args) {
/* Creating a window (300x400) */
JFrame frame = new JFrame("Add your own title");
frame.setPreferredSize(new Dimension(300, 400));
/* This is the part where we add the keyListener (notice that I am also sending
* this window as a parameter so that the listener can modify it)*/
frame.addKeyListener(new ArrowListener(frame));
/* Making the window visible */
frame.pack();
frame.setVisible(true);
}
}
And this is the class where we have the listener:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ArrowListener implements KeyListener {
/* We keep the window as an instance variable so we can modify it once the event is triggered */
JFrame frame;
/* This is the constructor */
public ArrowListener(JFrame j) {
frame = j;
}
/* This is where the magic happens */
public void keyPressed(KeyEvent e) {
/* Modify this with what you actually want it to do */
/* We clear the panel so we can add new text without any other text behind it */
frame.getContentPane().removeAll();
/* We add some text that actually shows the keyCode (left arrow = 37, top = 38, right = 39, bottom = 40) */
frame.add(new JLabel("Key Code #" + String.valueOf(e.getKeyCode())));
/* Redrawing the window */
frame.revalidate();
}
/* These two are part of the contract we made when we decided to
* implement the KeyListener */
public void keyTyped(KeyEvent e) { /* Do nothing */ }
public void keyReleased(KeyEvent e) { /* Do nothing */ }
}
Note: when running the program press the keys to see the text appearing on the window.
I didn't get around the library you were using, but I used the most popular one called swing (tutorial)

Related

I am not sure what is incorrect

I am creating a small Java Jpanel game in which I am supposed to have a rocket that moves up and down via arrows and fires via space.
The firing method should work like this: Space bar pressed, thing fires and moves across screen , and then when it hits a certain x, it disappears. Also, you can only fire once until the other bullet disappears.
I do not know what I am doing wrong. For one, as soon as my code starts you can see a bullet flying across the screen.
2nd, the bullet is not disappearing.
3rd, even though the other bullet is still visible, it allows me to fire again.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class SpaceGame extends JPanel implements ActionListener{
Timer t = new Timer(2, this);
private ImageIcon rocket,asteroid,bullet;
private JLabel rocketlabel,ast1,ast2,ast3,bulletLabel;
public static int y=90,dy=0,bulletX=110,bulletY,i=0,canFire;
//public sound sound;
static boolean bulletFired=false;;
static JFrame f = new JFrame();
SpaceGame(){
this.setBackground(Color.black);
rocket = new ImageIcon(getClass().getResource("rocketFinal.png"));
rocketlabel= new JLabel(rocket);
this.add(rocketlabel);
asteroid = new ImageIcon(getClass().getResource("asteroid.png"));
ast1=new JLabel(asteroid);
ast2=new JLabel(asteroid);
ast3=new JLabel(asteroid);
bullet = new ImageIcon(getClass().getResource("bulletReal.png"));
bulletLabel = new JLabel(bullet);
canFire=1;
bulletLabel.setVisible(false);
this.add(ast1);this.add(ast2);this.add(ast3);this.add(bulletLabel);
f.addKeyListener(new controller());
this.setLayout(null);
this.setVisible(true);
}
public class controller implements KeyListener{
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode== KeyEvent.VK_UP) {
dy=-1;
}
if(keyCode== KeyEvent.VK_DOWN) {
dy=1;
}
if(keyCode== KeyEvent.VK_SPACE) {
if(canFire==0) {
System.out.println(String.valueOf(canFire));
bulletFired = true;
bulletY = y;
bulletX=110;
}canFire=1;
}
}
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_UP: dy=0; break;
case KeyEvent.VK_DOWN: dy=0; break;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
rocketlabel.setBounds(45,y,rocket.getIconWidth(),80);
fireBullet();
paintStars(g);
t.start();
}
public void paintStars(Graphics g) {
g.setColor(Color.yellow);
for(int i=0; i<5;i++) {
Random rand = new Random();
int o = rand.nextInt(500);
int p = rand.nextInt(300);
g.fillOval(o, p, 3, 3);
}
}
public void actionPerformed(ActionEvent e) {
if(y==-20) y=249;
if(y==250)y=-20;
y+=dy;
if(bulletFired=true) {
bulletX++;
if(bulletX==455)bulletFired=false;bulletLabel.setVisible(false);System.out.println(String.valueOf(bulletX)); canFire=0;
}
repaint();
}
public void fireBullet(){
if(bulletFired=true) {
bulletLabel.setVisible(true);
bulletLabel.setBounds(bulletX,bulletY+25,bullet.getIconHeight(),bullet.getIconWidth());
}
}
public static void main(String[] args) {
String filepath = "SpaceGameMusic.wav";
musicStuff musicPlayer = new musicStuff();
musicPlayer.playMusic(filepath);
SpaceGame t = new SpaceGame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(t);
f.setSize(500,335);
f.setVisible(true);
f.setResizable(false);
}
}
For one, as soon as my code starts you can see a bullet flying across the screen.
The paintComponent() method is for painting only. You can't control when Swing will determine a component needs to be repainted.
So, for example:
t.start();
should NOT be in the painting method. As soon as the frame is made visible the panel will be painted and the Timer will be started.
You application code should control when the Timer is started.
Other issues:
you should not be using static variables. The variable should simply be instances of your class.
the paintStars() method should not generate random locations. Again. a painting method should only paint the current state of the class. So if you want to change the location of the stars you should have a method like randomizeStars(). In this method you would update an ArrayList of Point objects. Each Point instance would represent the location of a star. Then the paintStars() method would simply iterate through the ArrayList and paint each star.
you should not be using a KeyListener. A KeyListener only works if a component has focus. You can't guarantee that your component will lose focus. Instead you should be using Key Bindings. Key bindings allow you to handle a KeyEvent even if the component doesn't have focus. See Motion Using the Keyboard for more information and a working example.
you can only fire once until the other bullet disappears
Your canFire variable should be a boolean variable so it only has true/false values. Again you have a method that sets the state. Your game logic will then check the state before firing the bullet again.
if(y==-20) y=249;
if(y==250)y=-20;
Don't hardcode values. The number should be based on the size of your panel. So you use methods like getWidth() and getHeight() to determine the current size of the panel.
The problem was quite simply that I had forgotten to use == in my if(boolean) statements.

Java Jframe ICONIFIED closing failure

Thanks to a previous question answered I am now able to start my application as a tray icon (Java frame iconified issue), however I am now running into a few different issues and I am having trouble figuring out how to fix them. When the main program runs, the console window indeed no longer launches full screen as intended, however instead of just forming a system tray icon in the bottom right corner, the window also forms a traditional minimized window on the task bar. I have noticed that previously before I made this change, when the "Hide Window" button is pressed, the main taskbar window disappears leaving only the smaller system tray icon in the right corner. It seems the changes recommended in the previous question keeps the window running, but just seems to hide it from view. How can I change this behavior? I only expected to see the small system tray icon in the bottom right corner. Also, upon exiting the main application, the tray icons don't close down. They stay open, sometimes piling up if the main application is launched multiple times. If only I could figure out where the "Hide Window" action was coming from, I feel like I could figure this out, but alas, I cant see to find the actions of that button referenced anywhere in the code. Please help!
package com.skcraft.launcher.dialog;
import com.skcraft.launcher.Launcher;
import com.skcraft.launcher.swing.LinedBoxPanel;
import com.skcraft.launcher.swing.MessageLog;
import com.skcraft.launcher.swing.SwingHelper;
import com.skcraft.launcher.util.PastebinPoster;
import com.skcraft.launcher.util.SharedLocale;
import lombok.Getter;
import lombok.NonNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static com.skcraft.launcher.util.SharedLocale.tr;
/**
* A frame capable of showing messages.
*/
public class ConsoleFrame extends JFrame {
private static ConsoleFrame globalFrame;
#Getter private final Image trayRunningIcon;
#Getter private final Image trayClosedIcon;
#Getter private final MessageLog messageLog;
#Getter private LinedBoxPanel buttonsPanel;
private boolean registeredGlobalLog = false;
/**
* Construct the frame.
*
* #param numLines number of lines to show at a time
* #param colorEnabled true to enable a colored console
*/
public ConsoleFrame(int numLines, boolean colorEnabled) {
this(SharedLocale.tr("console.title"), numLines, colorEnabled);
}
/**
* Construct the frame.
*
* #param title the title of the window
* #param numLines number of lines to show at a time
* #param colorEnabled true to enable a colored console
*/
public ConsoleFrame(#NonNull String title, int numLines, boolean colorEnabled) {
messageLog = new MessageLog(numLines, colorEnabled);
trayRunningIcon = SwingHelper.createImage(Launcher.class, "tray_ok.png");
trayClosedIcon = SwingHelper.createImage(Launcher.class, "tray_closed.png");
setTitle(title);
setIconImage(trayRunningIcon);
setSize(new Dimension(650, 400));
setExtendedState(JFrame.ICONIFIED); //This is the new line of code added to minimize the window on load
initComponents();
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent event) {
performClose();
}
});
}
/**
* Add components to the frame.
*/
private void initComponents() {
JButton pastebinButton = new JButton(SharedLocale.tr("console.uploadLog"));
JButton clearLogButton = new JButton(SharedLocale.tr("console.clearLog"));
buttonsPanel = new LinedBoxPanel(true);
buttonsPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
buttonsPanel.addElement(pastebinButton);
buttonsPanel.addElement(clearLogButton);
add(buttonsPanel, BorderLayout.NORTH);
add(messageLog, BorderLayout.CENTER);
clearLogButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
messageLog.clear();
}
});
pastebinButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pastebinLog();
}
});
hideMessages();
}
/**
* Register the global logger if it hasn't been registered.
*/
private void registerLoggerHandler() {
if (!registeredGlobalLog) {
getMessageLog().registerLoggerHandler();
registeredGlobalLog = true;
}
}
/**
* Attempt to perform window close.
*/
protected void performClose() {
messageLog.detachGlobalHandler();
messageLog.clear();
registeredGlobalLog = false;
dispose();
}
/**
* Send the contents of the message log to a pastebin.
*/
private void pastebinLog() {
String text = messageLog.getPastableText();
// Not really bytes!
messageLog.log(tr("console.pasteUploading", text.length()), messageLog.asHighlighted());
PastebinPoster.paste(text, new PastebinPoster.PasteCallback() {
#Override
public void handleSuccess(String url) {
messageLog.log(tr("console.pasteUploaded", url), messageLog.asHighlighted());
SwingHelper.openURL(url, messageLog);
}
#Override
public void handleError(String err) {
messageLog.log(tr("console.pasteFailed", err), messageLog.asError());
}
});
}
public static void showMessages() {
ConsoleFrame frame = globalFrame;
if (frame == null) {
frame = new ConsoleFrame(10000, false);
globalFrame = frame;
frame.setTitle(SharedLocale.tr("console.launcherConsoleTitle"));
frame.registerLoggerHandler();
frame.setVisible(true);
} else {
frame.setVisible(true);
frame.registerLoggerHandler();
frame.requestFocus();
}
}
public static void hideMessages() {
ConsoleFrame frame = globalFrame;
if (frame != null) {
frame.setVisible(false);
}
}
}

Adding links to options in a Input Dialog

I'm trying to add links into a project that i'm making in eclipse. I have researched on how to do it, but i can't find much on it that pertains to eclipse.
This is the code that im trying to add links too:
Object[] possibilities = {"" +
"AWS Welder Certification Testing",
"Computer science",
"Aviation", "Construction",
"Health science",
"Programming",
"3D design",
"Cyber security",
"Advanced Safety Certification",
"Healthcare Provider CPR",
"Dietary Manager",
"Insurance",
"Emergency 911 Operator",
"Job Safety Analysis",
"Real Estate",
"Pharmacy Technician",
"Special Needs Education",
"School Bus Driver Training",
"Phlebotomy Technician",
"Security Guard",
"Home Inspection",
"Court Reporter",
"Long Term Care/Nurse Aide (CNA)",
"EPA Lead Safe Renovator Certification",};
Component frame = null;
Icon icon = null;
String s = (String)JOptionPane.showInputDialog(
frame,
"What class might you want to attend?\n"
+ "\"The options are endless!\"",
"Class Options",
JOptionPane.PLAIN_MESSAGE,
icon,
possibilities,
"all");
When I run the program, a dialog box appears, and it gives all the options of classes above. How would I make it to where when the user clicks on a class it will link them to the website for that class?
I recommend using a JTextField rather than a JButton for this use.
E.G.
That is how it appears when the mouse is hovering over the first link.
LinkLabel.java
/* License - LGPL
LinkLabel Using the Desktop Class
There are a lot of link labels. This one uses the Java 1.6+
Desktop class for its functionality, and is thereby suitable
for applets, applications launched using JWS, and 'standard'
(non-JWS) desktop applications.
*/
import java.awt.Desktop;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.JTextField;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.border.MatteBorder;
import javax.swing.border.Border;
import java.net.URI;
import java.io.File;
/**
A Java 1.6+ LinkLabel that uses the Desktop class for opening
the document of interest.
The Desktop.browse(URI) method can be invoked from applications,
applets and apps. launched using Java Webstart. In the latter
two cases, the usual fall-back methods are used for sandboxed apps
(see the JavaDocs for further details).
While called a 'label', this class actually extends JTextField,
to easily allow the component to become focusable using keyboard
navigation.
To successfully browse to a URI for a local File, the file name
must be constructed using a canonical path.
#author Andrew Thompson
#version 2008/08/23
*/
public class LinkLabel
// we extend a JTextField, to get a focusable component
extends JTextField
implements MouseListener, FocusListener, ActionListener {
/** The target or href of this link. */
private URI target;
public Color standardColor = new Color(0,0,255);
public Color hoverColor = new Color(255,0,0);
public Color activeColor = new Color(128,0,128);
public Color transparent = new Color(0,0,0,0);
public boolean underlineVisible = true;
private Border activeBorder;
private Border hoverBorder;
private Border standardBorder;
/** Construct a LinkLabel that points to the given target.
The URI will be used as the link text.*/
public LinkLabel(URI target) {
this( target, target.toString() );
}
/** Construct a LinkLabel that points to the given target,
and displays the text to the user. */
public LinkLabel(URI target, String text) {
super(text);
this.target = target;
}
/* Set the active color for this link (default is purple). */
public void setActiveColor(Color active) {
activeColor = active;
}
/* Set the hover/focused color for this link (default is red). */
public void setHoverColor(Color hover) {
hoverColor = hover;
}
/* Set the standard (non-focused, non-active) color for this
link (default is blue). */
public void setStandardColor(Color standard) {
standardColor = standard;
}
/** Determines whether the */
public void setUnderlineVisible(boolean underlineVisible) {
this.underlineVisible = underlineVisible;
}
/* Add the listeners, configure the field to look and act
like a link. */
public void init() {
this.addMouseListener(this);
this.addFocusListener(this);
this.addActionListener(this);
setToolTipText(target.toString());
if (underlineVisible) {
activeBorder = new MatteBorder(0,0,1,0,activeColor);
hoverBorder = new MatteBorder(0,0,1,0,hoverColor);
standardBorder = new MatteBorder(0,0,1,0,transparent);
} else {
activeBorder = new MatteBorder(0,0,0,0,activeColor);
hoverBorder = new MatteBorder(0,0,0,0,hoverColor);
standardBorder = new MatteBorder(0,0,0,0,transparent);
}
// make it appear like a label/link
setEditable(false);
setForeground(standardColor);
setBorder(standardBorder);
setCursor( new Cursor(Cursor.HAND_CURSOR) );
}
/** Browse to the target URI using the Desktop.browse(URI)
method. For visual indication, change to the active color
at method start, and return to the standard color once complete.
This is usually so fast that the active color does not appear,
but it will take longer if there is a problem finding/loading
the browser or URI (e.g. for a File). */
public void browse() {
setForeground(activeColor);
setBorder(activeBorder);
try {
Desktop.getDesktop().browse(target);
} catch(Exception e) {
e.printStackTrace();
}
setForeground(standardColor);
setBorder(standardBorder);
}
/** Browse to the target. */
public void actionPerformed(ActionEvent ae) {
browse();
}
/** Browse to the target. */
public void mouseClicked(MouseEvent me) {
browse();
}
/** Set the color to the hover color. */
public void mouseEntered(MouseEvent me) {
setForeground(hoverColor);
setBorder(hoverBorder);
}
/** Set the color to the standard color. */
public void mouseExited(MouseEvent me) {
setForeground(standardColor);
setBorder(standardBorder);
}
public void mouseReleased(MouseEvent me) {}
public void mousePressed(MouseEvent me) {}
/** Set the color to the standard color. */
public void focusLost(FocusEvent fe) {
setForeground(standardColor);
setBorder(standardBorder);
}
/** Set the color to the hover color. */
public void focusGained(FocusEvent fe) {
setForeground(hoverColor);
setBorder(hoverBorder);
}
public static void main(String[] args) throws Exception {
JPanel p = new JPanel(new GridLayout(0,1));
File f = new File(".","LinkLabel.java");
/* Filename must be constructed with a canonical path in
order to successfully use Desktop.browse(URI)! */
f = new File(f.getCanonicalPath());
URI uriFile = f.toURI();
LinkLabel linkLabelFile = new LinkLabel(uriFile);
linkLabelFile.init();
p.add(linkLabelFile);
LinkLabel linkLabelWeb = new LinkLabel(
new URI("http://pscode.org/sscce.html"),
"SSCCE");
linkLabelWeb.setStandardColor(new Color(0,128,0));
linkLabelWeb.setHoverColor(new Color(222,128,0));
linkLabelWeb.init();
/* This shows a quirk of the LinkLabel class, the
size of the text field needs to be constrained to
get the underline to appear properly. */
p.add(linkLabelWeb);
LinkLabel linkLabelConstrain = new LinkLabel(
new URI("http://sdnshare.sun.com/"),
"SDN Share");
linkLabelConstrain.init();
/* ..and this shows one way to constrain the size
(appropriate for this layout).
Similar tricks can be used to ensure the underline does
not drop too far *below* the link (think BorderLayout
NORTH/SOUTH).
The same technique can also be nested further to produce
a NORTH+EAST packing (for example). */
JPanel labelConstrain = new JPanel(new BorderLayout());
labelConstrain.add( linkLabelConstrain, BorderLayout.EAST );
p.add(labelConstrain);
LinkLabel linkLabelNoUnderline = new LinkLabel(
new URI("http://java.net/"),
"java.net");
// another way to deal with the underline is to remove it
linkLabelNoUnderline.setUnderlineVisible(false);
// we can use the methods inherited from JTextField
linkLabelNoUnderline.
setHorizontalAlignment(JTextField.CENTER);
linkLabelNoUnderline.init();
p.add(linkLabelNoUnderline);
JOptionPane.showMessageDialog( null, p );
}
}

detect drag of jframe

Is there a way to detect the position of a JFrame while it's dragged?
The problem is that on MAX OS X the position of a window updates when you stop moving the mouse. I saw a tip of calculating the new position and setting the position of the window manual. But therefore i have to know the position of when i started dragging.
To make it a bit more clear, the JFrame is used to capture the screen, but when you move it around it doesn't update cause it still think it's at the old position. When you stop moving the dragging (but you can still hold the mouse button) then it updates.
import java.awt.event.ComponentListener;
import java.awt.Component;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
void setup() {
frame.addComponentListener(new ComponentListener()
{
public void componentMoved(ComponentEvent evt) {
Component c = (Component)evt.getSource();
println("moved "+frameCount);
}
public void componentShown(ComponentEvent evt) {}
public void componentResized(ComponentEvent evt) {}
public void componentHidden(ComponentEvent evt) {}
}
);
}
void draw() {
}
If what you mentioned regarding the update happening only when the window has stopped moving, and if knowing the position of when you started dragging can really solve the issue, then I see an option that you store the last location in some variable and update it each time you detect a move.
So declare a private variable in your JFrame class:
Point originLocation=new Point(0,0);
in your listener method you can:
public void componentMoved(ComponentEvent evt) {
Component c = (Component)evt.getSource();
Point currentLocationOnScreen=c.getLocationOnScreen();
// do your requirements here with the variables currentLocationOnScreen and originLocation
// update the originLocation variable for next occurrences of this method
originLocation=currentLocationOnScreen;
}

Java mouse motion anywhere on screen

I'm sure this is possible but all my searching is coming up blank.
In Java is it possible to register for a mouse motion event outside of a Java app? So if the mouse pointer moves anywhere on the screen I get a call back. An approximation is possible with polling MouseInfo.getPointerInfo but there must be a better way.
Thanks
To explain the use case:
It's just for a pet project but basically firing events when the mouse hits the edge of the screen. I was also thinking that different events could be fired if you try to push past the edge of the screen. And for this I thought a mouse motion listener might be more appropriate.
java.awt.event.MouseMotionListener is only going to give you information about mouse movement inside your application window. For events that occur outside that window, there is no way around MouseInfo.getPointerInfo. However, you could write a (potentially singleton) class that polls the pointer info in regular intervals and allows MouseMotionListeners to be added:
import java.awt.Component;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
* This class checks the position every #DELAY milliseconds and
* informs all registered MouseMotionListeners about position updates.
*/
public class MouseObserver {
/* the resolution of the mouse motion */
private static final int DELAY = 10;
private Component component;
private Timer timer;
private Set<MouseMotionListener> mouseMotionListeners;
protected MouseObserver(Component component) {
if (component == null) {
throw new IllegalArgumentException("Null component not allowed.");
}
this.component = component;
/* poll mouse coordinates at the given rate */
timer = new Timer(DELAY, new ActionListener() {
private Point lastPoint = MouseInfo.getPointerInfo().getLocation();
/* called every DELAY milliseconds to fetch the
* current mouse coordinates */
public synchronized void actionPerformed(ActionEvent e) {
Point point = MouseInfo.getPointerInfo().getLocation();
if (!point.equals(lastPoint)) {
fireMouseMotionEvent(point);
}
lastPoint = point;
}
});
mouseMotionListeners = new HashSet<MouseMotionListener>();
}
public Component getComponent() {
return component;
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
public void addMouseMotionListener(MouseMotionListener listener) {
synchronized (mouseMotionListeners) {
mouseMotionListeners.add(listener);
}
}
public void removeMouseMotionListener(MouseMotionListener listener) {
synchronized (mouseMotionListeners) {
mouseMotionListeners.remove(listener);
}
}
protected void fireMouseMotionEvent(Point point) {
synchronized (mouseMotionListeners) {
for (final MouseMotionListener listener : mouseMotionListeners) {
final MouseEvent event =
new MouseEvent(component, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(),
0, point.x, point.y, 0, false);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
listener.mouseMoved(event);
}
});
}
}
}
/* Testing the ovserver */
public static void main(String[] args) {
JFrame main = new JFrame("dummy...");
main.setSize(100,100);
main.setVisible(true);
MouseObserver mo = new MouseObserver(main);
mo.addMouseMotionListener(new MouseMotionListener() {
public void mouseMoved(MouseEvent e) {
System.out.println("mouse moved: " + e.getPoint());
}
public void mouseDragged(MouseEvent e) {
System.out.println("mouse dragged: " + e.getPoint());
}
});
mo.start();
}
}
Beware that there are some notable differences from your standard MouseMotionListener though:
You will only receive mouseMoved events, never mouseDragged events. That's because there is no way to receive information about clicks outside the main window.
For similar reasons, the modifiers of each MouseEvent will be always be 0.
The same goes for the values clickCount, popupTrigger, button
You will need to provide a dummy java.awt.Component that will be used as the (fake) source of the MouseEvents - null values are not allowed here.

Categories