Error changing a button's .Enabled property in virtual screens

I am using the .Enabled property of a button (Delete) on virtual screens to force the user to perform a preliminary step (making a choice from a spinner) before he/she can use that button. The Delete button’s .Enabled property should only ever be set to true after choosing from the spinner control. After the immediate next step (clicking the Delete button or the Cancel button) the Delete button’s .Enabled property should be set back to false but that is NOT happening. The Delete button is stuck with .Enabled = true on the next pass through this process. It gets reset correctly to false on another pass.

I put a copy of the project in the gallery (ai2.appinventor.mit.edu/?galleryId=5500845576028160) and an image of the blocks below. To duplicate the problem:

  1. Click the Manage Waypoints> Group > Delete a Group command button on the Waypoint Management screen (vaWaypointManagement). The screen closes and the Delete Group screen (vaWMDeleteGroup) opens.
  2. When the Delete Group screen opens its Delete button should/must be disabled. Use the spinner to choose a group and then the Delete button’s .Enabled property will be set to true.
  3. At this point you can click either the Delete or Cancel buttons. The code in both buttons resets the Delete button’s .Enabled property to false and takes you back to the Manage Waypoints screen. When you click its Delete a Group button again, you return to the Delete Group screen but its Delete button’s .Enabled property is still set to true (an error).
  4. Repeat the process again (for example, by clicking Cancel) and the Delete Group’s Delete button will eventually reset to .Enabled = false as intended.

Note that it is the Delete Group’s spinner that sets the Delete Group’s Delete button to .Enabled = true. I have tried setting the Delete button’s .Enabled property to false in multiple places but can’t reset .Enabled to false on the first attempt.

What is causing this error and how do I fix it?

FYI: The exact same error occurs with the Delete button’s .Visible property. And the same error occurs if the Delete button is inside of an arrangement and I try to change the arrangement’s .Visible property instead of the button’s. That is, the button or the arrangement will still be visible when it shouldn’t be until you complete another pass through the cycle.

Tested your aia.

The button you indicate is made enabled = false on all three occasions.

Due to your settings, the user can never see that button when it is not enabled, except when the first Delete button is clicked.

Suggest you back track a bit, allow all your arrangements to remain visible, in order that you can check the logic for the enablements.

Hi TIMAI2,

Thanks for your quick response.

I just tried what you asked:

  1. I made all arrangements permanently visible. (This was not practical in my complete project. I’ve only shown a minimal excerpt.)
  2. I tried with the Delete button’s
    a) .Enabled = false in three places.
    b) .Enabled = false in two places (Delete and Cancel)
    c) .Enabled = false in one place (Delete a Group)

(FYI: My original code used solution c) but when that didn’t work I added b). The extra code is redundant, shouldn’t hurt, but didn’t fix the problem.)

The problem is still present in all three cases; however, I did discover something new. Both the Delete and the Cancel button correctly set .Enabled to false. It’s clicking the Delete a Group button that is resetting .Enabled back to true.

I added a notifier in the spinner .AfterSelecting code. I didn’t realize that that event fires when the Delete a Group button .Click code (buttonWMMenuGroupDelete.Click) reaches the spinner .SelectionIndex = 1 line. The spinner code does set the Delete button’s .Enabled = true but the very next code line sets it back to false which is what I want. Here’s the clincher: When does the spinner’s .AfterSelecting event get serviced? Now I suspect that the Delete a Group’s .Click code is finishing and then AFTERWARD the spinner’s .AfterSelecting code is running. That would leave the Delete button set to .Enabled = false. Does that sound correct?

If so, I learned two things:

  1. A call to a spinner’s .SelectionIndex will fire the spinner’s .AfterSelecting code
  2. The button’s .Click code runs to completion before the spinner’s AfterSelecting event is serviced

Thanks so much for your help.

P.

I just tested my suspicion about the spinner and the order of events:

  1. A call to the spinner’s set spinner.SelectionIndex method does raise a spinner .AfterSelecting event; however, …
  2. The spinner’s .AfterSelecting event is not processed until AFTER the thread which called .SelectionIndex has finished.

So in my project example, event though my button .Click code called spinner.AfterSelecting first and then set the button’s .Enabled property to false, the .Click code runs to completion BEFORE the spinner’s .AfterSelecting event is serviced.

So my problem isn’t due to a bug in AI2. It was just my misunderstanding of how the spinner events work.

Thanks for your help.

P.

  1. Yes, the spinner component is an android thing, takes a few workarounds to get it under control! I usually call the spinner from a button, rather than use it’s own “button”, this allows you set set the spinner up a little more. (You can make the spinner element almost invisible by sizing it to 1x1 pixels. It has to be visible for it to respond.)

  2. You should put any events you want to run after the afterSelecting event has fired in the afterSelecting event block, not in the button block.

I suggest you have a play/fight with the spinner in isolation (a little test app) to see if you can make it do what you want.