We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I want to get the value from the button when I press the button (but without using a function). Got two alternatives but none of them are good (most be a better way then using the if (mousePressed). How can I succed with this probably simple task. Guess i want to use some of these but I cant figure out how to implement them:
controlP5.Button : boolean isPressed()
controlP5.Controller : boolean isMousePressed()
controlP5.Controller : Button onPress(CallbackListener)
Anyone can guide me getting value from button without using function?
import controlP5.*;
ControlP5 cp5;
void setup() {
size(400, 600);
cp5 = new ControlP5(this);
cp5.addButton("Button")
.setValue(1)
.setPosition(100, 100)
.setSize(200, 19)
;
}
void draw() {
background(255);
if (mousePressed) {
// alternative 1
println("\nalternative 1: " + cp5.getController("Button").getValue());
// alternative 2
println("alternative 2: " + cp5.isMouseOver(cp5.getController("Button")));
}
}
Answers
Anyone?
Hi, the easiest would be to add a function to your sketch that uses the same name as your button, see the example below. You can also browse through the examples that come with controlP5 to learn more about how controlP5 works and can be used.
Thanks for answer. For various reasons the function option doesnt work for me. (Got my reasons :-) ) I need to create something in draw ()
What about these different options:
Im a bit confused how to implement them though. Been looking for example but cant find any with these.
Not possible to create something in draw that says:
So here is the reason and the problem with a function in my case. Im adding and removing buttons. So as soon as I have added more buttons than I have functions the new button of course doesnt work. I need to loop through the buttons somehow!
How can I solve this? I guess it have to be without using a function:
ok, this example makes more sense of what you are looking for. Adding a callback function onPress for each controller will prevent you from manually adding functions for each button that is dynamically created. Below are 2 sketches that show the transition from your sketch to a more dynamic approach. The first sketch adds a callback listener to each button for onPress events. The second example uses an ArrayList to keep track of dynamically added and removed Buttons, the structure and logic of your sketch changes a bit, I have added comments into the code, please have a look.
sketch 1
sketch 2
Thanks! This solves my problem! Thankyou. I got som questions though, some things i dont understand. See my questions in CAPITALS in the sketch below. I put them here as well:
The returning object of function createButton() is being used as argument for List's add() method:
buttons.add( createButton("Button", 0, 0) );
Obviously,
void
is outta question there. We can't putvoid
in a List or anything else! ;;)Now some very important observations about how @sojamo had declared variable buttons: 8-X
ArrayList buttons = new ArrayList();
The way it is right now, we are free to add() anything ( but
void
or primitive types ;-) ) into the ArrayList referred to by buttons. ~:>It's almost anathema within Java community! >:) Proper way is to specify the generic type for the List:
Besides guaranteeing that only compatible Button object references goes into the List now, there's a nice boon of completely getting rid of
(cast)
operators when using get() methods and such: :-bdNo more
((Button)buttons.get(last)).remove();
Just
buttons.get(last).remove();
is enough! :bzDunno much about controlP5 library, but I bet onPress() method is a way to tell some Button instance which function to callback when it gets pressed.
More precisely that function's name is controlEvent(). Whatever is inside it is executed every time a CallbackEvent of such type is triggered over that Button.
At least before Java 8, we can't pass functions/methods/lambdas around directly.
We gotta 1st instantiate an interface/class that includes the function requested by the higher function.
So the high-order function onPress() requests a callback function parameter called controlEvent().
But instead we need to instantiate its CallbackListener interface and only then
@Override
controlEvent().And finally pass the resultant instance to method onPress() as its argument:
Such a hassle boilerplate! But that's the reality when using Java before version 8. :-& Or not using JS! :P
As an alternative, the CallbackListener along w/ its overridable controlEvent() method can be instantiated apart once, stored in some variable, and reused as onPress()'s argument over & over: :ar!
P.S.: Gonna leave question #3 to @sojamo! :-h
Thanks @GoToLoop for this in detail feedback to @Per's questions. Regarding questions 3, casting can indeed be avoid if the List would be generic and only accept Buttons as valid elements. sketch 2 does not use a generic ArrayList, hence accepts any element of type Object and even primitive types. As a consequence when requesting an element from this List you need to specify it's type if you want to run type specific operations on that element (which we want, we want to call a Button's remove function). So what happens here in sketch 2:
((Button)buttons.get(last)).remove();
first we get an element from ArrayList buttons using get(index) which returns the Object at that particular index, or position, in the List.
buttons.get(last)
the element we receive is of type Object, but we need a Button and since we know that we are dealing with an element of type Button (we only added Buttons previously) we need to cast the element from an Object to a Button.
((Button)buttons.get(last))
and finally we can call the remove() function on the Button which will remove that particular Button from cp5.
((Button)buttons.get(last)).remove()
Using a generic List (ArrayList) would make the code more explicit and would prevent casting. Maybe something for @Per to enhance the sketch 2 code?
Although it seems to accept any of those 8 Java primitive types, some wrapper object needs to be created so it can be stored in the List. That's called auto-boxing: :-B
http://docs.Oracle.com/javase/tutorial/java/data/autoboxing.html
Notice that add()'s signature is
boolean add(E e)
:http://docs.Oracle.com/javase/8/docs/api/java/util/List.html#add-E-
The type E represents the chosen generic datatype when a List is created.
It can't be a primitive type. Even the most permissive Object isn't a primitive type either!
Therefore
buttons.add(true)
would be auto-boxed asbuttons.add(Boolean.valueOf(true))
.buttons.add('+')
asbuttons.add(Character.valueOf('+'))
.buttons.add(100)
asbuttons.add(Integer.valueOf(100))
.buttons.add((short) 100)
asbuttons.add(Short.valueOf(100))
Thanks a lot for your answers!
Got a last question. I thought that would be easy to solve but stuck again :-)
Now first thing I now want to remove one of the buttons by clicking on them.
Im using
Collections.swap(buttons, (int)value, last);
from the java.util package to first swap place and put the button I pressed last in line in arraylist. And after that removing the button. But I probably need to get the indexnumber rather than the valuenumber for the button because in my example the index is getting OutOfBounds. How do I get the indexnr?And second I also want to change the position so the buttons move up when ever some is removed and are filling the gap.
Im really thankful for your help!
I was successful in removing the only Button I had in my own example by modifying callback instance btnAction a little in order to include Controller's remove() method: *-:)
But since you've got a List of Button instances too, you need to remove() them from that as well! :|
Lucky for us, the List's remove() method, besides being capable of removing any element by its index:
http://docs.Oracle.com/javase/8/docs/api/java/util/List.html#remove-int-
It is also overloaded to do the same by specifying the target Object itself: \m/
http://docs.Oracle.com/javase/8/docs/api/java/util/List.html#remove-java.lang.Object-
Although performance wise it is O(n) now rather than O(1). But who cares? :P
So you're gonna need some function to setPosition() all Button objects every time onPress() is triggered.
That is, besides issuing remove() for both the Button and List, you're gonna need to invoke some repositionButtons() code: *-:)
Thank you! I implemented your code as below
I used another solution for reposition the buttons with this code:
I also added buttons for adding buttons. I remove button by clicking on the button.
Heres the full sketch: