1 2 3 4 5 6 7 8 | local buttons = 3 local buttonImage = { "btn1.png", "btn2.png", btn3.png" } local buttonTable = display.newGroup() for i=1, buttons do button = display.newImage(buttonimage[i]) --button[1] = display.newImage() buttonTable:insert(button) end |
Was searching for the exact same thing (something like this[] in flash), but than I actually forget why to use that, since there are always better workarounds.
Why would you want to do that?
Why not putting those into the group directly and/or into a table?
You could also give those Images other "attributes"
i.e.
1 2 3 4 5 6 | for i=1, buttons, 1 do local button = display.newImage(...) button.name = i buttonGroup:insert(button) -- or even table.insert(buttonTable,button) end |
Why not just use a table/array:
1 2 3 4 5 6 7 8 9 | local buttons = 3 local buttonImage = { "btn1.png", "btn2.png", "btn3.png" } local buttonTable = display.newGroup() local button = {} for i=1, buttons do button[i] = display.newImage(buttonimage[i]) buttonTable:insert(button[i]) end |
There are ways to do it if you *really* want to. Though I think the table of buttons is better, I'll post this as an example of how it could be done.
Globals are easy:
1 2 3 4 5 | for i=1, 10 do _G["button"..i] = i end print( button1 ) -- here the global button1 is equal to 1 |
@ Yobonja
Is there actually a benefit of doing it that way?
I really haven't come across a good reason to make it - but I love to learn new stuff :)
xxxfanta: The "why" is simply because if you don't know the number of buttons, you can't declare the variables. (I won't know if I need button2 until I know the variable, right?)
Building out a table works too (hence my original code), but it just seemed like a simple, elemental thing to do would be able to make variable names out of variables. Also, none of the table.function calls work in a displayGroup which can complicate things.
robmiracle: Looks like your code is identical to my original sample except:
1. You didn't miss the " I did. ;)
2. You're inserting all of the buttons into button{} and then inserting button{} into buttonTable. Not really sure why?
Yobonja: Well...uh...I've never even heard of _local or __index before, so I can see why it's less desirable.Heck, I think I can finish coding the function before I can figure out exactly what's going on there. But thanks for the demo :-)
@xxxfanta
I haven't found any good reason to do it :) just that it's possible. it's essentially the exact same thing though, you're just adding the variable to a table.
@richard9
He puts it in the table so you can reference button1 by writing button[1].
Also, I've found that you can dump a display group into a table, then call the table function you want on that table.
-Angelo
You're original example wasn't using an array:
button = display.newImage(buttonimage[i])
Each time you iterate through the loop, you keep reusing the variable "button" but it keeps reallocating memory. This is a prime example of a memory leak since you loose access to the previous buttons.
My code keeps unique references:
button[i] = display.newImage(buttonimage[i])
There was something commented out at the end of the line where it looks like you tried to use an array. You also needed to create the array before the loop:
button = {}
Hope that helps.
@richard, have a read of the tutorial here
and to answer your question, as to why the button={} and buttonTable:insert
if you have a little idea about coronaSDK, you will see that buttonTable is declared as display.newGroup(), this is the group that @robmiracle has created to hold the buttons. This is a display object, nothing to do with arrays.
so after creating the button object, he is using the buttonTable:insert(button[i]) to place the display object into the display group. This line can be avoided by altering the code as
6 7 8 | for i=1, buttons do button[i] = display.newImage(buttonTable, buttonimage[i]) end |
@richard9
the example by @robmiracle works, but i think that storing buttons in both a regular table and a display group is overkill - as they're both tables so can both be used for storage.
the example by @yobonja is giving you the ability to do name look up as you asked for, but i don't think it's what you want. as they say, "be careful what you ask for because you might get it." :) one of the issues with this solution is that it requires having a deeper understanding of the Lua language. second issue is that in practice you'd never need to do this nor can i think of a reason why you would want to. :P
i think an important question that you need to ask/answer is: "What are you *doing* with the buttons ?"
What do you want to happen when you click one ? why do you need to have a way to find them after they are created ? Do they need to act as a unit, a la Display Group ?
your answer to that will guide you to determine whether to use a Lua table or Corona Group. also, the key you use to retrieve them from the storage will play a factor as well.
the display group and the regular lua table can both be used as storage - they both have insert/remove/get functionality on them. (though the methods are different). however, i'd say that the one you choose depends on what you have intended for your buttons.
for example, putting display objects into a display group implies that the objects are going to act as a unit. if you change x,y position on the group, you change the location for all contained objects. if you change alpha on the group, you change for all contained objects.
the regular Lua table doesn't do any of that. if you use it, it's really just a raw Lua-based container for things, like your buttons or anything else you want. plus, you have A LOT more flexibility in how to index / lookup your values - see below.
so without knowing more about what you're trying to achieve, i'd say that combining both examples from @robmiracle and @xxxfanta is the way to go. choose either display group or table, taking the above into consideration.
1 2 3 4 5 6 7 8 9 10 11 12 | local buttons = 3 local buttonTable = display.newGroup() -- local buttonTable = {} -- use this if just need a container object for i=1, buttons do local button = display.newImage( "btn" .. i .. ".png" ) button.name = i buttonGroup:insert( button ) -- or even table.insert( buttonTable, button ) end |
Welll, first off, truly, thanks to all for responding. I thought it was a simple mechanical question but there has been a ton of variety in these well thought out responses. :)
The original goal of this was simply because my designer brain immediately thought "hey, I can just use .. to make dynamic variables on the fly! This is easy!" (*cough*) Basically, jayantv's link is dead on with my thinking.
As a relative "noob", tables flip between easy and intimidating for me. So to dmccuskey, I say, I know what I need, but sometimes it's hard to glean how a particular approach does that for me without maximum understanding of that approach - understanding that doesn't come without trial-and-error.
Now, as to what I'm *actually* trying to make...is the iPad bottom tab bar. I know there's an existing template, but it's not extensible and I'd pretty much have to go in and re-write half of the thing. For learning reasons I'd rather just make my own - that way I have some sturdy to share here and to use for myself on two radically different projects.
(And really, I like to try and respond to other guys posts too. :P)
edit: I do see how you removed the image table...but not so useful in a function where you'd arguably want to be able to state the needed images ahead of time. :)
@richard9,
yeah, there are some quirky aspects of Lua which can be confusing, and tables is one of them. for example, the fact that Lua uses the same base data structure for different situations and that structure can act a little differently depending on how you use it can cause issues. so, as you say, you will have to learn by trial-and-error, but i think once you're familiar and comfortable with the idiosyncrasies, like jayantv says, "it's a lot of fun". in any event, it seems like you're making great progress with Corona and Lua.
since you're tackling the bottom tab bar, i'll mention that i've done that too and added that code to a re-usable, extensible library i've started to put together. the lib uses object oriented programming exclusively (OOP is also part of the lib) so you can tweak it as much as you like, but you'd have to know about OOP and perhaps a little more about Lua. i have written docs and examples, so if you want to check it out: http://developer.anscamobile.com/code/dmc-corona-library
but i also understand the desire to Build It Yourself and be able to learn from that experience. i'm sure we've all been there. :)
good luck with the project !
cheers,
dmc
"the example by @robmiracle works, but i think that storing buttons in both a regular table and a display group is overkill - as they're both tables so can both be used for storage."
**SCRATCH THAT**
First, the OP created the table. And in this case, the display group is only holding buttons, so you could use it to reference the other buttons.
But I still think that using a specific buttons[] array is clearer and easier to understand whats going on.
I guess there are several ways to skin a cat...
No particular way is better than the other, the one which makes you feel comfortable is the best. Sometimes what happens is that in a given context, some things work best and some don't where as in a different context things might be different.
I guess everyone that pitched in had good reasoning and code samples for the issue at hand, I avoid a lot of advance stuff in my tutorial and code as *I believe* that a beginner needs to understand how things work more importantly than understanding memory leaks at this stage. Once they get beyond the stage of basic syntax and operations, then they can bother about optimisations etc.
Just my two bits
cheers,
?:)
Yeah, I totally understand the memory leaks issue but my brain just can't handle going back to recode everything to avoid require and globals yet. Gotta make something first and then make it reliable after. (Considering how badly I managed to break widget.newTableView...)
wait, what, I can insert display.newImage directly into a group right away? Nice.
Alright, more mindless jabber from me later. But I do appreciate the help - just looking at the examples in this thread has given me a good idea out of how to rope in the other bits.
So, I hate to drag this out but I've sort of run into the exact wall I was afraid of by using tables.
I was hoping to do two things by referring to tables/groups inside of other tables/groups, like:
1 2 3 4 5 6 7 | function tabBar() -- some code return tabGroup -- this is a master group containing buttons and over states. end myTab = tabBar() myTab.buttonsGroup.button[1]:addEventHandler("touch", press) --theoretically would apply the handler only to button 1. |
do you have a group called tabGroup?
that has another group added to it called buttonsGroup?
which has an array added to it called buttons?
and each element in this buttons Array is a display object that can be made visible or invisible.
if you have YES to all the questions, let us look at it further. Please read and check carefully.
cheers,
?:)
Yeah, exactly.
1 2 3 4 5 6 7 8 9 | local tabGroup = display.newGroup() -- holds everything local buttonsGroup = display.newGroup() -- holds all of the buttons local buttonsOverlay = display.newGroup() -- holds all of the button overlays local button = {} -- the buttons themselves, basically similar to above or your link. local buttonOverlay = {} tabGroup:insert(buttonsGroup) tabGroup:insert(buttonsOverlay) buttonsGroup:insert(button) buttonsOverlay:insert(buttonOverlay) |
Hmm... I have been doing a lot of this in corona(dynamic "naming" of object... really just putting them in a table and referancing them by thier table index.)
I thought I would throw together a working sample... it is a little ugly (ok maybe more than a little) but I thought it might inspire someone else....
The following is a "Color Picker". The number of colors displayed is based on the screen resoltion.(varible) and they are changed by referancing the rectangle(color) by it's table index. (in this case it just cycles thru all off the objects but it is possible to change just one if you keep track of the indexes... like in anouther Lua table where the index is something usefull and the value is it's position in the display group.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | Ww,Hh = display.viewableContentWidth, display.viewableContentHeight BackgroundColor = display.newRect( 0,0,Ww,Hh);BackgroundColor:setFillColor(0,0,255) function cButton(lx,ly) local c=1 while customButton[c] do local tT=customButton[c] if tT["active"]== "true" and lx > tT["x1"] and lx < tT["x2"] and ly > tT["y1"] and ly < tT["y2"] then if tT["command"] then return tT["command"] else return "color",tT["r"],tT["g"],tT["b"] end end c=c+1 end return nil end local testHandle = function (event) -- print("---began-----"..event.x.." "..event.y) local lCMD,r,g,b = cButton(event.x,event.y) if event.phase == "began" and lCMD then print("---began-----"..event.phase.."--------"..lCMD) CMD = lCMD elseif event.phase == "moved" and CMD then print("---moved-----"..event.phase.."--------"..CMD) if lCMD ~= CMD then print("---cancel----"..event.phase.."--------"..CMD) CMD = nil end elseif event.phase == "ended" and CMD then print("---ended-----"..event.phase.."--------"..CMD) if lCMD == "color" then PickerGroup.alpha=0 PickerButtonGroup.alpha=1 local i = 1 --disable picker buttons while i<PickerKey do customButton[i]["active"]="false" i = i+1 end customButton[PickerKey]["active"]="true" BackgroundColor:setFillColor(r,g,b) elseif lCMD == "pick" then displayPicker() elseif lCMD == "more" then displayPicker() elseif lCMD == "cancel" then PickerGroup.alpha=0 PickerButtonGroup.alpha=1 local i = 1 --disable picker buttons while i<PickerKey do customButton[i]["active"]="false" i = i+1 end customButton[PickerKey]["active"]="true" end CMD = nil end end function createPicker() local cgrid =math.floor(Ww/7) local maxWIDE = 7 local maxHIGH = math.floor((Hh - 100)/cgrid ) local colorKey = 1 customButton = {} local gW = 3--math.ceil(cgrid/2)--10 --width of lines PickerGroup = display.newGroup() local mH,mV = 1,1 while mH <= maxWIDE do local bH=(mH-1)*cgrid while mV <= maxHIGH do local bV=(mV-1)*cgrid local rR,gG,bB = math.random (1,255),math.random (1,255),math.random (1,255) cColor = display.newRect( PickerGroup,bH,bV,cgrid,cgrid);cColor:setFillColor(rR,gG,bB) customButton[colorKey] = {} customButton[colorKey]["x1"] = bH customButton[colorKey]["x2"] = bH+cgrid customButton[colorKey]["y1"] = bV customButton[colorKey]["y2"] = (bV+cgrid) customButton[colorKey]["r"]= rR customButton[colorKey]["g"]= gG customButton[colorKey]["b"]= bB customButton[colorKey]["active"]="false" colorKey = colorKey + 1 mV = mV+1 end--vert while mH = mH+1 mV = 1 end--horz while -- adding command buttons --cancel PickerGroup.alpha=0 --Picker button PickerButtonGroup = display.newGroup() local Choose = display.newRect(PickerButtonGroup, Ww/4,Hh/4,Ww/2,Hh/2);Choose:setFillColor(255,255,255) customButton[colorKey] = {} customButton[colorKey]["x1"] = Ww/4 customButton[colorKey]["x2"] = Ww-(Ww/4) customButton[colorKey]["y1"] = (Hh/4) customButton[colorKey]["y2"] = Hh-(Hh/4) customButton[colorKey]["command"]= "pick" customButton[colorKey]["active"]="true" PickerKey = colorKey colorKey = colorKey + 1 local title = display.newText(PickerButtonGroup,"Pick Color",Ww/3,Hh/3, nil, 20 );title:setTextColor(0,0,0) local Cancel = display.newRect( PickerGroup,0,Hh-100,Ww/2-2,100);Cancel:setFillColor(255,255,255) customButton[colorKey] = {} customButton[colorKey]["x1"] = 0 customButton[colorKey]["x2"] = Ww/2 customButton[colorKey]["y1"] = Hh-100 customButton[colorKey]["y2"] = Hh customButton[colorKey]["command"]= "cancel" customButton[colorKey]["active"]="false" colorKey = colorKey + 1 local More = display.newRect( PickerGroup,Ww/2+2,Hh-100,Ww/2-2,100);More:setFillColor(255,255,255) customButton[colorKey] = {} customButton[colorKey]["x1"] = Ww/2 customButton[colorKey]["x2"] = Ww customButton[colorKey]["y1"] = Hh-100 customButton[colorKey]["y2"] = Hh customButton[colorKey]["command"]= "more" customButton[colorKey]["active"]="false" colorKey = colorKey + 1 local title = display.newText(PickerGroup, "Cancel",Ww/8,Hh-50, nil, 20 );title:setTextColor(0,0,0) local title = display.newText(PickerGroup, "More",Ww/8*6,Hh-50, nil, 20 );title:setTextColor(0,0,0) end--func function displayPicker() PickerGroup.alpha=1 PickerButtonGroup.alpha=0 local i = 1 --enable picker buttons while i<PickerKey do local rR,gG,bB = math.random (1,255),math.random (1,255),math.random (1,255) PickerGroup[i]:setFillColor(rR,gG,bB) customButton[i]["active"]="true" customButton[i]["r"]=rR customButton[i]["g"]=gG customButton[i]["b"]=bB i = i+1 end i = i+1 customButton[i]["active"]="true" i = i+1 customButton[i]["active"]="true" PickerButtonGroup.alpha=0 customButton[PickerKey]["active"]="false" end createPicker() Runtime:addEventListener("touch",testHandle) |
That's...pretty complex, Allen. Hopefully somebody can get inspired from it. :)
As to my puzzle, I've found some behavior I can't explain.
1. As mentioned, the function variable myTab returns tabGroup.
2. tabGroup contains three groups, so you could say it's like this: (I didn't declare it this way, but this is the order)
a. tabGroup[1] = buttonsGroup
b. tabGroup[2] = buttonsOverlay
c. tabGroup[3] = buttonsTitle
3. If I add an event listener to "myTab"...
Results:
myTab[1] acts like tabGroup.buttonsGroup.button[1]
myTab[2] acts like tabGroup.buttonsOverlay.overlay[1]
myTab[3] acts like tabGroup.buttonsTitle.title[1]
Each group has 5 objects within, so I must be missing some sort of syntax that is causing it to pick the first one out of the subgroup...
send message and call to a person
Forum: Report Spam + PM
[INSTALL_PARSE_FAILED_NO_CERTIFICATES]
[SOLVED] Director ERROR: Failed to execute new( params ) function on 'screen1'
Too many (200) local variables
Corona SVG Level Builder released. Drag and drop physics level editor with Inkscape and SVG.
Small bug in Collectible Items example
Pivot Joints and apparent elasticity
Can't make removeSelf() delayed
Corona SDK satble build 451 and dially build on same maching
Audio API implementation crash
require modules by relative path
Large file count problems..
OTF fonts not working in Windows simulator
Native Keyboard in iPhone
New Computer (Certificate not Installed) Issue
Dragging a new object just created
Best way to develop for iPhone and iPad?