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

Touchscreen monitor bug

Started by FallenMoons, 11 May 2015 - 10:51 PM
FallenMoons #1
Posted 12 May 2015 - 12:51 AM
Trying to write a simple Open/Close door program with touch screen monitors. I was hoping to make it show a green box with white letters saying "open" when the door is closed, then when the door is open the button would be red and say "close". Simple right? Well I keep getting java thrown errors. I'm trying to set up both monitors to one computer (one monitor per side of the door) and the best way to do that would be with networking cables. So I've included a picture of my setup so you guys can understand. Thank you in advance, I'm new to Lua and Computercraft but not to programming so I will most likely be able to understand any code that you guys may right. Thanks!

My setup photo:
Spoilerhttp://gyazo.com/9ffc9186462aa1ec0c0bd42a622cd636

My code:
Spoiler

--Wrap Monitors
local om = peripheral.wrap("monitor_0") --"om" is "Outside Monitor"
local im = peripheral.wrap("monitor_1") --"im" is "Inside Monitor"

--Set Colors
local bkg = colors.black
local txt = colors.white
local btn_o = colors.red
local btn_c = colors.green
--Set Button Text
local txt_o = "Close"
local txt_c = "Open"
--Set button state
local state = 0 --0 = open 1 = closed
while true do
  --Set what color & text the button is at state
  if state==0 then
    local scolor=btn_o
    local stext=txt_o
    else
    local scolor=btn_c
    local stext=txt_c
  end
  --Draw Button
  paintutils.drawFilledBox(2,2,6,6,scolor)
 
  --Draw Button Text
  om.setCursorPos(3,4)
  im.setCursorPos(3,4)
  om.write(stext)
  im.write(stext)
  --Detect click
  event, side, x, y = os.pullEvent("monitor_touch")
    if x>2 and x<6 and y>2 and y<6 then
	  if state==0 then
	    state=1
	    else
	    state=0
	  end
    end
  om.clear()
  im.clear()
end
KingofGamesYami #2
Posted 12 May 2015 - 02:11 AM
I don't know what's throwing the java error - I'd initially thought you weren't yielding, but you are.

There are several issues with your script though.

For example,


  if state==0 then
    local scolor=btn_o
    local stext=txt_o
    else
    local scolor=btn_c
    local stext=txt_c
  end
You are defining them local to the if statement, meaning they are never set to anything outside of said statement. Instead, do something like this:


local scolor, stext
if state == 0 then
  scolor = btn_o
  stext = txt_o
else
  scolor = btn_c
  stext = txt_c
end

I'd even go as far as to use and/or, doing away with the entire if statement.

For example, you could use this for drawing your button:

paintutils.drawFilledBox(2,2,6,6, (state == 0) and btn_o or btn_c )

Of course, this is pretty much preference, so do what you understand and like.

In addition, you are redrawing the monitors every time input is detected, which isn't something you'd want to do all the time.

Instead, make a 'render' Function, which you can then when a monitor touch event is detected in the given area (and therefor needs to update).
Bomb Bloke #3
Posted 12 May 2015 - 03:13 AM
I don't know what's throwing the java error - I'd initially thought you weren't yielding, but you are.

It'll be the attempt to write nil to the monitors. Your fix should sort that.

One other issue is that paintutils.drawFilledBox() will only target the current terminal. term.redirect() can be used to change the "active" one:

  --Draw Button
  term.redirect(om)
  paintutils.drawFilledBox(2,2,6,6,scolor)
  term.redirect(im)
  paintutils.drawFilledBox(2,2,6,6,scolor)

I'd go as far as to stick the monitors into a table, and then iterate like so:

local mons = {peripheral.find("monitor")}

.
.
.

for i = 1, #mons do
  term.redirect(mons[i])
  paintutils.drawFilledBox(2,2,6,6,scolor)
  term.setCursorPos(3,4)
  term.write(stext)
end
FallenMoons #4
Posted 12 May 2015 - 03:16 AM
Thanks guys, I was on the IRC and figured some of this out. Then Lyqyd pointed me to his API. Just trying to get it to work. The only thing I can't get to work with his API is the color switching, other than that, everything works fine! Here's the code:

Spoiler

os.loadAPI("touchpoint")
local o = touchpoint.new("monitor_0")
local i = touchpoint.new("monitor_1")
local state = "open"
function toggleState()
if state == "open" then
  o:rename("Close", "Open")
  i:rename("Close", "Open")
  o:toggleButton("monitor_0")
  i:toggleButton("monitor_1")
  state = "closed"
  rs.setOutput("top", false)
else
  o:rename("Open", "Close")
  i:rename("Open", "Close")
  o:toggleButton("monitor_0")
  i:toggleButton("monitor_1")
  state = "open"
  rs.setOutput("top", true)
end
end
o:add("Close", nil, 1, 1, 7, 5, colors.red, colors.lime)
i:add("Close", nil, 1, 1, 7, 5, colors.red, colors.lime)
while true do
o:draw()
i:draw()
local event = {i:handleEvents(o:handleEvents(os.pullEvent()))}
if event[1] == "button_click" then
  toggleState()
end
end
Lyqyd #5
Posted 12 May 2015 - 04:31 AM
You said you "[g]ot it" on the IRC channel, so I'd imagine you've already figured out that the toggleButton lines need to have the current button name, not the monitor side name as the argument.
FallenMoons #6
Posted 13 May 2015 - 10:57 PM
You said you "[g]ot it" on the IRC channel, so I'd imagine you've already figured out that the toggleButton lines need to have the current button name, not the monitor side name as the argument.

Yes sir. I just had to poke around the code a bit. It's very clean and understandable BTW! Thank you!