distinguish vgui elements created by loop

So I am trying to do a list of players but the doclick function on AvatarImage didn’t quite worked so I created a button it and here the problem begins



			for k,v in pairs(player.GetAll()) do
				local tablet_avatar = tablet_app_text_avatar_scroll:Add( "AvatarImage" )
				tablet_avatar:SetText( "" )
				tablet_avatar:Dock( TOP )
				tablet_avatar:SetSize(ScrW() / 12, ScrH() / 8)
				tablet_avatar:SetPlayer(v, 256)
				tablet_avatar.id = k
				function tablet_avatar:PaintOver(w, h)
					StencilStart()
					DrawCircle(w/2, h/2, w/2, 1, Color(0,0,0,1))
					StencilReplace()
					surface.SetDrawColor(220,220,220, 128)
					surface.DrawRect(0, 0, w, h)
					if tablet_avatar.picked == true then
						surface.SetDrawColor( 255, 255, 255, 255 )
						draw.NoTexture()
						surface.DrawTexturedRect( 0, 0, w, h )
					end
					if tablet_avatar_button:IsHovered() and tablet_avatar_button and tablet_avatar_button.id == tablet_avatar.id then
						draw.RoundedBox( 0, 0, 0, w, h, Color( 220, 220, 225, 255 ) )
					end
					StencilEnd()
				end
				tablet_avatar_button = vgui.Create("DButton", tablet_avatar)
				tablet_avatar_button:SetText("")
				tablet_avatar_button:SetSize(tablet_avatar:GetSize())
				tablet_avatar_button.Paint = function()
				tablet_avatar_button.id = k
			end


As you can see I tried to distinguish each vgui elements with each other by assigning a current key to it and comparing it… which didn’t worked.

You create a local var tablet_avatar inside the loop meaning that variable doesn’t exist outside of the for loop - additionally, it CAN be used in the function you defined PaintOver…

I’d recommend doing something like this outside of the loop:
local _avatar_panels = { }; – if it needs to be accessed ONLY within the area you originally define it…

If you want to access it anywhere inside of the large panel, ie you define it inside of function PANEL:Init( ) then I’d do:
local self.AvatarPanels = { }; – Then you’d be able to access it ANYWHERE you have a reference to the panel… so if you do local _panel = vgui.Create( “ThePanelWithselfDotAvatarPanels” ); then _panel.AvatarPanels would have access to it, ie _panel.AvatarPanels[ LocalPlayer( ) ] or _panel.AvatarPanels[ LocalPlayer( ):EntIndex( ) ]; would return the AvatarImage panel you added…

then in the loop do:
_avatar_panels[ v ] = tablet_app_text_avatar_scroll:Add( );

and use _avatar_panels[ v ] to reference all of the rest - although I’d do something like local _pnl or _panel = blah:Add( … ); then _avatar_panels[ v ] = _pnl or _panel; depending on which var I used as _pnl or _panel would be shorter and you wouldn’t need to repeat the reference each time…

Then, you can access it as long as you have the player ent ( Another option, I’d recommend using v:EntIndex( ) as it’ll be 1 to maxplayers… then you’d use the entity index of the player to reference it )…

It also depends how far out you want to access the data…

I haven’t messed with :Add in a while - make sure it doesn’t require an actual panel ( ie vgui.Create( “AvatarImage” ); )…

EDIT: I see what you’re doing now - I didn’t see it until now… you’re doing something.id = k; which won’t do anything other than add a key, id, to the table, blah, with the value k assigned to it… It won’t turn the variable into something you can use to reference with… You need to create a table, as examples are above, to have references to each individual var…

Unfortunatey Dropbox removed public folder access for all free accounts so all of my previous tutorial links are dead - I used a nice and easy .lua.html file format so .lua.html is for the the script highlighted in html form to read it… and you remove .html in the link to view .lua as plain-text which is used for copy / paste as html doesn’t copy code well… So I may either pay for now, but I am working on getting my site up to post them there…

For the time being, these are the basics I send out to people to read first and they give you an idea of how Lua is structed - Everything is stored in tables so understanding how to reference, add, edit, remove is vital… A few other files are in here too - .lua for Lua files, .lua.html for the script with the syntax colored for viewing in a browser…

I just added a quick example of scopes, but it barely even scratches the surface…

:snip:

Ninja’d
Plus, i think Acecools response is much better than mine

ninja’d boi

I didn’t quite understood you… If you could post an example it would be greatful

I did an edit, but too late:

EDIT: I see what you’re doing now - I didn’t see it until now… you’re doing something.id = k; which won’t do anything other than add a key, id, to the table, blah, with the value k assigned to it… It won’t turn the variable into something you can use to reference with… You need to create a table, as examples are above, to have references to each individual var…

Unfortunatey Dropbox removed public folder access for all free accounts so all of my previous tutorial links are dead - I used a nice and easy .lua.html file format so .lua.html is for the the script highlighted in html form to read it… and you remove .html in the link to view .lua as plain-text which is used for copy / paste as html doesn’t copy code well… So I may either pay for now, but I am working on getting my site up to post them there…

For the time being, these are the basics I send out to people to read first and they give you an idea of how Lua is structed - Everything is stored in tables so understanding how to reference, add, edit, remove is vital… A few other files are in here too - .lua for Lua files, .lua.html for the script with the syntax colored for viewing in a browser…

I just added a quick example of scopes, but it barely even scratches the surface…

Hopefully those examples will shed some line on it… But another one here – this is why you see some people doing this:

This is what you’re doing, the way I understand it


for i = 1, 10 do
    print( i );
end
print( i ); -- even though i ended at 10 in the loop, this will print nil because i no longer exists outside of the loop

This is one way to get the data outside of the scope


local i = nil -- this defines i outside of the for scope so it can be used outside - this type of for loop creates the variable in its scope which is why I called it x, then set i = x so i has the value... then it is set outside of the scope...
for x = 1, 10 do
    i = x;
    print( i );
end
print( i ); -- now this prints 10 - if I were to print x, it'd be nil


But this is what you want to do from what I gather:


self = { }; -- assume this is in PANEL:Init( ) so self == PANEL table
self.AvatarPanels = { }; -- Set up the panels so we can access them where ever we have a reference to the primary vgui, or inside it...

-- So, lets say we have players 1 through 10
for i = 1, 10 do
    -- So, set self.AvatarPanels key as i which could be k in your case... you can also use v as the player, or you can use v:EntIndex( ) which would be a number from 1 to maxplayers
    -- = "Player_" .. tostring( i ); basically makes it Player_1, Player_2, Player_3, ..., Player_10 which could be set as vgui.Create( "AvatarImage" ); or if your panel:Add( "AvatarImage" ); returns the panel, then that'd be set as the vgui panel....
    self.AvatarPanels[ i ] = "Player_" .. tostring( i );
end

--now outside of the scope - these would be references to the panels if set up that way..
print( self.AvatarPanels[ 10 ] );
print( self.AvatarPanels[ 5 ] );
print( self.AvatarPanels[ 1 ] );


Run them on: https://www.lua.org/cgi-bin/demo

Please excuse the crude examples - but they should point out the mechanics easily enough…

Oh, thanks. And one question in which panel do you want me to do PANEL:Init()? tablet_avatar, tablet_app_text_avatar_scroll or tablet_avatar_button?

It is just an example - the for loop, etc… must be in some function, right?

If that function is named similar to: function PANEL:Init( ) or function blah:Bleh( ) … ie with : then you can use self… and it’ll be bound to the object / table which is what self points to… in the 2 examples above, self would be PANEL, or blah…

Look at that zip / rar I gave you called __TheBasics… It’ll explain . vs : and how to read / understand function naming, Lua tables, etc…

You don’t need to name it self.AvatarPanels if you don’t want to either - it was an example too…

If your issue is simply to get the PaintOver if-statement to run when the associated button is hovered, you can solve it simply by defining the button locally above the PaintOver function, then just referencing that in the function.
[lua]local tablet_avatar = tablet_app_text_avatar_scroll:Add(“AvatarImage”)
– Stuff with tablet_avatar
local tabel_avatar_button = vgui.Create(“DButton”, tablet_avatar)
– Stuff with tablet_avatar_button

local color = Color(220,220,255) --Don’t constantly create new colors in a Paint function
function tablet_avatar:PaintOver(w,h)
– …
if tablet_avatar_button:IsHovered() then
draw.RoundedBox(0,0,0,w,h,color)
end
end[/lua]
Basically, the local variable “tablet_avatar_button” will in each iteration of the loop only refer to the specific value it had during that iteration - even when the loop is finished. This is only the case if the variable is local to the inside of the loop.

It is in



function tablet_app_text:DoClick()


but the problem is that it removes it self after running so I think I can’t use self variables.

bumpy



tablet_app_text.DoClick = function( self )
-- use self now


[editline]3rd September 2017[/editline]

Also, I don’t know what you mean about it ‘removing self’. If self was removed, the panel wouldn’t be able to do anything internally. It should work

tablet_app_text is a button, then it creates a frame like when you click something on windows it closes current window and opens another one.

You should use gist.github.com, it’s kind of like pastebin with extra features.