This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Senmori's profile picture

[Lua][Question]

Started by Senmori, 03 February 2013 - 10:27 PM
Senmori #1
Posted 03 February 2013 - 11:27 PM
Title:[Lua][Question] Table not printing correctly

Ok, so after staring/derping around with this code for about 4 hours I can't figure out why my table won't work.

Before I start here's the code:
Spoiler

m = peripheral.wrap("top")

--Creates table 'menu'
local menu = {}

--Function to define 'menu' options
--'name' = name of button
--'active' determines background color
function setTable(name, xmin, xmax, ymin, ymax)
   menu[name] = {}
	 menu[name]["active"] = false
	 menu[name]["xmin"] = xmin
	 menu[name]["xmax"] = xmax
	 menu[name]["ymin"] = ymin
	 menu[name]["ymax"] = ymax
end

--Function to define table information.
function fillTable()
   setTable("Test1", 30, 40, 5,10)
   setTable("Test2", 30, 40, 15, 20)
   setTable("Test3", 30, 40, 25, 30)
end

--Function to fill the desired space
function fill(x,y,color,text)
   m.setBackgroundColor(color)
   m.setCursorPos(x,y)
   m.write(text)
   m.setBackgroundColor(colors.black)
end

--Function to change button background
--from one color to another
function bColor()
  local y = 5
  local currColor
	 for name,data in pairs(menu) do
		local on = data["active"]
		   --If then for background color
		   if on == true then
			  currColor = colors.lime
		   else
			  currColor = colors.blue
		   end
	   fill(10,y,currColor,name)
	   y = y + 5
	 end
end

--Function to change 'active' value if
--a right click is confirmed
function check(x,y)
  for name, data in pairs(menu) do
	if (y>=data["ymin"] and y<=data["ymax"]) then
	  if (x>=data["xmin"] and x<=data["xmax"]) then
		 data["active"] = not data["active"]
			print(name)
	  end --closes 'x' if
	end  --closes 'y' if
  end --closes 'for' loop
end --ends function

--On to the juicy stuff!
fillTable()
  while true do
	m.clear()
	bColor()
	local event,side,x,y = os.pullEvent("monitor_touch")
	print(x..":"..y)
	check(x,y)
	sleep(.1)
end
Pastebin: http://pastebin.com/XgM0eSv5

Problem 1: Table won't print correclty. The third button(Test3) prints above Test1 and Test2. Obviously, it needs to be below them. D:
If you can't tell. The buttons have a blue background when not active.





Problem 2: Right click (monitor_touch) on the 'Test3' button activates 'Test1' button. All other events work correctly so I don't understand how it got messed up.




So, in conclusion:

Wat?
Grim Reaper #2
Posted 04 February 2013 - 06:17 AM
Try this:



m = peripheral.wrap("top")

--Creates table 'menu'
local menu = {}

--Function to define 'menu' options
--'name' = name of button
--'active' determines background color
function setTable(name, xmin, xmax, ymin, ymax)
menu[name] = {}
  menu[name]["active"] = false
  menu[name]["xmin"] = xmin
  menu[name]["xmax"] = xmax
  menu[name]["ymin"] = ymin
  menu[name]["ymax"] = ymax
end

--Function to define table information.
function fillTable()
setTable("Test1", 30, 40, 5, 5)
setTable("Test2", 30, 40, 15, 15)
setTable("Test3", 30, 40, 25, 25)
end

--Function to fill the desired space
function fill(x,y,color,text)
m.setBackgroundColor(color)
m.setCursorPos(x,y)
m.write(text)
m.setBackgroundColor(colors.black)
end

--Function to change button background
--from one color to another
function bColor
	local currentColor = nil

	for name, option in pairs(menu) do
		currentColor = (option["active"] and colors.lime or colors.blue)
		fill(option["xmin"], option["ymin"], currentColor, name)		
	end
end

--Function to change 'active' value if
--a right click is confirmed
function check(x,y)
	for name, option in pairs(menu) do
		if x >= option["xmin"] and x <= option["xmax"] and y >= option["ymin"] and y <= option["ymax"] then
			option["active"] = not option["active"]
			return true
		end
	end

	return false
end

--On to the juicy stuff!
fillTable()
while true do
m.clear()
bColor()
local event,side,x,y = os.pullEvent("monitor_touch")
print(x..":"..y)
check(x,y)
sleep(.1)
end
Senmori #3
Posted 04 February 2013 - 07:02 AM
I assume you meant this because it worked.

--Function to change button background
--from one color to another
function bColor
	    local currentColor = nil
	    for name, option in pairs(menu) do
			    currentColor = (option["active"] and colors.lime or colors.blue)
			    fill(option["xmin"], option["ymin"], currentColor, name)			   
	    end
end
--Function to change 'active' value if
--a right click is confirmed
function check(x,y)
	    for name, option in pairs(menu) do
			    if x >= option["xmin"] and x <= option["xmax"] and y >= option["ymin"] and y <= option["ymax"] then
					    option["active"] = not option["active"]
					    return true
			    end
	    end
	    return false
end

Thanks! It seems so easy once I looked at what you changed. :/
Any idea why it was print the table wrong? I'd rather not run into this problem again.
remiX #4
Posted 04 February 2013 - 07:07 AM
It's doing this because when you check the click, it's checking if the clicked Y position is equal to the
position of ymin and ymax in the table. Now test 3 is printed on about line 5 and the Y values for Test 1
ranges from 5 - 10 and that's why it is happening.

The way you should print the values is to print them according to their own ymin and ymax values and print them between
the two values.

This is the way if you're making a button for each with a box around so people know where they are allowed
to click for the click to work.

If you're going to have it to just be able to click the text and not around, you will need to change the xmax
value to be xmin + the length of the text 'name' for each. Also, you will need to only have 1 y value
for each option.

PS: Accesing values within the table can be done by using this method as well (easier, imo)

menu = { {active = false, xmin = 3, xmax = 6, ymin = 1, ymax = 3 } }
print(menu[1].active)
-- Is the same as
print(menu[1]["active"] -- more effort :P/> but what ever suits you

Spoiler
m = peripheral.wrap("top")

--Creates table 'menu'
local menu = {}

--Function to define 'menu' options
--'name' = name of button
--'active' determines background color
function setTable(name, xmin, xmax, ymin, ymax)
	menu[name] = {}
	menu[name]["active"] = false
	menu[name]["xmin"] = xmin
	menu[name]["xmax"] = xmax
	menu[name]["ymin"] = ymin
	menu[name]["ymax"] = ymax
end

--Function to define table information.
function fillTable()
	setTable("Test1", 30, 40, 5, 10)
	setTable("Test2", 30, 40, 15, 20)
	setTable("Test3", 30, 40, 25, 30)
end

--Function to fill the desired space
function fill(x,y,color,text)
	m.setBackgroundColor(color)
	m.setCursorPos(x,y)
	m.write(text)
	m.setBackgroundColor(colors.black)
end

--Function to change button background
--from one color to another
function bColor()
	local currColor
	m.setBackgroundColour(colours.black) m.clear()
	for name, data in pairs(menu) do
		currColor = data.active and colors.lime or colours.blue
		fill(data.xmin, (data.ymax + data.ymin)/2, currColor, name)
	end
end

--Function to change 'active' value if
--a right click is confirmed
function check(x,y)
	for name, data in pairs(menu) do
		if (y>=data["ymin"] and y<=data["ymax"]) and
		(x>=data["xmin"] and x<=data["xmax"]) then
			data["active"] = not data["active"]
			print(name)
		end
	end
end

--On to the juicy stuff!
fillTable()
while true do
	bColor()
	local event,side,x,y = os.pullEvent("monitor_touch")
	print(x..":"..y)
	check(x,y)
	sleep(.1)
end

EDIT: Woops, left tab open for too long o.O
Senmori #5
Posted 04 February 2013 - 07:19 AM

menu = { {active = false, xmin = 3, xmax = 6, ymin = 1, ymax = 3 } }
print(menu[1].active)
-- Is the same as
print(menu[1]["active"] -- more effort :P/>/> but what ever suits you

That makes much more sense. D:
Thanks for the help, and the explanation. ;D

Problem solved. ;o