libGDX - Button is set to down even if outside of bounds - java

I'm am trying to properly setup button clicks for my UI. I want my buttons to respond right after clicking them instead of releasing by using ClickListeners touchDown method.
I've created a class which creates and displays a table with text input:
public class InputBox {
public static float OFFSET = 20;
private Table table;
private TextField inputField;
private TextButton okButton;
private TextButton closeButton;
private String saveText;
private TextButtonStyle style;
private Skin skin;
public InputBox(Skin skin, float x, float y, float width, float height, boolean visible) {
this.skin = skin;
table = new Table();
// Creating a new style as suggested.
style = new TextButtonStyle();
style.up = skin.getDrawable("button_normal_up");
style.down = skin.getDrawable("button_normal_down");
style.font = skin.getFont("default");
inputField = new TextField("", skin);
okButton = new TextButton("Ok", style);
okButton.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (button != Buttons.LEFT) {
return false;
}
Game.resources.getSound("click_2").play();
table.setVisible(false);
if (inputField.getText().equals("")) {
saveText = null;
return false;
}
saveText = inputField.getText();
return true;
}
});
closeButton = new TextButton("Close", style);
closeButton.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (button != Buttons.LEFT) {
return false;
}
Game.resources.getSound("click_2").play();
saveText = null;
table.setVisible(false);
return true;
}
});
table.setVisible(visible);
table.setX(x);
table.setY(y);
table.setWidth(width);
table.setHeight(height);
table.add(inputField).colspan(2).center().width(width - OFFSET).expand().padRight(2);
table.row();
table.add(okButton).width(width / 2 - OFFSET / 2).right();
table.add(closeButton).width(width / 2 - OFFSET / 2).left();
table.pad(5);
}
public void setUnclicked() {
style.down = skin.getDrawable("button_normal_up");
// I think these two lines ar uneeded.
okButton.setStyle(style);
closeButton.setStyle(style);
}
public void setClicked() {
style.down = skin.getDrawable("button_normal_down");
// Same here.
okButton.setStyle(style);
closeButton.setStyle(style);
}
public void setText(String text) {
inputField.setText(text);
}
public String getSaveTextOnce() {
String temp = saveText;
saveText = null;
return temp;
}
public void setBackground(Drawable background) {
table.setBackground(background);
}
public boolean isVisible() {
return table.isVisible();
}
public void setVisible(boolean visible) {
table.setVisible(visible);
}
public Table getTable() {
return table;
}
}
The table is being set to visible after clicking a different button:
// Save map button.
saveMap = new ImageButton(new ImageButtonStyle());
saveMap.getStyle().imageUp = uiSkin.getDrawable("save");
saveMap.getStyle().up = uiSkin.getDrawable("button_flat_up");
saveMap.getStyle().down = uiSkin.getDrawable("button_flat_down");
saveMap.addListener(new ClickListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (button != Buttons.LEFT) {
return false;
}
Game.resources.getSound("click_2").play();
if (saveBox.isVisible()) {
saveBox.setVisible(false);
saveBox.setUnclicked();
return false;
}
saveBox.setVisible(true);
saveBox.setClicked();
return true;
}
});
The entire class for the saveMap button: http://pastebin.com/62ZGfcch
However, if I close the table by clicking the "ok" or "close" button and click and hold the mouse over the show table button, the table reappears with last clicked button being held down.
This video illustrates whats happening:
https://www.youtube.com/watch?v=Jf3WzU8G4dE&feature=youtu.be
If I move the mouse while holding it down, the last clicked button on the table resets to its normal state.

First i would recommend you to rather use a TextButtonStyle instance for setting the style of the buttons rather than a Skin instance.
You could somehow get the TextButton's references to the saveMap.addListener anonymous inner class. Then you could manualy set the style of the Ok and Cancel TextButton's, something like this:
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Game.resources.getSound("click_2").play();
if (saveBox.isVisible()) {
saveBox.setVisible(false);
okButtonReference.setStyle(unclickedTextButtonStyle) // Not-clicked TextButtonStyle as parameter
cancelButtonReference.setStyle(unclickedTextButtonStyle) // Not clicked TextButtonStyle as parameter.
return false;
}
saveBox.setVisible(true);
return true;
}
By forcing the TextButton to change it's TextButtonStyle by calling setStyle() you can be confident that the button will change.
Also i noticed that you are not calling the debug() method on the Table object. This is not necessary but it is advisable:
table.add(inputField).colspan(2).center().width(width - OFFSET).expand().padRight(2);
table.row();
table.add(okButton).width(width / 2 - OFFSET / 2).right();
table.add(closeButton).width(width / 2 - OFFSET / 2).left();
table.pad(5);
table.debug();

After more fiddling I found out that the way I setup my games InputProcessor was causing this issue. I did not handle the touchUp event properly.
Game.inputs.addProcessor(new InputProcessor() {
...
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
releasedButton = -1;
if (UI.isOver()) {
return false;
}
if (button == Buttons.LEFT) {
releasedButton = Buttons.LEFT;
}
if (button == Buttons.RIGHT) {
releasedButton = Buttons.RIGHT;
}
return true; // <--- setting this to false fixes the issue
}
});

Related

Passing static Method to a button factory (Java)

I am coding a little Plugin for Eclipse (using SWT), which creates a view with a couple of buttons. In order not to produce redundant code I want to create some kind of factory method to create my buttons for me. The call would be something like:
Button button0 = createButton(new Button(parent, SWT.PUSH), "Test DB zurücksetzen", btnHight, btnWidth, new FormAttachment(0, 2), new FormAttachment(0,2));
My factory, so far, looks like this:
private Button createButton(Button buttonToCreate, String buttonText, int height, int width, FormAttachment left, FormAttachment top) {
buttonToCreate.setText(buttonText);
FormData formData = new FormData();
formData.height = height;
formData.width = width;
formData.left = left;
formData.top = top;
buttonToCreate.setLayoutData(formData);
buttonToCreate.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
Actions.editPropertys();
}
});
return buttonToCreate;
}
My Question is: How can I pass the Method of the Actions class I want to execute to the factory as a parameter?
You could convey it as a Runnable parameter of the method.
For example :
private Button createButton(Button buttonToCreate, String buttonText, int height, int width, FormAttachment left, FormAttachment top, Runnable actionOnSelection) {
// ...
buttonToCreate.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
actionOnSelection.run(); // change here
}
});
}
and invoke it :
Button button0 = createButton(new Button(parent, SWT.PUSH), "Test DB zurücksetzen", btnHight, btnWidth, new FormAttachment(0, 2), new FormAttachment(0,2),
Actions::editPropertys); // other change here

Breaking If statements.. Clicking a button once

I am trying to make a keyboard and everything works fine. I just want to break the if statement after each click to stop repetitiveness of the char. I don't want to use a Boolean because user can enter same character more than once. This is the image listener
a = new Image(new Texture("Sprites/Keyboard/a.png"));
a.addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
apressed = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
apressed= false;
}
});
And this is what i have in my update inside the activity or state.
#Override
public void handleInput() {
if (keyboard.apressed) {
builder.append('A');
currentWord = builder.toString();
//break; here doesn't work. says its outside the loop.
}
}
So in theory this is what i want but can't use because im guessing its to much work for every char?
#Override
public void handleInput() {
if (keyboard.apressed) {
builder.append('A');
currentWord = builder.toString();
try {
TimeUnit.MILLISECONDS.sleep(400);
} catch (Exception e) {
System.out.println("error");
}
}
any ideas? thanks in advance.
I made my own keyboard as well using LibGDX TextButtons. Since you are using images and not text, you could use the ImageButton instead. I then used the ChangeListener with the changed() method because it only triggers after pressing and releasing the button, which avoids repetitive characters while the button is being pressed.
keyButton.addCaptureListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor){
// key logic here

Override method that toggles 'isSelected' in getListCellRendererComponent

I would like to make my own method that controles when a component is 'isSelected'.
I have a JList containing multiple JPanel. The constructing class of the JPanel extends ListCellRenderer<>.
To show that one of the JList-component (the JPanels) is selected i use;
#Override
public Component getListCellRendererComponent(..., boolean isSelected, ...) {
if(isSelected){
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
return this;
}
I would like a method that keeps a selected item 'selected' eventhough I choose to select another. I understand this can be done by holding down CTRL, but .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); does not quite do the trick. I would rather like to select multiple by clicking on them, and deselect by clicking on them.
For this i have worked with the ListSelectionMode, but i cant find a way.
When done the above I would like to implement a method that only selects a component in the list when clicked in a certain area (instead of the whole component which is preset). I have made this method, which returns true if the correct area is clicked, else false. But since I cant figure out how to override the mouseevent that makes the components 'isSelected' this has been tricky.
Here is the code for the method I would like to override the 'isSelected' method;
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent evt) {
if(ActionHandler.mouseClickedPrebuild(evt.getPoint())){
//This code runs if that special place is clicked!
//So now the component should be 'isSelected' or
//deselected if it already was 'isSelected'.
}
}
});
This code is in the constructor of my JList
And the mouseClickedPrebuild method;
public static boolean mouseClickedPrebuild(Point point) {
int index = theJList.locationToIndex(point);
Rectangle bounds = theJList.getCellBounds(index,index);
Point p = bounds.getLocation();
return ( ... long list of greater than & less than ...);
//This gives the certain area which is accepted to return true
I solved the issue!
So I get my view showing by running this line;
// UI Class JScrollPane Custom JList
UIConstructor.listview.setViewportView(new ListView( -insert ArrayList here- ));
Here is my ListView. The custom DefaultListSelectionModel I used to solve my problem was posted by #FuryComptuers right here;
JList - deselect when clicking an already selected item
I had to make a few changes to the code, since the two methods in the selectionModel will run before my mouseevent. I saved the variabels staticly, so instead of running the code in setSelectionInterval I did it inside my mousePressed.
I then could add the boolean isSelected which returns true, if a curtain area within a specific list element is clicked.
public class ListViewd extends JList {
static boolean isSelected;
static Point point;
static boolean gS = false;
static int in0;
static int in1;
#Override
public Dimension getPreferredScrollableViewportSize() {
Dimension size = super.getPreferredScrollableViewportSize();
size.setSize(new Dimension(0,0));
return size;
}
public ListView(ArrayList<System> items) {
DefaultListModel<System> list = new DefaultListModel<System>();
for (System item : items) {
list.addElement(item);
}
this.setSelectionModel(new DefaultListSelectionModel() {
boolean gestureStarted = false;
#Override
public void setSelectionInterval(int index0, int index1) {
gS = gestureStarted;
in0 = index0;
in1 = index1;
gestureStarted = true;
}
#Override
public void setValueIsAdjusting(boolean isAdjusting) {
if (!isAdjusting) {
gestureStarted = false;
}
}
});
ListSelectionModel selectionModel = this.getSelectionModel();
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
point = e.getPoint();
isSelected = ActionHandler.mouseClickedPrebuild(point);
if(!gS && isSelected){
if (isSelectedIndex(in0)) {
selectionModel.removeSelectionInterval(in0, in1);
} else {
selectionModel.addSelectionInterval(in0, in1);
}
}
}
});
setModel(list);
setCellRenderer(new ListModelPrebuild());
}

Libgdx error clickListener

I have 5 button and a want each button can't print number 1,2,3,4,5. but each button only print "5". Is there any wrong with my code? Or its bug on libgdx? I use libgdx v1.2.0
for (Integer i = 1; i <=5 ; i++){
tabeldalam=new Table(skin);
tabeldalam.row();
tabeldalam.add(new Label("GAmbar :", skin)).height(100).width(100);
tabeldalam.row();
tabeldalam.add(new Label("Harga",skin)).height(30).width(100);
tabeldalam.row();
TextButton nextbutton = new TextButton("Beli",skin);
nextbutton.setWidth(100);
nextbutton.setHeight(20);
nextbutton.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
beli(i);
}
});
tabeldalam.add(nextbutton).height(20).width(100);
tabelLuar= new Table(skin);
tabelLuar.add(tabeldalam).width(100).height(150);
}
private void beli(Integer i){
text2.setText(i.toString());
}
Use int instead of Integer for your for loop. All of your click listeners are referencing the same instance of Integer because it is an object and not a primitive.
For code non-ambiguity I would copy the variable to a final int variable and use that for the click listener so it is absolutely clear that a separate int is used for each.
final int index = i;
...
//use index in the ClickListener instead of i
try this simple example:
...// Change in your Code addListener for this:
nextbutton.addListener(new ClickListenerOverflow(i) {
#Override
public void clicked(InputEvent event, float x, float y) {
beli(n);
}
});
...//
Add this code inside of your Class:
private class ClickListenerOverflow extends ClickListener{
int n;
public ClickListenerOverflow(int n){
this.n = n;
}
}
when you click call beli (i), i then its value is 5, it is the latter who won the for.

Android - AndEngine Apply Force

I'm using AndEngine and Box2d in android application.
What do I have to do so that when pushing the "leftArrow" and "rightArrow" buttons, the player doesn't start moving too fast because of the too frequent call of the "Update Handler" method? I want the player to move constantly with the same speed.
//same for leftArrow
Sprite rightArrow = new Sprite(...) {
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY) {
if(pSceneTouchEvent.isActionDown()) {
goRight = true;
}
else if(pSceneTouchEvent.isActionUp()) {
goRight = false;
}
return true;
}
};
private IUpdateHandler UpdateHandler = new IUpdateHandler(){
#Override
public void onUpdate(float pSecondsElapsed) {
if(goLeft) {
playerBody.applyForce(-50, 0, body.getWorldCenter().x, body.getWorldCenter().y);
}
if(goRight){
playerBody.applyForce(50, 0, body.getWorldCenter().x, body.getWorldCenter().y);
}
}
};
use setLinearVelocity instead of applyForce. It should work

Categories

Resources