Making "toggle buttons" with LibGDX - java

I'm trying to make sort of toggle buttons with LibGDX, so I searched how I could do them, and I found the ToggleButton class, but I suppose it's old since I don't have it in the last build...
So I'm trying to do them this way:
final TextButton button = new TextButton(weapon.getName(), skin2, "buy");
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
if(button.isChecked()){
button.setChecked(false);
System.out.println("unchecked");
} else {
button.setChecked(true);
System.out.println("checked");
}
}
});
Actually, it keeps telling me unchecked, as if my button was always unchecked, so the setChecked method doesn't seems to word ...
I tried the toggle method, and it doesn't help at all, and I didn't found any other solution ...
So i was wondering if you had any idea of how I should do this !
Thanks for your help ! :)

The button is toggled automatically when clicked, you don't have to add another listener to do it manually.
So the reason it only prints "unchecked" is because the Button checks itself when clicked, and then your listener is called, which just unchecks it immediately.

Related

Why is my LibGDX ImageButton only being detected once?

I am making a game in Android Studio using LibGDX, and I am attempting to add a pause button to the top corner of the main game screen. My game has been pausing fine thus far, but I have only been pausing when a key was pressed. Now I want to add a button, and I got the button to render in the top right corner, but when I press it it only works once. The first time I press it, my game pauses fine. But every time I try and pause it after that, it doesn't work. I have used extensive log statements and debugging and have found out that after pressing it once, the Listener doesn't even detect the button being pressed at all, so I am lead to believe that is where my issue is.
This is how I create my button in my HUD class, which is the class that prints the score onscreen at all times:
TextureAtlas buttonAtlas = new TextureAtlas(Gdx.files.internal("Buttons.pack"));
Skin skin = new Skin();
skin.addRegions(buttonAtlas);
ImageButton.ImageButtonStyle style = new ImageButton.ImageButtonStyle();
style.imageUp = skin.getDrawable("PauseButton");
style.imageDown = skin.getDrawable("PauseButton");
style.imageChecked = skin.getDrawable("PauseButton");
button = new ImageButton(style);
I then added a Listener to check if the button is clicked:
button.addListener(new ClickListener()
{
#Override
public void clicked(InputEvent event, float x, float y)
{
Gdx.app.log("","Button was pressed");
pauseGame();
}
});
The method pauseGame() that is called after the Listener detects the button being clicked:
public void pauseGame()
{
Gdx.app.log("","Game should be pausing");
screen.pauseGame();
}
screen is a class called PlayScreen that is the main game screen for my game, and its pauseGame() method works perfectly. The game before you press the pause button is as follows(You can see the pause button in the top right corner, please excuse the graphics, they are simply placeholders until I make and add my own graphics):
Game before pause
In my main PlayScreen class, this is my pauseGame method:
public void pauseGame()
{
gamePaused = true;
if(music.isPlaying())
{
musicType = type.NORMAL;
music.pause();
}
else if(barrageMusic.isPlaying())
{
musicType = type.BARRAGE;
barrageMusic.pause();
}
createPauseWindow();
}
And then in my render method, I call another method called update. In this method, I update my viewport, my HUD, and create new enemies. This is the only method that stops being called when gamePaused is true. The rest of my rendering and other necessary updates still take place. I have been trying to fix this problem for a long time but no matter how many different ways I rewrite the code to pause the game or make different listeners, the pause button only works one time and then never again.
Have you ever tried with touchDown method?
It might works.
button.addListener(new ClickListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
pause();
event.handle();
return true;
}
});
And try to change to a global variable base, a variable that is checked inside your render method and if it is true call the pause method. That to avoid call complex actions like pause from a listener, something like this:
button.addListener(new ClickListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
pause = true;
event.handle();
return true;
}
});
...
public void render(){
if (pause == true){
pauseGame();
}
...
}
It simplifies your listener and let you find easily your error.

Why do keybindings stop working after pressing the corresponding button?

I'm creating a simple Calculator program using Java, Swing.
The keybindings work fine. Well... almost. I ran the software, pressed the number buttons and everything went well, as it should've. Then, I pressed some buttons using my mouse and still, everything is just fine up to this point.
The problem comes when, after pressing the buttons with my mouse the keybindings stop working.
Here's the code for pressing the number 0 (the code for the rest of the buttons are implemented in the same way).
actions[0] = new press0Action();
frame.getRootPane().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD0, 0), "0");
frame.getRootPane().getRootPane().getActionMap().put("0", actions[0]);
private class press0Action extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
buttons[0].doClick();
}
}
private void buttonPressed0() {
buttons[0].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Code goes here for pressin the button...
});
}
So why can't I use the keyboard after clicking on the buttons in the
GUI manually with a mouse?
How can I fix this problem?
Thank you for answering in advance! Feel free to add any suggestions for improvement.
P.S.: I've got a feeling it's something to do with the fact that I bound the keys to frame.getRootPane()
You registered your inputs for the root pane, and with no explicit condition. Instead try registering them for the entire window:
actions[0] = new press0Action();
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD0, 0), "0");
frame.getRootPane().getRootPane().getActionMap().put("0", actions[0]);
Note the alternate getInputMap with argument.

How to reduce the click area of an Button?

I have a gridview that is filled with buttons that looks like this:
right now if I click anywhere on the button, it will be pressed. But I want to the button to only be pressed when it's clicked in the light gray area, not the dark gray or white area on the top and left sides. I tried using setPadding(int,int,int,int) and setPaddingRelative(int,int,int,int) but neither of them makes any effect. How do I fix this?
Edit: the button is 50x50 and is already extended from the Button Class
Make a custom Button view inherit from Button class and override onDraw method with custom code to do that.
You can override touch methods to detect when button is pressed and get the x and y coords to remove cases when button must not be pressed.
Override onTouchEvent in your custom button:
#Override
public boolean onTouchEvent(MotionEvent event) {
if (isInGrayArea(event.getX(), event.getY())) {
return super.onTouchEvent(event);
}
return false;
}
event.getX() and event.getY() is pixels coordinates, you will need to convert them into dp, I suppose.

Event when window/stage lost focus

How can I run a piece of code (or more exactly: close the stage) when the JavaFX stage lost it's focus?
For example in Dropbox or Chrome: if you click the tray icon, a small window opens. If you click anywhere on the screen now, the window closes. Exactly this is the behaviour I want to create in my JavaFX application.
I searched a long time already for a solution, but couldn't find one...
So, I'm looking for something something like this:
stage.addEventHandler(EventType.FOCUS_LOST, new EventHandler() { /*...*/ } );
Thank you for helping me out!
Add a listener to stage.focusedProperty().
primaryStage.focusedProperty().addListener(new ChangeListener<Boolean>()
{
#Override
public void changed(ObservableValue<? extends Boolean> ov, Boolean onHidden, Boolean onShown)
{
<Your code here>
}
});

ImageButton doesn't seem to detect clicks (Scene2d.ui)

When trying to put a simple ImageButton on stage, It didn't seem to detect clicks.
ImageButton btnStart = new ImageButton(ButtonArt.UP, ButtonArt.DOWN));
// btnStart.setClickListener(new ClickListener() {
// #Override
// public void click(Actor a, float arg1, float arg2) {
// a.visible = false;
// }
// });
stage.addActor(btnStart);
ButtonArt.UP and ButtonArt.DOWN are TextureRegions, of each state.
Now when I click on the button, it doesn't change state! I also tried the above ClickListener (for testing), but it seemed that didn't work either.
In my render method I just call stage.act() and stage.render().
I also tried drawing the TextureRegions with SpriteBatch in my render method, and they are in fact different textures.
Am I doing something wrong?
You will need to set the stage as your inputprocessor:
Gdx.input.setInputProcessor(stage);
If you need to have multiple inputprocessors (e.g., you need clicks registered outside your scene), you will need to use an InputMultiplexer, like this:
InputMultiplexer plex = new InputMultiplexer();
plex.addProcessor(myOtherProcessor);
plex.addProcessor(stage);
Gdx.input.setInputProcessor(plex);

Categories

Resources