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;
}
Related
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.
I am very new to Java, and I wanted to try to make a thing in BlueJ that requires BlueJ to know when the mouse is clicked, and to be able to determine the mouse's coordinates on the x,y plane.
In my class where I code, I have seen some imported class and things like Scanner and Graphics, so it might be something along those lines, but I am not sure.
I just mainly need
The thing to import (if it is a thing that needs to be imported)
How to make it tell if the mouse is clicked
How to make it be able to tell me the x, y position of the mouse when asked (like, what class method would I have to refer to to find this)
After I have that, I will work with that to try to make my program. Thank you!
EDIT: Upon request, here is my attempt
java.awt.event.MouseAdapter
public class main
{
MouseAdapter test = new MouseAdapter();
}
public void mouseMoved(test e)
{
System.out.println("hey your mouse moved");
}
I am clearly doing something horribly wrong
One way to achieve your goal would be to use java swing. The following code will print out a statement if the mouse is moved inside the created window:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame jFrame = new JFrame();
jFrame.setSize(720,480);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
jFrame.getContentPane().addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent mouseEvent) {
System.out.println("STUFF");
}
#Override
public void mouseMoved(MouseEvent mouseEvent) {
System.out.println("STUFF");
}
});
});
}
This is not an ideal solution but I hope it helps you to look in the right direciton.
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)
I have created the following simple Java Swing program which outputs a 3*3 square in the window every time the user clicks their mouse. The squares remain in the window even if the user clicks more than once. The program compiles and runs just fine, however, when one clicks in the window the square is drawn far below where the mouse pointer is. I've been racking my brain over this one for a while -- what can I change here to get the square to appear exactly with the pointer on each click? Many thanks for any help!
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class ClickCloud extends JComponent {
final ArrayList<Point2D> points = new ArrayList<Point2D>();
public void addPoint(Point2D a) {
points.add(a);
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < points.size(); i++) {
Point2D aPoint = points.get(i);
g2.draw(new Rectangle2D.Double(aPoint.getX(), aPoint.getY(), 3, 3));
}
}
public static void main(String[] args) {
final ClickCloud cloud = new ClickCloud();
JFrame aFrame = new JFrame();
class ClickListen implements MouseListener {
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
cloud.addPoint(arg0.getPoint());
cloud.repaint();
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
aFrame.setSize(500, 500);
aFrame.add(cloud);
aFrame.addMouseListener(new ClickListen());
aFrame.setVisible(true);
}
}
You're adding the MouseListener to the JFrame, but displaying the results in the JComponent and relative to the JComponent. So the location of the Point clicked will be relative to the JFrame's coordinates, but then displayed relative to the JComponent's coordinates which will shift things down by the distance of the title bar. Instead simply add the MouseListener to the same component that is responsible for displaying the results so that the display and clicking coordinates match:
aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
aFrame.setSize(500, 500);
aFrame.add(cloud);
//!! aFrame.addMouseListener(new ClickListen()); // !! Removed
cloud.addMouseListener(new ClickListen()); // !! added
aFrame.setVisible(true);
By the way: Thanks for creating and posting a decent SSCCE as this makes it so much easier to analyse and solve your problem.
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.