01-21-12, 08:35 AM | #1 |
Help creating scroll frame
Hello,
After spending lots of hours, I'm still stuck with creating a scrolling message frame. I've solved several issues, but I still got two majors ones: 1. When the scrolling frame is loaded and some messages are added to it, I get "0" for GetNumLinesDisplayed(). I need a correct value in order to set correctly the slider SetMinMaxValues(). If I print the GetNumLinesDisplayed() on some events, I then get correct value. What should I do in order to get the correct value when constructing the scrolling message frame? Note that GetNumMessages() does return the correct value. 2. I can't make the frame hide when hitting "escape". I've tried to use tinsert(UISpecialFrames, "historyFrame"), but it juse hide my frame and I can't get to show it. I will appreciate any help, I'm really stuck here. This is my code (can be copied and run as standalone code): Code:
local historyFrame = CreateFrame("Frame", "historyFrame", UIParent) historyFrame.width = 500 historyFrame.height = 250 historyFrame:SetFrameStrata("FULLSCREEN_DIALOG") historyFrame:SetSize(historyFrame.width, historyFrame.height) historyFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 0) historyFrame:SetBackdrop({ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", tile = true, tileSize = 32, edgeSize = 32, insets = { left = 8, right = 8, top = 8, bottom = 8 } }) historyFrame:SetBackdropColor(0, 0, 0, 1) historyFrame:EnableMouse(true) historyFrame:EnableMouseWheel(true) -- Make movable/resizable historyFrame:SetMovable(true) historyFrame:SetResizable(enable) frame:SetMinResize(100, 100) historyFrame:RegisterForDrag("LeftButton") historyFrame:SetScript("OnDragStart", frame.StartMoving) historyFrame:SetScript("OnDragStop", frame.StopMovingOrSizing) historyFrame:SetScript("OnLoad", function(self) print(self:GetName()) end) --tinsert(UISpecialFrames, historyFrame) -- Close button local closebutton = CreateFrame("Button", nil, historyFrame, "UIPanelButtonTemplate") closebutton:SetScript("OnClick", function(self) HideParentPanel(self) end) closebutton:SetPoint("BOTTOM", 0, 10) closebutton:SetHeight(25) closebutton:SetWidth(70) closebutton:SetText(CLOSE) -- ScrollingMessageFrame local historyScrollingMessage = CreateFrame("ScrollingMessageFrame", historyScrollingMessage, historyFrame) historyScrollingMessage:SetPoint("CENTER", 15, 20) historyScrollingMessage:SetSize(historyFrame.width, historyFrame.height - 50) historyScrollingMessage:SetFontObject(GameFontNormal) historyScrollingMessage:SetTextColor(1, 1, 1, 1) -- default color historyScrollingMessage:SetJustifyH("LEFT") historyScrollingMessage:SetHyperlinksEnabled(true) historyScrollingMessage:SetFading(false) historyScrollingMessage:SetMaxLines(300) historyScrollingMessage:Clear() historyScrollingMessage:AddMessage("1 Here is a message!") historyScrollingMessage:AddMessage("2 Here is a message!") historyScrollingMessage:AddMessage("3 Here is a message!") historyScrollingMessage:AddMessage("4 Here is a message!") historyScrollingMessage:AddMessage("5 Here is a message!") historyScrollingMessage:AddMessage("6 Here is a message!") historyScrollingMessage:AddMessage("7 Here is a message!") historyScrollingMessage:AddMessage("8 Here is a message!") historyScrollingMessage:AddMessage("9 Here is a message!") historyScrollingMessage:AddMessage("10 Here is a message!") historyScrollingMessage:AddMessage("11 Here is a message!") historyScrollingMessage:AddMessage("12 Here is a message!") historyScrollingMessage:AddMessage("13 Here is a message!") historyScrollingMessage:AddMessage("14 Here is a message!") historyScrollingMessage:AddMessage("15 Here is a message!") historyScrollingMessage:AddMessage("16 Here is a message!") historyScrollingMessage:AddMessage("17 Here is a message!") historyScrollingMessage:AddMessage("18 Here is a message!") historyScrollingMessage:AddMessage("19 Here is a message!") historyScrollingMessage:AddMessage("20 Here is a message!") historyScrollingMessage:AddMessage("21 Here is a message!") historyScrollingMessage:AddMessage("22 Here is a message!") historyScrollingMessage:AddMessage("23 Here is a message!") historyScrollingMessage:AddMessage("24 Here is a message!") historyScrollingMessage:AddMessage("25 Here is a message!") --historyScrollingMessage:ScrollToBottom() --historyScrollingMessage:ScrollDown() print (historyScrollingMessage:GetNumMessages(), historyScrollingMessage:GetNumLinesDisplayed()) ------------------------------------------------------------------------------- -- Scroll bar ------------------------------------------------------------------------------- local ScrollBar = CreateFrame("Slider", "ScrollBar", historyFrame, "UIPanelScrollBarTemplate") ScrollBar:ClearAllPoints() ScrollBar:SetPoint("RIGHT", historyFrame, "RIGHT", -10, 10) ScrollBar:SetSize(30, historyFrame.height - 90) ScrollBar:SetMinMaxValues(0, 9) ScrollBar:SetValueStep(1) ScrollBar.scrollStep = 1 ScrollBar:SetScript("OnValueChanged", function(self, value) historyScrollingMessage:SetScrollOffset(select(2, ScrollBar:GetMinMaxValues()) - value) end) ScrollBar:SetValue(select(2, ScrollBar:GetMinMaxValues())) historyFrame:SetScript("OnMouseWheel", function(self, delta) print (historyScrollingMessage:GetNumMessages(), historyScrollingMessage:GetNumLinesDisplayed()) local cur_val = ScrollBar:GetValue() local min_val, max_val = ScrollBar:GetMinMaxValues() if delta < 0 and cur_val < max_val then cur_val = math.min(max_val, cur_val + 1) ScrollBar:SetValue(cur_val) elseif delta > 0 and cur_val > min_val then cur_val = math.max(min_val, cur_val - 1) ScrollBar:SetValue(cur_val) end end) |
|
01-22-12, 03:31 AM | #2 | ||
When cross-posting on WoWInterface and WowAce, you should usually link to the other thread. Many people read and post on both forums, so linking will prevent people from spending 20 minutes reading your post and writing code for you when someone already did the same in the other thread.
See also: http://forums.wowace.com/showthread.php?t=19881
Some other general comments about your code, in no particular order: (1) I'd advise against using "historyFrame" as the global name for your frame. Give it a name that makes it immediately obvious which addon controls it, like AnimorHistoryFrame. Also, names beginning with a lowercase letter are conventionally used for local variables, while object names begin with an uppercase letter. It doesn't really matter, but it helps other programmers reading your code if you stick to common conventions. (2) You should definitely not give your scrollbar a global name of "ScrollBar". Not only is this horrible for debugging and error reporting, but it's also extremely likely to conflict with other addons that are poorly written and/or inadvertently leaking variables into the global namespace. (3) Variable names in Lua are case-sensitive, so you cannot write "scrollBar" in one place and "ScrollBar" in another place. The only reason this works is because you assigned "ScrollBar" as the global name of the object you assigned to the local variable "scrollBar", so both names happened to refer to the same thing. (4) You have an error on line 24 of your code. You wrote frame:SetMinResize(100, 100), but frame is not defined; this looks like it was meant to be a reference to historyFrame instead. (5) OnLoad scripts don't work for frames created in Lua. Just write any code you want to execute immediately in the main chunk after you create the frame. (6) Your panel is not a true "UI panel" with all of the relevant attributes set, so you should not call HideParentPanel(self) to close it; just call self:GetParent():Hide() instead. (7) You should provide some way to programmatically access your buttons and widgets. Either pass a string as the second parameter to CreateFrame to give them a global name (slow and sloppy way) or add them as members of your main frame's table (fast and clean way): Code:
local closebutton = CreateFrame("Button", nil, historyFrame, "UIPanelButtonTemplate") ... historyFrame.closeButton = closebutton Code:
local frame = CreateFrame("Frame", "AnimorHistoryFrame", UIParent) frame.width = 500 frame.height = 250 frame:SetFrameStrata("FULLSCREEN_DIALOG") frame:SetSize(frame.width, frame.height) frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0) frame:SetBackdrop({ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", tile = true, tileSize = 32, edgeSize = 32, insets = { left = 8, right = 8, top = 8, bottom = 8 } }) frame:SetBackdropColor(0, 0, 0, 1) frame:EnableMouse(true) frame:EnableMouseWheel(true) -- Make movable/resizable frame:SetMovable(true) frame:SetResizable(enable) frame:SetMinResize(100, 100) frame:RegisterForDrag("LeftButton") frame:SetScript("OnDragStart", frame.StartMoving) frame:SetScript("OnDragStop", frame.StopMovingOrSizing) tinsert(UISpecialFrames, "AnimorHistoryFrame") -- Close button local closeButton = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") closeButton:SetPoint("BOTTOM", 0, 10) closeButton:SetHeight(25) closeButton:SetWidth(70) closeButton:SetText(CLOSE) closeButton:SetScript("OnClick", function(self) HideParentPanel(self) end) frame.closeButton = closeButton -- ScrollingMessageFrame local messageFrame = CreateFrame("ScrollingMessageFrame", nil, frame) messageFrame:SetPoint("CENTER", 15, 20) messageFrame:SetSize(frame.width, frame.height - 50) messageFrame:SetFontObject(GameFontNormal) messageFrame:SetTextColor(1, 1, 1, 1) -- default color messageFrame:SetJustifyH("LEFT") messageFrame:SetHyperlinksEnabled(true) messageFrame:SetFading(false) messageFrame:SetMaxLines(300) frame.messageFrame = messageFrame for i = 1, 25 do messageFrame:AddMessage(i .. ". Here is a message!") end --messageFrame:ScrollToBottom() --messageFrame:ScrollDown() print(messageFrame:GetNumMessages(), messageFrame:GetNumLinesDisplayed()) ------------------------------------------------------------------------------- -- Scroll bar ------------------------------------------------------------------------------- local scrollBar = CreateFrame("Slider", nil, frame, "UIPanelScrollBarTemplate") scrollBar:SetPoint("RIGHT", frame, "RIGHT", -10, 10) scrollBar:SetSize(30, frame.height - 90) scrollBar:SetMinMaxValues(0, 9) scrollBar:SetValueStep(1) scrollBar.scrollStep = 1 frame.scrollBar = scrollBar scrollBar:SetScript("OnValueChanged", function(self, value) messageFrame:SetScrollOffset(select(2, scrollBar:GetMinMaxValues()) - value) end) scrollBar:SetValue(select(2, scrollBar:GetMinMaxValues())) frame:SetScript("OnMouseWheel", function(self, delta) print(messageFrame:GetNumMessages(), messageFrame:GetNumLinesDisplayed()) local cur_val = scrollBar:GetValue() local min_val, max_val = scrollBar:GetMinMaxValues() if delta < 0 and cur_val < max_val then cur_val = math.min(max_val, cur_val + 1) scrollBar:SetValue(cur_val) elseif delta > 0 and cur_val > min_val then cur_val = math.max(min_val, cur_val - 1) scrollBar:SetValue(cur_val) end end) SLASH_AHF1 = "/ahf" SlashCmdList.AHF = function() if AnimorHistoryFrame:IsShown() then AnimorHistoryFrame:Hide() else AnimorHistoryFrame:Show() end end |
|||
01-22-12, 07:08 AM | #3 |
Thank you so much for this. I learned a lot from your comments about good practice in programming, you should write a guide with these conventions!
About GetNumLinesDisplayed - it looks like it's giving the correct result if I use it after Show(). However, when I originally used this function right after the frame construction, it gave "0". I don't really understand it. Two questions, if I may: 1. Because of tinsert(UISpecialFrames, "AnimorHistoryFrame"), the frame was hidden by default when I reload. However, when I've added AnimorHistoryFrame:Show() to the bottom of the code, it didn't work - nothing happened. But when I used the slash command you coded for me, with the same function, the frame did show. Why is that? 2. What is the difference between HideParentPanel(self) and self:GetParent():Hide(), and why I should not use the first? Thanks again! Last edited by Animor : 01-22-12 at 08:40 AM. |
|
01-23-12, 05:02 PM | #4 | ||
HideParentPanel will still hide the frame if none of those conditions are met, but it will add unnecessary overhead. It's more efficient to just hide the frame directly, since after all of the extra checks that aren't relevant to your frame, that's all HideParentPanel will do anyway. |
|||
01-24-12, 05:41 AM | #5 |
Thank you!
|
|
WoWInterface » Developer Discussions » Lua/XML Help » Help creating scroll frame |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|