Adding a circle object to pane after button is clicked (JAVA FX) - java

I am creating a game where the user can control the human object. However, I would like to add a circle object to the pane to indicate where the human has already travelled. In simpler terms, I would like to leave a trail indicating where the user has travelled.
I would like to know how to add a circle object to the pane every time I press a directional button.
Here is what I have:
//Button Action Event for up button
Up.setOnAction(new EventHandler <ActionEvent>() {
#Override
public void handle(ActionEvent e) {
//Move object Up
human.setLayoutY(human.getLayoutY()-80);
//Keep object within the boundaries
if(human.getLayoutY()<40) {
human.setLayoutY(human.getLayoutY()+80);
}
}
});

Related

How to check if left click is pressed after unpressing it from Robot class?

I'm making something like an auto clicker.
I would like to make it so that when the left mouse button is pressed, the auto clicker should turn on. When the button is released, the auto clicker should turn off.
Is there a way to check if the left mouse click (in real life) is pressed after calling the robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK) method?
You should implement MouseListener interface in your class then override these two methods : mousePressed and mouseReleased .
public void mousePressed(MouseEvent e) {
//do the auto click code here
}
public void mouseReleased(MouseEvent e) {
//turn off the auto click here
}
read this article

Waiting for a click input after a button press Java Fx

Im having some issues trying to wait for an input after clicking a button.
With my team, we are making a card game, in which cards attack one another, the problem is that i don't know how to, after a button is clicked, make the event handler wait for the user to click another button.
The code looks like this:
private Button attackingButton(){
Button b1 = new Button();
b1.setOnAction(new EventHandler<ActionEvent>()
{
public void handle(ActionEvent event){
//Here i want the user to press another button and, depending which one he
//pressed, asing a variable
Card aCard = //The card that the button pressed has inside
}
}
That's just it, you don't make the handler wait. Instead you change the behavior of the handler depending on the state of the object. If the object is in the "user has not pressed the first button yet" state, the handler does one thing. If the object is in the "user has previously pressed the first button", then the handler does something else. Your handler should query the state of the object's instance fields to determine this state.
e.g.,
b1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event){
// may need to use boolean fields or .equals(...) method......
if (someStateField == someValue) {
doBehavior1();
} else {
doBehavior2();
}
}
}

How to determine if the user clicked outside a particular JavaFX node?

I have a TextField, and I would like to do something if the user clicks anywhere that is not the TextField itself.
Apparently, the onMouseClicked event won't trigger if you don't click the node itself, so that wouldn't work.
Listening the focusedProperty may have been a good idea, but the problem is that almost the entirety of my application is not focus traversable, so in many cases clicking outside the textfield won't unfocus it, so the listener won't be notified.
The only thing left in my mind is to put an event filter on the scene itself, intercept mouse clicks, get the click coordinates and determine if they fall within the bounds of the textfield. I find this a little bit overkill and I may be missing something more obvious.
Is there another way to determine if the user clicked anywhere outside my TextField node?
The only thing left in my mind is to put an event filter on the scene itself, intercept mouse clicks, get the click coordinates and determine if they fall within the bounds of the textfield. I find this a little bit overkill and I may be missing something more obvious.
In fact I consider this your best option, but with a variation:
Use the PickResult provided by the MouseEvent to get the target Node and check, if it's in the hierarchy of the Node.
(This can be necessary, if the Node has children; e.g. a TextField also contains a Text element.)
In fact this seems to be the only option that cannot be broken by consuming the event somewhere in the scene graph.
Example
This moves the focus to the root pane in case the user clicks somewhere except the TextField.
public static boolean inHierarchy(Node node, Node potentialHierarchyElement) {
if (potentialHierarchyElement == null) {
return true;
}
while (node != null) {
if (node == potentialHierarchyElement) {
return true;
}
node = node.getParent();
}
return false;
}
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField();
textField.setMinSize(400, Region.USE_PREF_SIZE);
textField.setMaxWidth(400);
textField.setEditable(false);
textField.textProperty().bind(Bindings.when(textField.focusedProperty()).then("Got the Focus!").otherwise("Please give me the focus!"));
StackPane root = new StackPane();
root.getChildren().add(textField);
Scene scene = new Scene(root, 500, 200);
scene.addEventFilter(MouseEvent.MOUSE_CLICKED, evt -> {
if (!inHierarchy(evt.getPickResult().getIntersectedNode(), textField)) {
root.requestFocus();
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
Assume you top level container of your app is Pane. You can apply mouse click event to that pane and inside it handle the mouse click event for the textfield. So this way, if the user clicks on the textfield or clicks somewhere else both events will be notified. Here's is the sample code.
Pane.setOnMouseClicked((MouseEvent evt) -> {
System.out.println("Click outside textfield");
textField.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("textfield clicked");
}
});
});
If you have any other controls in that Pane. This mouse click wont interfere with them, it will be only called when you click directly on the pane.

Creating my own event for right button click

I have some component on the frame and I need it to respond just on right button click. I have to use my own event. Should I extend MouseEvent? How can I separate right button click from others in my event?
No, you wouldn't extend MouseEvent, rather you would use MouseEvent.
If this is a Swing GUI you could add a MouseListener to the component and then in the MouseListener's mousePressed method, get the MouseEvent object that is passed in to the method, get its modifiersEx and then check if right click has been pressed:
public void mousePressed(MouseEvent mEvt) {
if ((mEvt.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) != 0) {
// right button has been pressed
}
}
The MouseEvent class has a method that allows you to check which mouse button was used. It's called getButton and it returns an int value that you can compare to one of predefined values
On top of that, there's a convenient class called SwingUtilities, which provides a nice layer of abstraction over the use of these fields. Here's a method you'll find particularly interesting: isRightMouseButton
In other words, you don't need to create your own MouseEvent, a MouseListener implementation will suffice. Here's an example of inline implementation, irrelevant details excluded.
new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {
if(SwingUtilities.isRightMouseButton(e)){
//do what you want on right click
}
}
// other methods required by the interface
};

How to make JComboBox selected item not changed when scrolling through its popuplist using keyboard

I have a JComboBox component in the panel and ItemListener attached to it. But it gets fired after every up/down keypress (when scrolling though opened popup list). I want to change the selected value after the user accepts selection by pressing for example Enter key.
This is not a case when using mouse. When I move mouse over the combobox's list the highlight follows mouse pointer, but selected item is not changed until I press the mouse button. I would like to have the same behavior for keyboard, i.e. moving highlight via up/down arrow does not change selected item, but pressing Enter does.
I believe you should be able to do:
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
after you have created your comboBox instance to get this functionality
In Java 8 they have fixed this behaviour, but only trigger if u set one UI property
UIManager.getLookAndFeelDefaults().put("ComboBox.noActionOnKeyNavigation", true);
the JComboBox.isTableCellEditor method works for arrow movement through the list, but does not work for type-ahead supported by the KeySelectionManager. i.e. you still get ActionEvents for every non-navigation key the user types, as the JComboBox interprets those characters for searching though the model to move to (or move close to) the user's intended selection.
this solution has a drawback in that it changes the action command for mouse clicks, which was a OK compromise for me because the the flow of the GUI forces the user to change the focus away from the combo box
I ended up making a special KeyListener, that relys on changing the combo box's default action command from comboBoxChanged to comboBoxMovement. Here's the line of code I need after my combo box is all initialized:
setExplicitSelectionManager(myComboBox);
... and here is the method and its contained class that do all the work:
private void setExplicitSelectionManager(JComboBox comboBox) {
class ExplicitSelectionManager implements KeyListener, FocusListener {
private JComboBox src;
private KeyListener superKeyListener;
ExplicitSelectionManager(JComboBox src) {
this.src = src;
// we like what the default key listener does, but not the action command
// it uses for ActionEvents it fires for plain text type-ahead characters
this.superKeyListener = src.getKeyListeners()[0]; // we only have one
src.removeKeyListener(superKeyListener); // will be replace right away, below
}
#Override
public void keyTyped(KeyEvent e) {
// basic combo box has no code in keyTyped
}
#Override
public void keyPressed(KeyEvent e) {
// in the default JComboBox implementation, the KeySelectionManager is
// called from keyPressed. I'm fine with the implementation of
// the default, but I don't want it firing ActionEvents that will cause
// model updates
src.setActionCommand("comboBoxMovement");
this.superKeyListener.keyPressed(e);
src.setActionCommand("comboBoxChanged");
if (e.getKeyCode() == 10) {
src.setSelectedIndex(src.getSelectedIndex());
}
}
#Override
public void keyReleased(KeyEvent e) {
// basic combo box has no code in keyReleased
}
#Override
public void focusGained(FocusEvent e) {
}
#Override
// this will also give us the event we want, if the user decides to Tab out of
// the combo box, instead of hitting Enter
public void focusLost(FocusEvent e) {
src.setSelectedIndex(src.getSelectedIndex());
}
}
ExplicitSelectionManager newSelectionManager = new ExplicitSelectionManager(comboBox);
comboBox.addKeyListener(newSelectionManager);
comboBox.addFocusListener(newSelectionManager);
}
... and here's the action performed method
private void comboBoxActionPerformed(java.awt.event.ActionEvent evt) {
JComboBox source = (JComboBox) evt.getSource();
// "comboBoxChanged" is the default,
// so any normal JComboBox can also use this action listener
if (evt.getActionCommand().equals("comboBoxChanged")) {
updateModel(source.getName(), (String) source.getSelectedItem());
}
}
Its the expected behavior with the ItemListener. whenever the displayed value changes the event is fired. For your requirement use an ActionListener.

Categories

Resources