WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Remove a Frame element with LUA (https://www.wowinterface.com/forums/showthread.php?t=28224)

richardCANE 10-28-09 08:30 PM

Remove a Frame element with LUA
 
hi guys

i want to create a frame that shows your main bag's content with icons too...

so when i open up my addon frame the LUA dynamically draws a frame and draws the CURRENT content of my bag into...

is it possible to remove/delete/clear frames, textures and fontstrings ( xml elements ) with LUA somethings like Frame:Delete ?

thanks for any replies

Torhal 10-28-09 08:54 PM

No, this is not possible. Nor is it possible to give them to the Lua garbage collection facility. What you need to do is create these things once and re-use them as they're needed.

richardCANE 10-29-09 04:25 AM

thanks for reply

and how to do that? can you give me some little example in LUA? how can i reuse the elements?

Slakah 10-29-09 04:32 AM

lua Code:
  1. local framepool = {}
  2.  
  3. local function removeframe(f)
  4.     f:Hide()
  5.     tinsert(framepool, f)
  6. end
  7.  
  8. local function getframe()
  9.     local f = tremove(framepool)
  10.     if not f then
  11.         --Create your frame here and assign it to f
  12.     else
  13.         --revert any unique changes you may have made to the frame before sticking it in the framepool
  14.     end
  15.     return f
  16. end

Something like that as a very basic example

richardCANE 10-29-09 04:59 AM

thank you so much :banana:

maximdewit 11-23-09 01:32 PM

cant you for example simply write frame=nil?

dont shoot me ^^

--

Seerah 11-23-09 01:33 PM

That nils the reference to the frame, and maybe its properties, but the actual frame object is still in memory.

Torhal 11-23-09 06:59 PM

Quote:

Originally Posted by maximdewit (Post 166866)
cant you for example simply write frame=nil?

dont shoot me ^^

--

I have to shoot you. Four posts above yours, I explained that this wasn't possible.

*BLAM!*

Sythalin 11-23-09 10:01 PM

But you can reduce the memory allocation by stripping the variable of it's data with f={}.

Akryn 11-23-09 10:11 PM

Quote:

Originally Posted by ChaosInc (Post 166911)
But you can reduce the memory allocation by stripping the variable of it's data with f={}.

That's still just re-pointing the pointer, it's not even as good as f=nil.

nightcracker 11-24-09 12:17 AM

And what about table.wipe(f) ?

Torhal 11-24-09 12:20 AM

That does nothing for frames but clear their table members. The frame itself still exists, and will always exist until the UI is reloaded or you re-start WoW. Tables CAN be garbage-collected. Frames, though they are a special form of table, CANNOT.

nightcracker 11-24-09 03:08 AM

Quote:

Originally Posted by Torhal (Post 166925)
That does nothing for frames but clear their table members. The frame itself still exists, and will always exist until the UI is reloaded or you re-start WoW. Tables CAN be garbage-collected. Frames, though they are a special form of table, CANNOT.

So basicly the closest you can get is like this:
lua Code:
  1. local function deleteframe(f)
  2.     if not f.DeletedEvent then
  3.         f.DeletedEvent = f.OnEvent
  4.         f:Hide()
  5.         f.OnEvent = function() end
  6.     end
  7. end
  8.  
  9. local function restoreframe(f)
  10.     if f.DeletedEvent then
  11.         f:Show()
  12.         f.OnEvent = f.DeletedEvent
  13.         f.DeletedEvent  = nil
  14.     end
  15. end

Torhal 11-24-09 03:45 PM

No - that requires that you have a frame pointer for restoreframe(), which at that point isn't really possible without breaking the illusion that the frame has been "deleted". You would use this, instead:

Code:

local AcquireFrame, ReleaseFrame
do
        local frame_cache = {}

        function AcquireFrame(parent)
                local frame = tremove(frame_cache) or CreateFrame("Frame")
                frame:SetParent(parent)
                return frame
        end

        function ReleaseFrame(frame)
                frame:Hide()
                frame:SetParent(nil)
                frame:ClearAllPoints()
                tinsert(frame_cache, frame)
        end
end        -- do block

I also don't see the purpose in replacing the frame's OnEvent script - perhaps you're thinking of OnUpdate...but that never fires when the frame is hidden anyway.

nightcracker 11-25-09 12:22 AM

Quote:

Originally Posted by Torhal (Post 166983)
No - that requires that you have a frame pointer for restoreframe(), which at that point isn't really possible without breaking the illusion that the frame has been "deleted". You would use this, instead:

Code:

local AcquireFrame, ReleaseFrame
do
        local frame_cache = {}

        function AcquireFrame(parent)
                local frame = tremove(frame_cache) or CreateFrame("Frame")
                frame:SetParent(parent)
                return frame
        end

        function ReleaseFrame(frame)
                frame:Hide()
                frame:SetParent(nil)
                frame:ClearAllPoints()
                tinsert(frame_cache, frame)
        end
end        -- do block

I also don't see the purpose in replacing the frame's OnEvent script - perhaps you're thinking of OnUpdate...but that never fires when the frame is hidden anyway.

Because it might be - for example - registered to PLAYER_REGEN_DISABLED and in the event handler it shows itself, and sets it to a certain point for example? And something is wrong with your frame_cache table, it works fine as long as you work with 1 frame, but with multiple frames you would get the wrong one back from the acquire function.

Torhal 11-25-09 05:11 AM

Quote:

Originally Posted by nightcracker (Post 167031)
Because it might be - for example - registered to PLAYER_REGEN_DISABLED and in the event handler it shows itself, and sets it to a certain point for example? And something is wrong with your frame_cache table, it works fine as long as you work with 1 frame, but with multiple frames you would get the wrong one back from the acquire function.

There is nothing wrong with the code. We were talking about deleting a Frame, which we established was impossible to do.

This code gives you a way to say "I no longer need this frame. Make it go away." while still giving you a way to re-claim it later if it's needed, or a create a new one if there are none currently in the cache. If you want to be sure you're dealing with the same frame every time, why in the hell would you "delete" it and then "reclaim" it? Just hide the damn thing and unregister its events, then un-hide it when you need it to be available again. Also, setting an OnEvent script like this:

Code:

        frame:SetScript("OnEvent", function() end)
...creates an empty function which uses memory that must be dealt with later by the garbage collector when it's no longer being referenced whereas simply calling

Code:

        frame:UnregisterEvent(PLAYER_REGEN_DISABLED)
or even (though, again, WHY?)

Code:

        frame:SetScript("OnEvent", nil)
are both "free" methods and do what you need without pretending that you're deleting a frame which you obviously aren't because you have to have a handle to it to "undelete" it. Always remember: There is no such thing as a magic bullet - things which appear to be usually have hidden caveats.

nightcracker 11-25-09 12:01 PM

I see, but still I think you should clean up the frame a little bit more, since once you'd want to reuse a frame you get all the rubbish hooked to it. What about this? I'm planning to release it as a lib.
LUA Code:
  1. FrameHandler = {
  2.     cache = {},
  3.     scripts = {
  4.         OnDragStart = true,
  5.         OnDragStop = true,
  6.         OnEnter = true,
  7.         OnEvent = true,
  8.         OnKeyDown = true,
  9.         OnKeyUp = true,
  10.         OnLeave = true,
  11.         OnLoad = true,
  12.         OnMouseDown = true,
  13.         OnMouseUp = true,
  14.         OnMouseWheel = true,
  15.         OnReceiveDrag = true,
  16.         OnSizeChanged = true,
  17.         OnUpdate = true,
  18.     },
  19. }
  20.  
  21. function FrameHandler:CreateFrame(parent, name, inherits)
  22.     local parent = parent or UIParent
  23.     local f = tremove(FrameHandler.cache) or CreateFrame("Frame")
  24.     if name or inherits then
  25.         local f = CreateFrame("Frame", name, parent, inherits)
  26.     else
  27.         local f = tremove(FrameHandler.cache) or CreateFrame("Frame")
  28.     end
  29.     f:SetParent(parent)
  30.     f:Show()
  31.     return f
  32. end
  33.  
  34. function FrameHandler:DeleteFrame(f)
  35.     local name = f:GetName()
  36.     f:Hide()
  37.     f:SetParent(nil)
  38.     f:UnregisterAllEvents()
  39.     f:SetID(0)
  40.     f:ClearAllPoints()
  41.     for script, _ in pairs(FrameHandler.scripts) do
  42.         f:SetScript(script, nil)
  43.     end
  44.     if name then
  45.         _G[name] = nil
  46.     end
  47.     tinsert(FrameHandler.cache, f)
  48. end

Torhal 11-25-09 02:58 PM

I do not see any benefit in having this exist as a library - the caching code is simple and small enough to be included directly within the AddOn. Also, indiscriminately setting all scripts to nil and removing the global name can cause an assortment of issues. If you're making a named frame, or setting scripts to it, you're generally going to want to keep it around so removing either makes no sense. Also, you cannot determine the intent of such a library's users - they may want the ability to safely add and remove frames for a frame factory, but not do all of the things you are doing.

The code I pasted here is ripped from my own LibQTip library, which manages its OWN frames since it knows all the attributes which are set on them. A general-purpose library that attempts to do such a thing will ultimately fail. AddOn A does this:

Code:

frame.this_is_awesome = function(self, arg1) DoStuff() end
and then releases the frame to the general-purpose frame-recycling library. AddOn B grabs that frame from the lib's cache, does other stuff to it, and shoves it back when done. After all of this modification and passing around, the frames will end up using more memory overall than a discrete AddOn-specific cache would ever dream of, since it has absolutely no knowledge of what the AddOns that use it are doing to the frames and therefore has no way to properly clean them up.

nightcracker 11-25-09 03:54 PM

Quote:

Originally Posted by Torhal (Post 167080)
I do not see any benefit in having this exist as a library - the caching code is simple and small enough to be included directly within the AddOn. Also, indiscriminately setting all scripts to nil and removing the global name can cause an assortment of issues. If you're making a named frame, or setting scripts to it, you're generally going to want to keep it around so removing either makes no sense. Also, you cannot determine the intent of such a library's users - they may want the ability to safely add and remove frames for a frame factory, but not do all of the things you are doing.

The code I pasted here is ripped from my own LibQTip library, which manages its OWN frames since it knows all the attributes which are set on them. A general-purpose library that attempts to do such a thing will ultimately fail. AddOn A does this:

Code:

frame.this_is_awesome = function(self, arg1) DoStuff() end
and then releases the frame to the general-purpose frame-recycling library. AddOn B grabs that frame from the lib's cache, does other stuff to it, and shoves it back when done. After all of this modification and passing around, the frames will end up using more memory overall than a discrete AddOn-specific cache would ever dream of, since it has absolutely no knowledge of what the AddOns that use it are doing to the frames and therefore has no way to properly clean them up.

Your right ;) (damn, sometimes that's really hard to say you know?)

Torhal 11-25-09 03:58 PM

That's why remembering that there's no such thing as a magic bullet is so important. :D


All times are GMT -6. The time now is 11:46 PM.

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