WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Closing all frames with the same name (https://www.wowinterface.com/forums/showthread.php?t=57949)

Milton 04-17-20 08:48 AM

Closing all frames with the same name
 
I am creating many frames in the same spot, overlapping one another, with this:

local tar_btn = CreateFrame("Button", "get_tar", UIParent, "SecureActionButtonTemplate")

when I click them, they do what I need them to do and then close, one after the other:

tar_btn:SetScript("PostClick", function (self, button, down)
-- if button == "RightButton" then
-- ...
-- end
self:Hide()
self:SetParent(nil)
end)

I want them all to close at the same time when I right click, what command can I give so all frames with the name "get_tar" disappear and get garbage collected when I right click on any one of them?

This didn't work:

if button == "RightButton" then
get_tar:Hide()
get_tar:SetParent(nil)
end

Fizzlemizz 04-17-20 09:22 AM

Frames don't get disposed/garbage collected. You should re-use the same frame where possible.

The global name of the first frame created with the same name is stored so you would need to keep track of any frames created yourself, most commonly by adding the reference to a table, or use unique names.

Lua Code:
  1. local MyButtons = {} -- Storage
  2.  
  3. local function CreateButton(id)
  4.     local f = CreateFrame("Button", "MiltonActionButton"..id, UIParent, "SecureActionButtonTemplate") -- Create your button(s)
  5.     tinsert(MyButtons, f) -- and add to storage
  6.     ...
  7. end
  8.  
  9. local function HideButtons()
  10.     for i=1, #MyButtons do -- Hide them all
  11.          MyButtons[i]:Hide()
  12.     end
  13. end

Seerah 04-17-20 11:54 AM

Quote:

Originally Posted by Milton (Post 335682)
I am creating many frames in the same spot, overlapping one another, .....

... why though?

Milton 04-17-20 02:31 PM

Quote:

Originally Posted by Fizzlemizz (Post 335684)
Frames don't get disposed/garbage collected. You should re-use the same frame where possible.

The global name of the first frame created with the same name is stored so you would need to keep track of any frames created yourself, most commonly by adding the reference to a table, or use unique names.

Lua Code:
  1. local MyButtons = {} -- Storage
  2.  
  3. local function CreateButton(id)
  4.     local f = CreateFrame("Button", "MiltonActionButton"..id, UIParent, "SecureActionButtonTemplate") -- Create your button(s)
  5.     tinsert(MyButtons, f) -- and add to storage
  6.     ...
  7. end
  8.  
  9. local function HideButtons()
  10.     for i=1, #MyButtons do -- Hide them all
  11.          MyButtons[i]:Hide()
  12.     end
  13. end

Thank you, it worked like a charm. I added a MyButtons[i] = nil to the loop so that the table contains only the new frames created.

frame:SetParent(nil) I got from here

Quote:

Never forget to unset the frames parent, if you want to get rid of a frame. I would suggest to hide the frame via frame:Hide() and to use frame:SetParent(nil) afterward (this will remove the frame from its parents child list). If you just hide the frame without this additional step, frames created afterward will get a higher framelevel than the hidden one. After a while, you will get frames at maximum framelevel which are likely to be drawn in a distorted way (false order caused by equal framelevel).
https://wowwiki.fandom.com/wiki/API_CreateFrame

Quote:

Originally Posted by Seerah (Post 335688)
... why though?

Because the location is important. I want the button(s) right in the center of the screen so I can click through them fast. And I want them to take as little of my screen as possible (and I'm a lua noob so anything more complex requires hours of research).

Fizzlemizz 04-17-20 03:07 PM

In this instance, "get rid of" doesn't mean dispose and release resources, it just means, "not see" and avoid some possible future problems with new frames.

Setting the parent to nil just releases it from the strictures of being a child of it's current parent (following scale, hide state etc.).

Milton 04-17-20 04:25 PM

Quote:

Originally Posted by Fizzlemizz (Post 335690)
In this instance, "get rid of" doesn't mean dispose and release resources, it just means, "not see" and avoid some possible future problems with new frames.

Setting the parent to nil just releases it from the strictures of being a child of it's current parent (following scale, hide state etc.).

When do I "reuse" a frame? I ended up creating many frames like this

Quote:

local tar_btn = CreateFrame("Button", nil, UIParent, "SecureActionButtonTemplate")
So they don't have a 'name' property, and they all have the same... tar_btn - I don't know what to call this, the name of each frame's table?

They all behave like different frames - each one appears and disappears as needed and they can all be on the screen at the same time - so I don't know how would I be reusing the same frame instead of creating a new one (with its appropriate resources) every time.

Fizzlemizz 04-17-20 04:56 PM

It depends on what you are doing with the buttons and how many you need active at the one time (if you are just stacking one on top of the other it sounds like you only need one).

An example of re-use is your action bar buttons. You can change the spell/action for a single button any number of times by dragging a spell/item etc. onto it. This doesn't create a new button each time, just changes what the current button is used for.

You could use re-use individual button from the table if you identify which one is no longer in use.

Cheesey example using the 3rd button created to re-use:
Code:

local reUseButton = MyButtons[3]
reUseButton:SetText("Some New Action!")
reUseButton:SetScript("OnClick", function(self)
    print("You clicked:", self:GetText())
    self:Hide()
end)
reUseButton:Show()


Milton 04-17-20 11:13 PM

Ah, I understand. Reusing it means just changing the functionality of it, what is displayed and what it does, without creating a new frame.

In this case, I create maybe 500 new frames during a play session, it probably has no impact on the overall performance of the game at this level. On the other hand, there would be no more than 10 frames overlapping at any one time, so I could reduce the number to 10 and have cleaner code (or rather just one frame as you suggested earlier, though it's more difficult to implement). Maybe I will when I get a little bored with the actual game.

Thank you for sharing your wisdom.

sezz 04-23-20 06:00 AM

Quote:

Originally Posted by Milton (Post 335696)
Ah, I understand. Reusing it means just changing the functionality of it, what is displayed and what it does, without creating a new frame.

Exactly. Blizzard also added CreateObjectPool/CreateFramePool in BfA I think if you don't want to write the code to handle the frames yourself. You just create a pool and acquire a unused/new button and release it when you don't need it anymore so it can be reused later when you need another one.


All times are GMT -6. The time now is 08:13 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI