hi there! just getting started with app inventor, made a "hello world" app & now working on a simple color picker. i have run up against 2 basic things i can't figure out, i suspect it may be that they just can't be done but figured it was worth asking.
1. is there a way to copy and paste components in the Designer? for instance, i've made a table arrangement full of labels and sliders and i want to make a copy with a few little changes. it was kind of a pain to make the 1st one and took several tries (some bugginess in the way tables are filled?), so if i can avoid building again from scratch that would be ideal. but the Components panel only seems to give options to rename or delete, and using control click (which works to copy/paste Blocks) doesn't seem to do anything.
2. is there a way to change the same parameter of a whole bunch of labels at once, without having to set each one individually? for instance, i want all the labels within a certain vertical arrangement to change text color when a button is pressed. i can obviously do this by using "set LabelXX.TextColor" for each of the 25 labels, but it seems like there should be an easier way. in the Blocks menu, under "Any component-->Any Label", i thought i could use "set Label.TextColor of component" and give it the entire Vertical Arrangement as the component parameter, but it won't accept that block, nor any block other than a single label. which seems to just do the same thing as using "set LabelXX.TextColor" from the individual label blocks, so i can't even figure out why it exists as a separate block if it just does the same thing? :/
--
1. Currently, there's no way to copy and paste components. We can only duplicate the blocks, either by right clicking and selecting DUPLICATE or dropping them in the backpack, on the upper right corner of the blocks editor, to use them in a different screen or project.
2. Please see the sample in this image to change the text color of 5 labels at the same time.
--
Each component has to be dragged into the Designer individually.
Horizontal and Vertical nested arrangements work better than Table Arrangements, at setting uniform heights and widths inherited from an enclosing arrangement.
The Any component blocks work best with lists of components, built up at Screen.Initialize time.
See attached for an example.
I tried a Kakuro simulator with 120 labels and 120 buttons, but it bogged down from too many components in the Designer,
so at some point you might have to switch to drawing your "components" on a Canvas instead.
--
Question 1: no. You cannot copy designs. But yes, you can copy blocks via the backpack.
Question 2: The way to change your 26 labels (do you really need that many?) is, to create a global variable that will contain a list with these lables. Fill this list in Screen1.Initialize.
When you need to set the attributes, you use a for each item in list block and use the item as component in the any block.
Something like this (I made only 3 labels). Cheers, Ghica
Question 2: The way to change your 26 labels (do you really need that many?) is, to create a global variable that will contain a list with these lables. Fill this list in Screen1.Initialize.
When you need to set the attributes, you use a for each item in list block and use the item as component in the any block.
Something like this (I made only 3 labels). Cheers, Ghica
--
thank you all for your quick and informative replies!
can anyone comment on the advantage of defining the list at screen initialize as Abraham and Ghica have done, vs defining it within the button press event handler as Italo has done?
I'm also not clear on the need for the "create empty list" command, if anyone can elucidate its usage.
in the end, i'm not sure if the list method is worthwhile in this particular case, since i am only changing a single parameter it may be easier to just set them all one by one. but if i were trying to change multiple parameters, this would def be the way to go. thanks again for your advice :)
--
If you need to use the list more than once, it is better to do it during initialize. Italo was just clarifying the concept I assume. In his implementation you would create the list every time you press the button, which is not nice if the list is very long.
Creating the empty list is not really necessary, you could also have set the variable to an empty string or 0. But is wise to create the variable with a value that inicates its later use.
As soon as you would want to do something else with your labels, or when you would want to add or remove a label, you will find that this list method is much more powerful and it is less easy to make mistakes, once you have set it up.
Creating the empty list is not really necessary, you could also have set the variable to an empty string or 0. But is wise to create the variable with a value that inicates its later use.
As soon as you would want to do something else with your labels, or when you would want to add or remove a label, you will find that this list method is much more powerful and it is less easy to make mistakes, once you have set it up.
--
The way I did it is for when you are not going to use the list many times. Like Abraham and Ghica did is better if you change the properties of that list of components many times in the project. That way you save blocks, by just mentioning the global that contains the components.
--
the need for the "create empty list" command, if anyone can elucidate its usage.
You need something to fill the empty socket for the define global variable block,
you know it will be a list, but you don't know what you will put in it yet.
You need the empty list value there to insure later on when you go to
add items to it or check its contents, it will
have the proper internal structure for that and not crash your app.
last q's for Abraham: why did you use the procedures to contain the other blocks, and would it work without them? and why local variables instead of global?
--
why did you use the procedures to contain the other blocks,
Collecting all the components took a lot of blocks, but accomplished only one result.
It was only a small part of the initialization process, and for the sake of readability,
hiding it away in a separate procedure makes it easier to see the rest of the initialization
process at a glance, without the wallpaper of all those blocks.
I find it easier to understand what I write if I divide it up into pieces that will fit onto one computer screen,
with a single purpose to each piece.
and would it work without them?
The app might work, but I would find it harder to maintain and grow.
and why local variables instead of global?
Have you ever seen a movie or TV show where the boss is evil and tells his
employee: "I want it done, and I don't care how you do it!"?
That's an abuse of a proper management practice where a boss sets up the work
environment for his employees to produce results without interfering with
each other or with himself.
Local variables are handy for temporary work, where you don't want to litter the name space after you're done.
Global variables are necessary for debugging and for a well managed shared object, but they come with a cost
in complexity. You have to constantly worry about which procedures might be changing them behind your back,
unless you exercise conscious restraint and allow only a small number of procedures to access them in a small
number of places.
That's why I used a local variable and a result procedure. Collecting all my buttons is one thing, and assigning
the collection into whatever list I keep them in for the long term is another decision, up to the calling routine in
my initialization code.
--
댓글 없음:
댓글 쓰기