Why is my TextButton, from libgdx not responding on clicks?
I have a button, this button has a Listener, but it doesn't respond.
The button is showing, but it doesn't respond on mouse clicks.
public MyStage extends Stage {
...
next.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
Gdx.app.log(ApothecaryGame.LOG, "Pressed: Next button.");
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log( ApothecaryGame.LOG, "Released: Next button.");
super.touchUp( event, x, y, pointer, button );
nextPage();
}
} );
this.addActor(next);
}
Add a ClickListener to your button. It'll look something like this.
button.addListener(new ClickListener() {
public void clicked(InputEvent event, float x, float y) {
// Do something interesting here...
}
});
Also, make sure that you set the stage to be an input processor, otherwise it won't see the events.
Gdx.input.setInputProcessor(stage);
Related
I'm trying to create eventListner on each image (playIcon,pauseIcon) but its not working using touchUp and touchDown
here is my code:
TextureAtlas buttonsPlayPause = new TextureAtlas("uiii/uiii.pack");
skin.addRegions(buttonsPlayPause);
TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle();
textButtonStyle.font = font;
textButtonStyle.up = skin.getDrawable("pauseIcon");
textButtonStyle.checked = skin.getDrawable("playIcon");
TextButton button = new TextButton("", textButtonStyle);
button.setY(pauseY);
button.setX(Gdx.graphics.getWidth()/6);
button.setSize(150,150);
stage.addActor(button);
//pause/playAction
button.addListener(new ClickListener() {
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {resume();
}
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
pause();
return true;
}
});
What happens now is that the button listener behaves as 'istouched()' rather than 'justtouched()'. When I click the button, the game is paused but whenever I remove my finger, there's no pause, the game runs.
If I understand correctly, you want this button to toggle between Play and Pause, calling either pause() or resume() based on current state.
The Button class already has a built-in internal InputListener, so all you need is a ChangeListener to react to button presses:
//pause/playAction
button.addListener(new ChangeListener() {
#Override
public void changed (ChangeEvent event, Actor actor) {
if (button.isChecked())
resume();
else
play();
}
});
Make sure you mark it final when you first declare it, so the listener can reference it:
//...
final TextButton button = new TextButton("", textButtonStyle);
//...
I am making a game where you have two buttons to rotate the player, one to left and the other one to right. I'm using a TextButton in LibGDX. My problem is that the method clicked(InputEvent event, float x, float y) in ClickListener is only called once it's clicked. I want an event to be called repeatedly as long as it's held down. Here is my code:
TextButton btnLeft = new TextButton("<", styleButton);
TextButton btnRight = new TextButton(">", styleButton);
btnLeft.setSize(100, 100);
btnRight.setSize(100, 100);
btnLeft.setPosition(25, 25);
btnRight.setPosition(200, 25);
btnLeft.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
player.rotate(-1);
System.out.println("Left");
}
});
btnRight.addListener(new ClickListener() {
Override
public void clicked(InputEvent event, float x, float y) {
player.rotate(1);
System.out.println("Right");
}
});
stage.addActor(btnLeft);
stage.addActor(btnRight);
The listener is not good place to perform continuous actions since it is by definition asynchronous mechanism. The place to perform some action like this is render() method of Screen or act() method of actor.
Although you can use listener to check a state of actor (is it pressed or not) in this way:
//Global instance
ClickListener listenerLeft;
//show() method
...
listenerLeft= new ClickListener();
btnLeft.addListener(listenerLeft);
...
//render() method
...
if(listenerLeft.isPressed())
//perform turning left
...
The second option is to implement ClickListener's touchUp and touchDown methods to change some flag and then check it in render but it would not be doing anything new.
Worth to notice is than both ClickListener and DragListener have touchDragged method that is something about what you want but works only if the mouse/finger is moving when touching actor
listener = new DragListener(){
#Override
public void touchDragged(InputEvent event, float x, float y, int pointer)
{
System.out.println("Left");
}
};
Keeping touching is not an action - no action = nothing to listen
I want to use the exit() method in the InputListener to see wheter the cursor is inside the button or not.
Here is the explanation in the libGDX docs.
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor)
Called any time the mouse cursor or a finger touch is moved out of an actor.
But when I put my cursor on the button and then move it outside the button, the method is not called. I am testing it by a System.out.println("exited"); and I get nothing in the console.
EDIT:
LibGDX Version: Latest Stable Nightlies
InputListener implementation:
//This button class is a custom class to make button creation easier. This is the constructor.
public Button(Vector2 position, String packLocation, String text, Stage stage, BitmapFont font, Color color) {
//Removed buttonStyle creation etc. to shorten the code.
button = new TextButton(text, buttonStyle);
button.setPosition(position.x, position.y);
stage.addActor(button);
Gdx.input.setInputProcessor(stage);
pressed = false;
button.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
pressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
pressed = false;
}
#Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
System.out.println("exited");
}
});
}
EDIT:
Hovering over the button also does not change the texture of the button as I set it to like so:
buttonStyle.over = skin.getDrawable("over");
But clicking does.
After searching for a couple hours I finally found what was missing. stage.act(); had to be called in the render method. This both gave functionality to the texture change when we hover over the button and also the enter/exit methods in the InputListener.
I'm making a simple RTS game. I've created separate Stages for map and UI, and used scene2D Table class for side panel. The problem is, when i hover my side panel, if there is an actor (building) under panel at the moment, it fires its mouseover event. Click events work properly.
Here is my building class input listeners:
public class Building extends Actor {
addListener(new InputListener(){
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("Click");
return true;
}
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){
((Building)event.getTarget()).hover = true;
}
Here is my panel class listeners
public class SidePanel extends Table {
panelBg = new Image(skin,"side-panel");
addListener(new InputListener(){
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("Click");
return true;
}
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){
System.out.println("Enter");
}
});
addActor(panelBg);
}
}
Then side panel is added to UI class stage:
public class UI {
public UI(){
stage = new Stage();
sidePanel = new SidePanel();
stage.addActor(sidePanel);
Gdx.input.setInputProcessor(stage);
}
And finally i added UI to main class:
#Override
public void create () {
ui = new UI();
CP =new InputMultiplexer();
CP.addProcessor(ui.stage);
CP.addProcessor(gameStage);
Gdx.input.setInputProcessor(CP);
}
Not sure where the problem is, because click event works fine;
One quick solution would be to have your Building class check if the mouse was also over the SidePanel. For example, you could change your Building listener's enter method to something like this:
if (mouseIsOverSidePanel)
((Building)event.getTarget()).hover = true;
Your SidePanel listener's enter method can be something like this:
mouseIsOverSidePanel = true;
And your leave method in your SidePanel can be:
mouseIsOverSidePanel = false;
This is mostly pseudo code so it won't work without declaring the variables (obviously) but it should give you a basic idea of how to fix your problem.
I have the following problem in LibGDX. When you move over an Actor you get the enter event from the ClickListener and the exit event when you move out of the bounding box of the Actor. I keep a boolean mouseOver that tells me if the cursor is over an Actor with these events. But when you click on the Actor and after releasing the mouse, an exit event is given. So after releasing the mouse click, it is as if the cursor isn't over the Actor anymore, while it is.
How can I keep a correct state for the boolean mouseOver? In other words: how can I know if the mouse is over my Actor when a TouchUp event has occurred as in the above scenario.
You can override touchUp and set the boolean mouseOver to true there.
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button){
...
mouseOver = true;
}
The best hack I found so far is to look at the pointer arg in the exit and enter overrides and look if the mouse is clicked. I'm still looking for a cleaner solution though.
addListener(new ClickListener() {
#Override
public void enter(InputEvent event, float x, float y, int pointer,
Actor fromActor) {
mouseOver = pointer == -1 ? true : mouseOver;
super.enter(event, x, y, pointer, fromActor);
}
#Override
public void exit(InputEvent event, float x, float y, int pointer,
Actor toActor) {
mouseOver = pointer == -1 ? false : mouseOver;
super.exit(event, x, y, pointer, toActor);
}
}
Set mouseOver to false only if the Actor toActor of exit is not the actor you added the listener to:
myActor.addListener(new ClickListener() {
...
#Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
...
if (toActor != myActor) // and even myActor's children if it is a Group
mouseOver = false;
}
});