2 posts
Posted 06 December 2017 - 05:12 PM
Hi,
I am making a Big Reactors management program.
This is my problem: I want to be able to press monitor buttons (next screen, settings, etc) while frequently updating (1Hz) the monitor with new statistics.
As far as I can tell, the os.pullEvent("monitor_touch") blocks further code from executing until it has received a monitor touch event.
Is there any way I can keep updating the screen and receiving button presses?
I have thought of the following but do not know how to code them (or if they are actually possible at all):
- interrupts that execute a function when an event has happened, like the attachInterrupt(pin, function) for Arduino's and other microcontrollers
- parallel programming: a separate thread waits for an event while the main thread handles the updating stuff
Do you have any experience with this problem?
1220 posts
Location
Earth orbit
Posted 07 December 2017 - 12:29 AM
You don't need to filter for an event when you capture it - you can do the filtering afterward like so…
local event, data, x, y = os.pullEvent()
if event == "monitor_touch" then
--# do monitor touch stuff - x and y are the touch coords
elseif event == "updateTriggerEvent"
--# update values and screens, etc.
end
3057 posts
Location
United States of America
Posted 07 December 2017 - 12:30 AM
If you call os.pullEvent without a parameter, it will return any event.
Example:
while true do
local tEvent = {os.pullEvent()}
print( "An event of type " .. tEvent[ 1 ] .. " has occurred" )
end
Assuming you are currently using sleep to update the monitor, it may be useful to
view the actual declaration of sleep
7083 posts
Location
Tasmania (AU)
Posted 07 December 2017 - 12:57 AM
If you're using
touchpoint, then you might integrate in
os.startTimer() like so:
local timerDelay = 1
local myTimer = os.startTimer( timerDelay )
while true do
local event, p1 = t:handleEvents( os.pullEvent() )
if event == "button_click" then
-- Handle button clicks here.
elseif event == "timer" and p1 == myTimer then
-- Update displays here.
myTimer = os.startTimer( timerDelay )
end
end
467 posts
Location
Van Diemen's Land
Posted 07 December 2017 - 05:17 AM
If you call os.pullEvent without a parameter, it will return any event.
Example:
while true do
local tEvent = {os.pullEvent()}
print( "An event of type " .. tEvent[ 1 ] .. " has occurred" )
end
Assuming you are currently using sleep to update the monitor, it may be useful to
view the actual declaration of sleep
Well, isn't that frustrating?
Calling sleep() clears your events because it's going through all those events!
It would be useful if you stored those events in a table and then queued them all again after the sleep() function has completed. Might not work well for longer sleep times but I haven't tested it.
477 posts
Location
Germany
Posted 07 December 2017 - 06:15 AM
If you call os.pullEvent without a parameter, it will return any event.
Example:
while true do
local tEvent = {os.pullEvent()}
print( "An event of type " .. tEvent[ 1 ] .. " has occurred" )
end
Assuming you are currently using sleep to update the monitor, it may be useful to
view the actual declaration of sleep
Well, isn't that frustrating?
Calling sleep() clears your events because it's going through all those events!
It would be useful if you stored those events in a table and then queued them all again after the sleep() function has completed. Might not work well for longer sleep times but I haven't tested it.
That would be a terrible idea to be honest.
Imagine a program with a GUI you can click in using sleep, if it captures the mouse_click events during the sleep a user might click randomly in the GUI to check if the program is hanging. All these clicks will then be used by the program and some strange stuff might happen.
If you really wanted to you could override the sleep function:
function sleep( nTime )
local tEvents = {}
if nTime ~= nil and type( nTime ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( nTime ) .. ")", 2 )
end
local timer = os.startTimer( nTime or 0 )
local tEvent
repeat
tEvent = {os.pullEvent()}
tEvents[#tEvents+1] = tEvent
until tEvent[1] == "timer" and tEvent[2] == timer
tEvents[#tEvents] = nil --Remove the last entry which is the timer event from sleep
for _,v in ipairs(tEvents) do
os.queueEvent(unpack(v))
end
end
2 posts
Posted 07 December 2017 - 03:30 PM
If you really wanted to you could override the sleep function
I just found this:
https://github.com/sandalle/minecraft_bigreactor_control/blob/master/lolmer_bigreactor_monitor_prog.lua#L1387-L1399It seems a bit more simple than your suggestion Luca, but the repeat […] until seems more appropiate here so I'll replace the while loop with that, and the 'event[2] == timer' piece with >= in case it misses the exact second for whatever reason.
Thanks!
(but there really isn't a built-in interrupt function?)
467 posts
Location
Van Diemen's Land
Posted 08 December 2017 - 12:04 AM
That would be a terrible idea to be honest.
Imagine a program with a GUI you can click in using sleep, if it captures the mouse_click events during the sleep a user might click randomly in the GUI to check if the program is hanging. All these clicks will then be used by the program and some strange stuff might happen.
If you really wanted to you could override the sleep function:
I thought that too at first, but then realised that it would only store the event queue it had BEFORE it started pulling them, not DURING or AFTER.
477 posts
Location
Germany
Posted 08 December 2017 - 05:53 AM
I'm unsure what you mean. Every event before sleep() is send to the program and can be retrieved via os.pullEvent()
7083 posts
Location
Tasmania (AU)
Posted 08 December 2017 - 06:46 AM
I'll replace … and the 'event[2] == timer' piece with >= in case it misses the exact second for whatever reason.
Timers don't work like that -
read the documentation again.