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

getting a monitor_touch to run a function while in a loop

Started by makeme, 05 March 2014 - 07:46 PM
makeme #1
Posted 05 March 2014 - 08:46 PM
I'm struggling with what is pretty much the last part of my program!

All this code is inside a while loop how can i get a function to run when a monitor is pressed in the right place?

Full Code and API


function FluPrinter(FluDetails)
local Mon = peripheral.wrap("monitor_0")
local name = FluDetails["name"]
local Amount = FluDetails["amount"]
local Cap = FluDetails["capacity"]
local X = FluDetails["XPos"]
local Y = FluDetails["YPos"]
local YBar = FluDetails["YBarPos"]
local XBar = FluDetails["XPos"]
TankSpecs = FluNamePicker(name)
local FormdName = TankSpecs["Name"]
local ActiveColor = TankSpecs["BarColor"]
local TextColor = TankSpecs["TextColor"]
Mon.setCursorPos(X, Y)
Mon.write(FormdName)
local Percent = Percentage(Amount,Cap)
PercentBar(XBar, YBar, 128, ActiveColor, TextColor, Percent, Mon)
Button = {}  --
Button["Name"] = FormdName
Button["Amount"] = Amount
Button["Capacity"] = Cap
if os.pullEvent("monitor_touch") then
MonTouch = os.pullEvent("monitor_touch")
if MonTouch[2] >= X and MonTouch[2] <= X + 10 and MonTouch[3] >= Y and MonTouch[3] <= Y + 10 then
OnPushData(Button)
else
end
else
end---
end
CometWolf #2
Posted 05 March 2014 - 08:56 PM
See comments

if os.pullEvent("monitor_touch") then -- ditch this line, as os.pullEvent will freeze the program until it get's a desired event anyways
MonTouch = os.pullEvent("monitor_touch") --thus, this will suffice, however, you need to put the return values in a table for them to actually be a table.
if MonTouch[2] >= X and MonTouch[2] <= X + 10 and MonTouch[3] >= Y and MonTouch[3] <= Y + 10 then --Also note that monitor_touch[2] is the side of the monitor, while x is 3 and y is 4, so these need changing
OnPushData(Button)
else --i assume you intend to use this for something?
end
else --thus we ditch the else end aswell
end

So, now we get

MonTouch = {os.pullEvent("monitor_touch")} -- note the {}
if MonTouch[3] >= X and MonTouch[3] <= X + 10 and MonTouch[4] >= Y and MonTouch[4] <= Y + 10 then
OnPushData(Button)
else
end

The pullEvent will however prevent the rest of your program from running. I can show you ways around this if you want to.
Edited on 05 March 2014 - 07:59 PM
makeme #3
Posted 05 March 2014 - 09:06 PM
So, now we get

MonTouch = {os.pullEvent("monitor_touch")} -- note the {}
if MonTouch[3] >= X and MonTouch[3] <= X + 10 and MonTouch[4] >= Y and MonTouch[4] <= Y + 10 then
OnPushData(Button)
else
end

The pullEvent will however prevent the rest of your program from running. I can show you ways around this if you want to.

Please could you show me away around having to wait? Thanks
CometWolf #4
Posted 05 March 2014 - 09:17 PM
Normally to prevent a pullEvent from freezeing the program, you just setup a timer so it resumes running on a set interval.

while true do
  --program code here
  os.startTimer(0.2) --start the timer
  local tEvent = {os.pullEvent()}
  if tEvent[1] == "whatever event you're looking for" then
    --code here
  elseif tEvent[1] == "timer" then
    --skip
  end
end
I have some doubts this will work here, it depends on what you want it to do. This will make the fluPrinter function end, and it will move onto the next if statement in your case.
makeme #5
Posted 05 March 2014 - 09:31 PM
Normally to prevent a pullEvent from freezeing the program, you just setup a timer so it resumes running on a set interval.

while true do
  --program code here
  os.startTimer(0.2) --start the timer
  local tEvent = {os.pullEvent()}
  if tEvent[1] == "whatever event you're looking for" then
	--code here
  elseif tEvent[1] == "timer" then
	--skip
  end
end
I have some doubts this will work here, it depends on what you want it to do. This will make the fluPrinter function end, and it will move onto the next if statement in your case.


hmmm it wont work straight off like that but I think I can make it work

also how do I print a variable in a string?
D3matt #6
Posted 05 March 2014 - 09:47 PM
Ok, first a few easy mistakes I noticed. First, you run through your setup functions every single time, which slows down the program and is bad practice, although I think I understand why you did that (To keep it updated as tanks are added/removed). Second, your lists are not named very descriptively (SingleArray1?).

Now, to the nuts and bolts of the problem. What you want to do is possible, however it will require a substantial rewrite of the program. If you want to catch events while running in a loop, you need a different method of looping. Instead of using:

while true do
  stuff()
end
You need to use:

while true do
  local event = {os.pullEvent()}
  if event == "some_event" then
    some_event(event)
  elseif event == "some_other_event" then
    some_other_event(event)
  end
end
This will loop every time an event is pulled, allowing you to check and react to every event you need to without blocking the other things in your loop. If you need to do something periodically, you can use a timer. Using functions for each event isn't necessary, but helps to keep your code neat and easier to follow and edit. In your case, you could just run your setup code once, then grab peripheral and peripheral_detach events to update your tables. Your can catch monitor_touch events to do whatever it is you wanted to do with that, and you can use timers to update your tank info periodically. Don't just run the tank update every pass through the loop, because this loop will trigger any time ANY event is pulled, whether it's one you want or not, and that will probably result in excessive running.

Hopefully this is enough to get you going, otherwise just ask and I can provide more detailed examples.
makeme #7
Posted 05 March 2014 - 10:13 PM
the SingleArray bit is left over from testing. It works fine and right now I have no reason to change it. A complete rewrite is planned once I've got it working just to clean it up its a mess atm. I've learnt a lot and this is the first large program I have made

I've got it all working with one issue when I click on the buttons it runs what I want but after less than a second switches back to the main program displaying the 4 tanks see here
Any Ideas?
Edited on 05 March 2014 - 09:14 PM
CometWolf #8
Posted 05 March 2014 - 10:24 PM
That would be this function

function OnPushData(FluDetails, Mon)
	    local FluName = FluDetails["name"]
	    local Amount = FluDetails["amount"]
	    local Cap = FluDetails["capacity"]
	    local Percent = Percentage(Amount, Cap)
	    local RPercent = Round(Percent, 2)
	    local Mon = Mon -- this line is redundant since the variable Mon is already localized to this function when you pass it
	    Mon.clear()
	    Mon.setCursorPos(5,2)
	    Mon.setTextScale(2)
	    Mon.setTextColor(colors.white)
	    Mon.write(FluName)
	    Mon.setTextScale(1)
	    Mon.setCursorPos(3,3)
	    Mon.write("" .. Amount .. "/" .. Cap .. "")
	    Mon.setCursorPos(3,4)
	    Mon.write("" .. RPercent .. "%")
	    Mon.setCursorPos(13,10)
	    Mon.setBackgroundColor(colors.red)
	    Mon.setTextColor(colors.black)
	    Mon.write("<Back")
	    Mon.setBackgroundColor(colors.black)
	    local MonTouch ={os.pullEvent("monitor_touch")}
	    if MonTouch[3] == 13 and MonTouch[4] >= 10 and MonTouch[4] <= 14 then
	    os.shell("TankMon") -- this isn't even a function. Im guessing you want shell.run()?
	    else -- what's the deal with these?
	    end
end
correct?

I can't see anything that would cause that to happen, unless you clicked the monitor twice in that one spot or something.
makeme #9
Posted 05 March 2014 - 10:28 PM
yeah Ive tried to see if it was due to double clicking its not it almost seems that the function before keeps over riding it.

Ive also cut out the stuff you noted
CometWolf #10
Posted 05 March 2014 - 10:34 PM
or well actually, it would return no matter where you clicked. Might want to change that by throwing in a while true do loop.

while true do
  local MonTouch ={os.pullEvent("monitor_touch")}
  if MonTouch[3] == 13 and MonTouch[4] >= 10 and MonTouch[4] <= 14 then
    return -- end the function
  end
end
makeme #11
Posted 05 March 2014 - 10:52 PM
Thanks thats working well apart from me getting my x and y mixed up :/