How to use touchup and touchDown with buttons - button

I have 3 buttons and i am trying to do some stuff on touchup and touchdown,i read many stuff in stackoverflow but its confusing i tried
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if(button1.getX()==screenX&&button1.getY()==screenY) {
Gdx.app.log("button", "touchdown");
}
return true;
}
i also tried hit condition too and don't know right way to use it.plz help me with any suggestion

I don't understand your question. You can add a listener to your button which can catch the touchdown / touchup / checked state of a button:
Button playButton = new Button();
playButton.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
return true;
}
});
Have a look at the InputListener API, to find an explanation what these states are. For example the touchdown method:
"Called when a mouse button or a finger touch goes down on the actor. If true is returned, this listener will receive all touchDragged and touchUp events, even those not over this actor, until touchUp is received. Also when true is returned, the event is handled}."
You can also set different Button images for these states: Link
Create one InputListener and attach it to each of the three buttons. When you receive for example a touchDown, you can use the event parameter to get the listenerActor and check which button was used:
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (event.getListenerActor().equals(playButton)) {
}
}
Haven't tested it, but it should work:
public class Example {
private Button button1;
private Button button2;
private Button button3;
public Example() {
MyListener listener = new MyListener();
// create the buttons...
button1.addListener(listener);
button2.addListener(listener);
button3.addListener(listener);
}
private class MyListener extends InputListener {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (event.getListenerActor().equals(button1)) {
Gdx.app.log("Example", "button 1 touchdown");
} else if (event.getListenerActor().equals(button2)) {
Gdx.app.log("Example", "button 2 touchdown");
} else if (event.getListenerActor().equals(button3)) {
Gdx.app.log("Example", "button 3 touchdown");
}
return super.touchDown(event, x, y, pointer, button);
}
}
}

if your using input processor , you have to set the input processor to the class . this can be done by the follwing code.
//in your create method
Gdx.input.setInputProcessor(this);

Related

How to catch a ONE click of the button in libgdx?

The button counts down clicks several times, but i need only one click. How can i catch only ONE click.
I was trying InputListener, EventListener, ChangeListener and ClickListener. Or is that not the problem?
Please, help me.
Look.addCaptureListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
touched=true;
}
});
if(!Gdx.input.isTouched()) {
OpenActions.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
System.out.println("X:" + x + " Y:" + y);
return true;
}
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
System.out.println("touchup");
}
});
}
As you see - i tried to catch only one click without the possibility to catch another one. But i failed.
I was added a listener to the render()(the cyclical method)... It was a mistake. I moved a listener to create(), then my problem was gone.

How to use setOnAction event on javafx

I would like to validate if a textfield is empty or not using javafx.
I am confused of event handlers. I want to confirm :
- whether there are many ways to use setOnAction :
submit.setOnAction((new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
System.out.println("Hello World");
}
}));
or
submit.setOnAction(e -> handle(e));
what is the difference between these two choices?
whether the second choice can not use the ActionEvent
submit.setOnAction(e -> handle());
but then what is the purpose of defining e?
I would like to validate textfields in my application.
public class AppGUI extends Application{
public static void main(String[] args)
{
launch();
}
public void start(Stage topView)
{
createUI(topView);
}
private void createUI(Stage topView)
{
TextField name = TextField();
Button submit = new Button("Submit");
submit.setOnAction(e -> validate());
}
private boolean validate()
{
// if textfield is empty, return false. else, return true.
}
I am lost here. Is it okay if the e in setOnAction is not used in validate? How do I pass the value of textfield to validate()? is making the textfields private variables the only way? (because I have so many text fields I wonder if its a good option).
in createUI method, how do i say if validate() returns false, show error message and if true, do something else?
Thank you and sorry for bothering
what is the difference between these two choices?
In second option lambdas are used (appeared since Java 8)
but then what is the purpose of defining e?
For a button your method have a signature like this setOnAction(EventHandler<ActionEvent> handler) You should see EventHandler tutorials and an ActionEvent javadoc. For instance, from e you can get the object on which the Event initially occurred this way e.getSource()
It is ok if you don't use e in validate.
To pass the value of textfield your method should have signature like this
boolean validate(String text);
Code example:
private void createUI(Stage topView){
TextField name = TextField();
Button submit = new Button("Submit");
submit.setOnAction(e -> {
boolean validated = validate(name.getText());
if(validated) System.out.println("validated");
}
}
private boolean validate(String text){
return text != null && !text.isEmpty();
}

How do I automatically trigger enter key in Javafx

Nowadays I am working on raspberry pi and I write some programs in java , javafx platforms.I just would like to inform you that I am simply beginner on javafx.
According to that I just would like to trigger ENTER key after changing my textfield.Working principle of my program is like this;
1)I have created one masterform fxml and it is directing all other pages with one textfield.
2)I created main method that let me to use keyboard to enter some specific String values to assign them to textfield for page alteration.
3)I have a bridge java page, it includes global variables to use everywhere in project.So Firstly I set value from keyboard to these global variables.These global variables are created as stringproperty for adding actionlistener for any change.
4)Then I set these global variables to textfield.
5)Textfield indicates relevant values from keyboard.But Unfortunately I can not forward the pages without pressing to enter key.In this case ı would like to trigger this textfield.But unfortunately ı have no idea how to trigger texfield without pressing enter key.Therefore I decided to make auto trigger to enter key for this textfield.
I simply used robot method;
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
But it didn't work.Because After I set the global variable to textfield for first time.It does not define the value of the textfield is changed.It determines after pressing the enter key.
So how can I trigger this textfield after getting value of my global variables.I would like to pass how to set pages, I will show you how my program works.
Example of my code is;
Main method
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
for (String strBarcode = scanner.nextLine(); !strBarcode.isEmpty();
strBarcode = scanner.nextLine()) {
if (strBarcode.equals("distribution")){
Global.G_MOD.set("distribution");
System.out.println(Global.G_MOD.get());
}
}}
GlobalVariables.java(bridge page)
public class Global{
public static StringProperty G_MOD = new SimpleStringProperty("");
}
My MasterController Page for javafx
public class masterformController implements Initializable {
#FXML
public TextField tbxBarcode;
#FXML
void onchangetbxBarcode(ActionEvent event) {
if(Global.G_MOD.get().equals("distribution")){
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/puttolightfx/fxml/page1.fxml"));
Parent rootpage1 = (Parent)loader.load();
pnPages.getChildren().clear();
pnPages.getChildren().add(rootpage1);
} catch (IOException ex) {
Logger.getLogger(masterformController.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
Global.G_MOD.addListener(new ChangeListener(){
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
String Newvalue = (String)newValue;
tbxBarcode.setText(Global.G_MOD.get());}
});
}
}
So Everything is working, just I have to trigger textfield when the global value : Global.G_MOD is indicated on texfield.Then it will pass to another page according to global value of Global.G_MOD : "distribution".
SOLUTION(SOLVED):
I solved my problem using thread on listener of the textfield.I gave up to trigger enter key automatically and focused on textfield change.
I simply decided to use thread to change .fxml pages in textfield listener.
Platform.runLater(new Runnable() {
#Override
public void run() {
//if you change the UI, do it here !
}
});
EDITED CODE :
tbxBarcode.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
String Newvalue=(String)newValue;
System.out.println(tbxBarcode.getText());
Platform.runLater(new Runnable() {
#Override
public void run() {
if(Global.G_MOD.get().equals("distribution")){
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/puttolightfx/fxml/page1.fxml"));
Parent rootpage1 = (Parent)loader.load();
pnPages.getChildren().clear();
pnPages.getChildren().add(rootpage1);
} catch (IOException ex) {
Logger.getLogger(masterformController.class.getName()).log(Level.SEVERE, null, ex);
}
}
// }
}
});
});
Try using
textField.fireEvent(new KeyEvent(KeyEvent.KEY_PRESSED, "", "", KeyCode.ENTER, true, true, true, true));
According to the docs
public KeyEvent(EventType<KeyEvent> eventType,
String character,
String text,
KeyCode code,
boolean shiftDown,
boolean controlDown,
boolean altDown,
boolean metaDown)
Constructs new KeyEvent event with null source and target and KeyCode object directly specified.
Parameters:
eventType - The type of the event.
character - The character or sequence of characters associated with the event
text - A String describing the key code
code - The integer key code
shiftDown - true if shift modifier was pressed.
controlDown - true if control modifier was pressed.
altDown - true if alt modifier was pressed.
metaDown - true if meta modifier was pressed.
Since:
JavaFX 8.0
You can refer https://docs.oracle.com/javase/8/javafx/api/javafx/scene/input/KeyEvent.html
Edit 1
You need to identify the moment when Enter key event must be triggered.
For example:
If your textfield allows a limited number of characters, then you can add the above mentioned code in the following way:
txtField.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (newValue.length()>30) {
txtField.setText(oldValue);
txtField.fireEvent(new KeyEvent(KeyEvent.KEY_PRESSED, "", "", KeyCode.ENTER, true, true, true, true));
}
}
});
This is just an example. It can fire your event multiple times, so you need to write the code to fire the event just once.

NullPointerException at com.badlogic.gdx.graphics.g2d.TextureRegion.setRegion LIBGDX

I am getting null pointer exception when I try spawning an item(Mushroom) when the player collides with a particular coin(As in MARIO game). I have been following this tutorial but I want the inputs to be buttons and not the keys. I have created 4 buttons and added to the stage . The inputs are working perfectly . But I am getting exception when,
I simply add the buttons to the stage and the input is still using keys
I am not getting exception when,
I remove all the buttons from the code and the input is using keys.
Here is my code for adding buttons to the stage ,
public class PlayScreen implements Screen, InputProcessor
{
.......
private Array<Item> items;
private LinkedBlockingQueue<ItemDef> itemsToSpawn;
private TextureAtlas atlas = new TextureAtlas("move_sprites.pack"); //contains the mushroom as well as the player packed together
public PlayScreen(MyGame game) {
.............
stage = new Stage();
atlas = new TextureAtlas("ui/button_pack.pack");
skin = new Skin(atlas);
white = new BitmapFont(Gdx.files.internal("fonts/white.fnt"), false);
black = new BitmapFont(Gdx.files.internal("fonts/black.fnt"), false);
TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle();
textButtonStyle.up = skin.getDrawable("buttonin");
textButtonStyle.down = skin.getDrawable("buttonout");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.font = black;
buttonright = new TextButton("Right", textButtonStyle);
buttonleft = new TextButton("Left", textButtonStyle);
//table.setBounds(500, 5, 250, 150);
buttonleft.setPosition(350, 5);
buttonleft.setHeight(100);
buttonleft.setWidth(100);
buttonright.setPosition(100, 5);
buttonright.setHeight(100);
buttonright.setWidth(100);
buttonup = new TextButton("up", textButtonStyle);
buttonup.setPosition(600, 5);
buttonup.setHeight(100);
buttonup.setWidth(100);
stage.addActor(buttonup);
stage.addActor(buttonright);
stage.addActor(buttonleft);
Gdx.input.setInputProcessor(stage);
......
}
//create a new method
public void spawnItem(ItemDef idef)
{
itemsToSpawn.add(idef);
}
public void handleSpawingItems()
{
if (!itemsToSpawn.isEmpty()) {
ItemDef idef = itemsToSpawn.poll(); //poll is pop
if (idef.type == Mushroom.class) {
items.add(new Mushroom(this, idef.position.x, idef.position.y));
}
}
}
public void update(float dt) {
handleInput(dt);
handleSpawingItems();
........
}
//Giving inputs using buttons
public void handleInput(float dt)
{
if (gamehero.currentState != Hero.State.DEAD) {
buttonup.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
gamehero.heroBody.setLinearVelocity(0, 4f);
}
return true;
}
}
);
}
}
public void render(float delta)
{
......
update(delta);
stage.act();
stage.draw();
}
}
}
Mushroom Class..
public class Mushroom extends Item {
public Mushroom(PlayScreen screen, float x, float y) {
super(screen, x, y);
//mush is one of the sprite packed together using texture packer. Exception is thrown in the below line
setRegion(screen.getAtlas().findRegion("mush"), 0, 0, 16, 16);
velocity = new Vector2(0.7f, 0); //velocity of mushroom
}
I am triggering this mushroom when mario head collides with coin like below,
public class Coins extends InteractiveTileObject {
....
public void onHeadHit(Hero hero) {
if (object.getProperties().containsKey("mushroom")) {
Gdx.app.log("coins", "collision");
//Exception occurs in the below line too. When the collision occurs, spawnItem method is called in the main class
screen.spawnItem(new ItemDef(new Vector2(body.getPosition().x, body.getPosition().y + 16 / MyGame.PPM), Mushroom.class));
}
ItemDef Class,
public class ItemDef {
public Vector2 position;
public Class<?> type;
public ItemDef(Vector2 position, Class<?> type)
{
this.position = position;
this.type = type;
}
}
Exception occurs if I just add a button to my code and gave the input using keys. Problem lies in spawning the mushroom if I just add a button to my code. Its weird. Please help. I am a beginner . Thanks in advance
I found the cause for this Exception.
I have given the same name for 2 TextureAtlas while declaring,
private TextureAtlas atlas = new TextureAtlas("move_sprites.pack");
and the other,
atlas = new TextureAtlas("ui/button_pack.pack");
But I am referring the first TextureAtlas in other class. Since I have declared the TextureAtlas only once but used for two different packs, It threw null pointer exception as there was name conflict. Thanks for all your answers.

AspectJ capture button clicked

I want to know whether how to capture the button clicked with AspectJ and get its parameter (eg. button name). I think for having more generalized capturing with AspectJ, it shoudl be used MouseListener so it can capture other UI elements in general!
Example:
In a GUI example I have defined 2 buttons that take some actions
public JButton btn1 = new JButton("Test1");
public JButton btn2 = new JButton("Test2");
btn1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//take some actions
}
}
btn2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//take some actions
}
}
How to capture these buttons with AspectJ, and get their parameters (eg. name)?
It is possible. I have provided two examples. The first that prints out for every JButton that has an ActionListener. The other example only prints out if a specific buttons is clicked.
Prints the text for every JButton clicked with an ActionListener:
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent)")
public void buttonPointcut(ActionEvent actionEvent) {}
#Before("buttonPointcut(actionEvent)")
public void beforeButtonPointcut(ActionEvent actionEvent) {
if (actionEvent.getSource() instanceof JButton) {
JButton clickedButton = (JButton) actionEvent.getSource();
System.out.println("Button name: " + clickedButton.getText());
}
}
Prints the text for a specific JButton:
public static JButton j1;
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent) && if()")
public static boolean button1Pointcut(ActionEvent actionEvent) {
return (actionEvent.getSource() == j1);
}
#Before("button1Pointcut(actionEvent)")
public void beforeButton1Pointcut(ActionEvent actionEvent) {
// logic before the actionPerformed() method is executed for the j1 button..
}
UPDATED:
You can do this in many different ways. For example add your buttons to the aspect directly. But I prefere to use a enum object between (ButtonManager in this case), so the code does not know about the aspect. And since the ButtonManager is an enum object, it is easy for the aspect to retrieve values from it.
I just tested it with a Swing button class from Oracle and it works. In the Swing class:
b1 = new JButton("Disable middle button", leftButtonIcon);
ButtonManager.addJButton(b1);
AspectJ is extremely powerful when it comes to manipulating classes, but it can not weave advises into specific objects since objects is not created at the time of weaving. So you can only work with objects at runtime and that is why I have added the addJButton(..) method above. That enables the aspect to check the advised button against a list of registered buttons.
The ButtonManager class:
public enum ButtonManager {
;
private static Collection<JButton> buttonList = new LinkedList<JButton>();
public static void addJButton(JButton jButton) {
buttonList.add(jButton);
}
public static Collection<JButton> getButtonList() {
return buttonList;
}
}
Modified pointcut and advice to only print the name of the buttons registered in the ButtonManager:
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent) && if()")
public static boolean buttonListPointcut(ActionEvent actionEvent) {
Collection<JButton> buttonList = ButtonManager.getButtonList();
JButton registeredButton = null;
for (JButton jButton : buttonList) {
if (actionEvent.getSource() == jButton) {
registeredButton = jButton;
}
}
return registeredButton != null;
}
#Before("buttonListPointcut(actionEvent)")
public void beforeButtonListPointcut(ActionEvent actionEvent) {
JButton clickedButton = (JButton) actionEvent.getSource();
System.out.println("Registered button name: " + clickedButton.getText());
}
UPDATED 2
Okay, I believe I understand what you want. You want to listen to mouse events. That is possible. The downside is that you have to register all your GUI components that you want to listen for clicks with a mouse listener. It is not enough to register the JPanel of the JFrame with a MouseListener. So if you only have registered an ActionListener for your buttons, you also have to add a mouse listener.
I have created a quick solution that works for me. It only shows that it works. I have not tried to make the solution generic with many different GUI objects. But that should be quite easy to refactor in when you have got the basics to work.
In the Swing class:
private class MouseListener extends MouseInputAdapter {
public void mouseClicked(MouseEvent e) {}
}
In the init method of the Swing class:
MouseListener myListener = new MouseListener();
btn1.addMouseListener(myListener);
btn2.addMouseListener(myListener);
In the Aspect class:
#Pointcut("execution(* *.mouseClicked(*)) && args(mouseEvent)")
public void mouseEventPointcut(MouseEvent mouseEvent) {}
#Before("mouseEventPointcut(mouseEvent)")
public void beforeMouseEventPointcut(MouseEvent mouseEvent) {
if (mouseEvent.getSource() instanceof JButton) {
JButton clickedButton = (JButton) mouseEvent.getSource();
System.out.println("aspectJ --> mouseClicked: " + clickedButton.getText());
}
}
This results in the following output in the console:
aspectJ --> mouseClicked: Test1
I hope it helps!

Resources