Get Mouse Position when pressing a character - java

I want to get the position of my mouse relative to the frame when I click a shortcut:
#Override
public void handle(KeyEvent keyEvent) {
if (keyEvent.isShortcutDown()) {
if (keyEvent.getCode() == KeyCode.P) {
//Code Here
}
}
}

When the KeyEvent fires, just get the pointer location using MouseInfo.
#Override
public void handle(KeyEvent keyEvent) {
if (keyEvent.isShortcutDown()) {
if (keyEvent.getCode() == KeyCode.P) {
//Code Here
Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
}
}
If you want to continuously track the mouse location, you should use a MouseMoved listener.

Hey here from five years in the future. Since JavaFX still doesn't have this feature for some reason, my solution was to subtract the X/Y position of the cursor's position on the screen (java.awt.MouseInfo) from the X/Y position of the stage. As an example for Y:
MouseInfo.getPointerInfo().getLocation().getY() - stage.getY()
It's not perfect, you'll have to optimize it a bit, but it's an actual solution (the first guy who answered seems to think the screen equals the stage...)

Related

JavaFX - TextArea, how to activate the textarea only on double click?

JavaFX 2.2 - JDK 1.8.0_121
I have a TextArea inside a rectangle which also happens to have a mouse listener. The problem is that when I click on the TextArea it consumes the event and the rectangle doesn't get the click.
Consider the following code for example:
Group g = new Group();
Rectangle rect = new Rectangle(100,100);
TextArea textArea = new TextArea("Test");
textArea.setTranslateX(rect.getX());
textArea.setTranslateY(rect.getY());
textArea.setMinWidth(rect.getWidth());
textArea.setMinHeight(rect.getHeight());
//Calling a method to add an onMouseClickedProperty() mouse listener to the rectangle
addMouseListener(rect)
g.getChildren().addAll(rect, textArea);
In the above case the TextArea takes as much space as the rectangle so when I click on it the onMouseClickedProperty() event gets consumed by the TextArea.
Is there a way to "disable" or "remove" the onMouseClickedProperty() from the TextArea and instead have it fired when a double click occurs? In hopes that the single mouse click will be consumed by the rectangle instead.
Thanks.
EDIT:
I found a solution that works, it's not perfect but it's much more appropriate than what it was discussed in the comments.
Since you can't prevent the TextArea from consuming the MOUSED_PRESSED event the only way to process an event before TextArea areas does is using event filters.
So using the example code from above where i call the method addMouseListener(rect) instead of using just a mouse listener I'm adding an event filter, and instead of adding that to the rectangular shape I add it to the group.
private void addMouseLisenter(Group group){
group.addEventFilter(MouseEvent.MOUSE_PRESSED,
new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
//Code here
}
});
}
This way both the group and the TextArea get the mouse click.
Note: If you want only the group to get the mouse click you can add event.consume().
I hope that helps someone in the future looking for something similar.
I am pretty sure you cannot get away from having to have the MouseListener unfortunately as that is primary class for all mouse events if you wanted the text area to react at all to mouse it has to have the listener.
as far as detecting double clicks there is another thread that contains the answer that you are seeking answered by Uluk Biy.
there is another answer on there proposed by mipa that might answer your question on detection of difference between single and double click however if the Nodes overlap each other.
EDIT
perhaps in this case it might be worth modifying mipa's answer, try adding this to your code (in applicable areas)
Integer clickCount = 0;
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
ScheduledFuture<?> scheduledFuture;
root.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
if (e.getButton().equals(MouseButton.PRIMARY) && clickCount < 1) {
scheduledFuture = executor.schedule(() -> clickAction(), 500, TimeUnit.MILLISECONDS);
}
clickCount += 1;
}
});
private void clickAction() {
if (clickCount == 1) {
//actions for single click
clickCount = 0;
} else if (clickCount > 1) {
//action for multiple clicks
clickCount = 0;
}
}
I found a much more appropriate solution than what was discussed, check EDIT in my question.

JavaFx multiple click events

I am creating a simple programme in javafx.
private void onClick(final Circle circle) {
circle.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
circle.setTranslateX(150.);
}
});
}
in the "public void start" i match th created circle with the method "onClick"
onClick(circle1);
this code move a circle to the right. How can I move it multiple times? I tried to create more methods analogically "onClick1" but it always respond just to the first click. I need to move it to the right with each click again.
Thank you for your time.
What about
circle.setTranslateX(circle.getTranslateX() + 150.0);

JavaFX: pause until animation finishes

I have a basic javafx program where a rectangle, simulating an elevator, must move up and down at the push of 'up' and 'down' buttons. I have successfully implemented the code to do this below:
public void handle(ActionEvent event) {
if (event.getSource() == upButton) {
//this should all be put into a 'slideNode' method
TranslateTransition translateTransition1 = new TranslateTransition(Duration.millis(500), theElevator);
translateTransition1.setByX(0);
translateTransition1.setByY(-50);
translateTransition1.setCycleCount(1);
translateTransition1.setAutoReverse(false);
translateTransition1.play();
}
}
The issue I need to solve is what happens when the elevator is partway through this motion and the button is pressed again - the elevator doesn't get the full motion it would have if I waited until it reached its first destination to press the button again!
I understand why this happens, but I'd like to know if there's a way to solve this. I imagine there should be some piece of the API similar to the following, which I can toss at the end of my code:
Pause pause = new Pause(Duration.millis(500));
pause.pause();
Does such a thing exist? How would you solve my problem?
You can disable the button while the TranslateTransition is playing:
public void handle(ActionEvent event) {
if (event.getSource() == upButton) {
//this should all be put into a 'slideNode' method
TranslateTransition translateTransition1 = new TranslateTransition(Duration.millis(500), theElevator);
translateTransition1.setByX(0);
translateTransition1.setByY(-50);
translateTransition1.setCycleCount(1);
translateTransition1.setAutoReverse(false);
translateTransition.statusProperty().addListener((obs, oldStatus, newStatus) ->
button.setDisable(newStatus==Animation.Status.RUNNING));
translateTransition1.play();
}
}

Set the Actor's sprite to the default

I'm having troubles with my Actor objects. When I click on the Button Actor, I want it to switch the Screen. When I do this, and I return to the last screen, the button that I clicked is still being hovered until I move my mouse again:
The code that I have for it:
// Load Game
textButtons[1].addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
// GameState is a subclass of Screen,
// GameStateManager helps me to manage my GameStates.
game.setGameState(GameStateManager.get("screenLoadGame"));
}
});
I've tried to "trick" it to fix this, by using the keyUp method, and doing the following:
#Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
int[] mousePos = { Gdx.input.getX(), Gdx.input.getY() };
Gdx.input.setCursorPosition(0, 0);
stage.act(1);
game.setGameState(GameStateManager.get("screenLoadGame"));
Gdx.input.setCursorPosition(mousePos[0], mousePos[1]);
}
But it doesn't work.
In the end, I want to be able to switch from one Screen back to the Main Menu Screen, and have the button as its default sprite. Is there a way to set an Actor's (Button's) Sprite?
NOTE: For the sprites (in the Json file) The up/down is how "Start New Game" shows it. The over sprite is when it has the gray background (like "Load Game").
Use a ChangeListener instead of a ClickListener. This will also allow your buttons to behave like buttons are expected to (if you click down and move your cursor off the button before releasing, it won't fire).
You can use a single ChangeListener for many buttons quite easily to keep your code tidy.
ChangeListener changeListener = new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
if (actor == startNewGameButton){
startNewGame();
} else if (actor == loadGameButton){
loadGame();
} else if (actor == creditsButton){
showCreditsScreen();
}
}
};
And then to add it to a button:
startNewGameButton.addListener(changeListener);

SWT - how to listen for mouse events, and retrieve their absolute position?

I am capturing mouse events inside of a shell with Composites by adding a Filter.
For now the events are positioned relative to the Composites, where they occure.
How can I retrieve MouseEvents absolute position?
(Absolute position is the position with 0,0 in the left uper corner of the display).
parentShell.getDisplay().addFilter(SWT.MouseDown, new Listener() {
#Override
public void handleEvent(Event event) {
//do not know the absolute position here
}
});
You can use Control#toDisplay(int, int) to convert any relative coordinates to display relative absolute values.
public void handleEvent(Event event) {
if (event.widget instanceof Control) {
Point absolutePos = ((Control) event.widget).toDisplay(event.x, event.y);
...
}
}
The above will work if the event you received is a mouse event, which it is in your example. You can also use Display#getCursorLocation() at any point to get absolute mouse location if you do not have a mouse event at hand.
Following saved my day:
System.out.println("Click: " + parentShell.getDisplay().getCursorLocation());
The only way I can think of would be to use the getLocation() method to get the relative position of the widget with the listener to its parent. Use the method recursively until you get to the top composite and/or the Display. Add in the relative coordinates of the event to get the absolute coordinates. But that's just a guess.
Try this:
parentShell.getDisplay().addFilter(SWT.MouseDown, new Listener() {
#Override
public void handleEvent(Event event) {
Point p = Display.getCurrent().map(null, null, event.x, event.y);
}
});

Categories