Very often, displaying information in table form generally means creating a frame/button for each row where each row is broken up into sections (columns), and then positioning each row one below the next so they form a table. Then you loop through the rows and update the columns.
It's very common to do this with a scrollframe too, which allows your table to be scrollable.
The code that follows adds a /showme slash command to summon a scrollable table of random data. (You can repeat /showme to generate new random data.)
When the number of rows has the potential to far exceed the displayable area, it's common to use a HybridScrollFrameTemplate or FauxScrollFrameTemplate. Then you only have as many rows that can be displayed and you update the content based on the scrollbar offset. In the example below I've doing a basic scrollframe where every row is defined so you don't need to worry about offsets. (This is not suggested for long lists, but probably easier to pick apart.)
Lua Code:
local CELL_WIDTH = 100
local CELL_HEIGHT = 20
local NUM_CELLS = 3 -- cells per row
-- we'll use an ordered table of arbitrary data: {{fruit,number,alphabet},{fruit,number,alphabet},etc}
local fruits = {"apple","banana","orange","pear","tomato","pineapple"}
local numbers = {"one","two","three","four","five","six"}
local alphabet = {"abc","def","ghij","klmn","op","qrstuv","wx","yz"}
local data = {}
-- just generates a random bunch of data in the data table
local function updateData()
wipe(data)
for i=1,10+random(40) do
tinsert(data,{fruits[random(#fruits)], numbers[random(#numbers)], alphabet[random(#alphabet)]})
end
end
-- creating a basic dialog frame (if you name this frame and define basic bits during the load (not after PLAYER_LOGIN), then
-- the client will restore the window position on login to wherever it was last moved by the user)
local f = CreateFrame("Frame","SimpleScrollFrameTableDemo",UIParent,"BasicFrameTemplateWithInset")
f:SetSize(CELL_WIDTH*NUM_CELLS+40,300)
f:SetPoint("CENTER")
f:Hide()
f:SetMovable(true)
f:SetScript("OnMouseDown",f.StartMoving)
f:SetScript("OnMouseUp",f.StopMovingOrSizing)
-- adding a scrollframe (includes basic scrollbar thumb/buttons and functionality)
f.scrollFrame = CreateFrame("ScrollFrame",nil,f,"UIPanelScrollFrameTemplate")
f.scrollFrame:SetPoint("TOPLEFT",12,-32)
f.scrollFrame:SetPoint("BOTTOMRIGHT",-34,8)
-- creating a scrollChild to contain the content
f.scrollFrame.scrollChild = CreateFrame("Frame",nil,f.scrollFrame)
f.scrollFrame.scrollChild:SetSize(100,100)
f.scrollFrame.scrollChild:SetPoint("TOPLEFT",5,-5)
f.scrollFrame:SetScrollChild(f.scrollFrame.scrollChild)
-- adding content to the scrollChild
local content = f.scrollFrame.scrollChild
content.rows = {} -- each row of data is one wide button stored here
local function updateList()
for i=1,#data do
-- create a row if not created yet (buttons[i] is a whole row; buttons[i].columns[j] are columns)
if not content.rows[i] then
local button = CreateFrame("Button",nil,content)
button:SetSize(CELL_WIDTH*NUM_CELLS,CELL_HEIGHT)
button:SetPoint("TOPLEFT",0,-(i-1)*CELL_HEIGHT)
button.columns = {} -- creating columns for the row
for j=1,3 do
button.columns[j] = button:CreateFontString(nil,"ARTWORK","GameFontHighlight")
button.columns[j]:SetPoint("LEFT",(j-1)*CELL_WIDTH,0)
end
content.rows[i] = button
end
-- now actually update the contents of the row
for j=1,3 do
content.rows[i].columns[j]:SetText(data[i][j])
end
-- show the row that has data
content.rows[i]:Show()
end
-- hide all extra rows (if list shrunk, hiding leftover)
for i=#data+1,#content.rows do
content.rows[i]:Hide()
end
end
-- create /showme slash command to make up data and summon window
SLASH_SHOWME1 = "/showme"
SlashCmdList["SHOWME"] = function(msg)
updateData()
updateList()
f:Show()
end