2016년 12월 13일 화요일

Button Images and Changing Buttons


Ok, this one seems to be a tough one for me.

I have 16 buttons, each with a specific image that have a white background. When a button is pressed, upon validation of the action, I turn the button green. If the action is invalid, I turn the button red. After 3 seconds, the default image returns.

I have everything working perfectly...except for one thing. I am unable to dynamically change the button name so that I can change the button image. As it stands, every button I press, changes Button1. How can I make my procedure call that does all the work use the button information that was pressed to select the button image change process?

If I didn't explain this well, please let me know.

--
You can't change the components names dynamically. Looks like you are taking a wrong approach to something that it's possible to do in MIT AI2.
Anyway you question is not clear. Please elaborate and post a screenshot of your blocks, so we can see what is wrong with your project.

-- 
Thanks, Italo, for the feedback. I redesigned my approach, and now a a similar, but different problem.

Basically,I have programmed Button5mph to call GetGPS, write data, play a sound, and set the flag variable SetGPSSucess to 1 for success or 0 for fail. When the call is transferred back to the button, I then change the button image from white to green for success or to red for fail. It works perfectly until I attempt to change the button back to white after a 3 second timer call. Then only sounds are made, no image changes.

Attached is the Blocks download.
blocks.png 표시 중
--
Move the blocks that sets the button back to white INSIDE the Clock Timer event. Also, right after those blocks, set the clock to disabled.

-- 
I had tried that earlier, and it did work. However, I have 16 buttons and would therefore need to create 16 timers, one for each button to change back to white. Which, ultimately, puts me back to my original problem, needing to pick a button name dynamically and then set the image to white.

-- 
instead of using a global variable SetGPSSuccess you might want to take a look into procedures with result http://appinventor.mit.edu/explore/ai2/support/blocks/procedures.html#return
see also chapter 21 here http://www.appinventor.org/book2
the result  in your case could be true or false

--
You don't need 16 timers. It can be done with just one clock.

If you need to allow the user to keep pressing buttons while there's a red button, then you can record the instant when an individual button turned red, save that instant in a list that has 16 items (one for each button).
Save the instant in the correct index, so if the 3rd button turns red, save the instant it turned in the item 3 of the list.
For this solution, you need to have the clock timer enabled all the time.
Inside the clock timer event, check each item of the list and if you find one that is not 0, that means that button is red right now. Compare the value (instant recorded) with the instant now and if it's greater than 3 seconds, turn that button white and change that item value to 0.

It sounds a little complicated, but it's actually easier that it looks.

-- 
The user does not need to keep pressing buttons while the procedure is active. Specifically, the user will press a button, capture the GPS and write it to the sdcard. Upon success, turn the button green for 3 seconds, If there is a failure, turn the button red for 3 seconds and then return to white. Once the procedure is complete, the user can press another button and repeat the process.

Even if I don't use the timer function, the 3rd image change for the button (from green or red back to white) fails the procedure. I am not seeing how a list will help me change the button for the 3rd time.

I does work when I use the timer and set the 3rd image change under the time. So, a separate timer for each button is the only way I see to change a static button. If I could say something like:

"Set <ButtonName> Join.Get SetMPH + Get "white.png".image" I would have it made.

I hope this explains it better.

--
In that case is even easier, but somehow you have to prevent the user from pressing another button while there's a red one, then.

See this example:

-- 
With your suggestion, I was actually able to locate and program a universal button, like the "set Button.---", except in this case, it actually controls the button image. I am including the blocks.
blocks.png 표시 중
-- 
Great! I can give you a couple of suggestion if you want:

1. Since the [SET ButtonClock TimerEnabled TO TRUE] block is repeated exactly in each Button.Click event, may be you can include it at the beggining of the procedure GetGPS, just to save some blocks space, unless there's another reason that I don't see to have it repeated in each click event.

2. You can create a list of your buttons and optimize your enabling and disabling procedures like in this image:
--
Actually, you can use just one procedure for setting the buttons enabled or disabled:
--
Love the ideas, Italo.

I've tried implementing them, but I keep getting a single error. It doesn't stop the program, just throws the error.

runtime error setting was expecting a button component but got a string instead

Not even sure what the error is or where it is. Any ideas?

--
It would really help if you provided a screenshot of your relevant blocks, so we can see what you are trying to do, and where the problem may be.

--
Yes, like Taifun said, post the blocks you are having problem with.
I think you might be using strings instead of the actual button block (the one you find at the bottom in that button blocks drawer) when creating the list of buttons.

--
Thank you, Gentlemen. I was actually able to locate the error and correct it. Turns out I was trying to initialize a global variable for a button...which, apparently, cannot be done with a button.

-- 


댓글 없음:

댓글 쓰기