我正在编写一个脚本,以制作可在TI Nspire CX CAS 2计算器上打开和关闭的小窗口。添加新窗口效果很好,但是尝试删除它们会导致本应删除窗口的功能完成时我的软件崩溃。我也在计算器上尝试过它,但仍然卡住了,但是我能够关闭脚本,然后重新打开它。当我重新打开它时,在第465 a picture of my calculator with the error
行出现了“ break”错误screen = platform.window
screenx,screeny = screen.width(),screen.height()
-- system stuff
local password = nil
local passVerify = nil
local drawObjects = {}
local processes = {}
local rectangle = class()
local backgroundObj = class()
local taskbar = class()
local window = class()
local process = class()
local taskbarHeight = 20
local hasBeenSetup = false
local customSetupProcedures = {}
local isLogedIn = false
local draggingMode = {
move = 0,
left = 1,
top = 2,
right = 3,
bottom = 4
}
local readyToDraw = true
local currentDraggingMode = draggingMode.both
local selectedWindowForDragging = nil
local textures = {}
local processStatus = {
waiting = 0,
running = 1,
halted = 2,
dead = 3
}
local specialColors = {
taskbarColor = 0x00969E,
windowBackgroundColor = 0xF7F7F7,
windowTopBarColor = 0xA2A2A2,
windowCloseButtonColor = 0xFF5100,
windowMaximizeButtonColor = 0x00FF00,
windowMinimizeButtonColor = 0xFFFF00
}
function process:init(run,onKill)
self.status = processStatus.waiting
self.co = coroutine.create(run)
self.onKill = onKill
coroutine.resume(self.co,self)
end
function process:update()
if self.status == processStatus.running then
coroutine.resume(self.co)
end
end
function process:halt()
self.status = processStatus.halted
end
function process:resume()
self.status = processStatus.waiting
end
function process:kill()
readyToDraw = false
self.status = processStatus.dead
self.co = nil
self.onKill()
readyToDraw = true
end
function rectangle:init(x,y,width,height)
self.x = x
self.y = y
self.width = width
self.height = height
end
function rectangle:contains(x,y)
return self.x<x and x<self.x+self.width and self.y<y and y<self.y+self.height
end
function taskbar:init()
end
function taskbar:draw(gc)
gc:setColorRGB(specialColors.taskbarColor)
gc:fillRect(0,screeny-taskbarHeight,screenx,screeny)
--gc:drawImage(textures[1],0,screeny-20)
end
function taskbar:isWindow()
return false
end
function window:init(x,y,width,height)
self.x = x
self.y = y
self.draggedOnX = 0
self.draggedOnY = 0
self.width = width
self.height = height
self.icon = nil
self.components = {}
self.focusLevel = 0
newWindowFocused(#drawObjects+1)
self.resizable = true
self:subclassInit(x,y,width,height)
end
function window:subclassInit(x,y,width,height)
end
function window:getFocusLevel()
return self.focusLevel
end
function window:draw(gc)
gc:setColorRGB(specialColors.windowBackgroundColor)
gc:fillRect(self.x,self.y,self.width,self.height)
gc:setColorRGB(specialColors.windowTopBarColor)
gc:fillRect(self.x,self.y,self.width,10)
gc:setColorRGB(specialColors.windowMinimizeButtonColor)
gc:fillRect(self.x+self.width-29,self.y+1,8,8)
gc:setColorRGB(specialColors.windowMaximizeButtonColor)
gc:fillRect(self.x+self.width-19,self.y+1,8,8)
gc:setColorRGB(specialColors.windowCloseButtonColor)
gc:fillRect(self.x+self.width-9,self.y+1,8,8)
self:drawComponents(gc)
end
function window:drawComponents(gc)
for i in ipairs(self.components) do
self.components[i]:draw(gc,self)
end
end
function window:addComponent(component)
i = #self.components+1
self.components[i] = component
return i
end
function window:decreaseFocus()
self.focusLevel = self.focusLevel+1
end
function window:isWindow()
return true
end
function window:contains(x,y)
return self.x<x and self.y < y and self.width+self.x>x and self.height+self.y>y
end
function window:checkForMouse(x,y)
if y-self.y <= 3 and self.resizable then
cursor.set('resize row')
elseif y-self.y>=self.height-3 and self.resizable then
cursor.set('resize row')
elseif x-self.x<=3 and self.resizable then
cursor.set('resize column')
elseif x-self.x>=self.width-3 and self.resizable then
cursor.set('resize column')
end
end
function window:click(x,y,n)
self:focus(n)
if y-self.y <= 3 and self.resizable then
selectedWindowForDragging = self
currentDraggingMode = draggingMode.top
elseif y-self.y>=self.height-3 and self.resizable then
selectedWindowForDragging = self
currentDraggingMode = draggingMode.bottom
elseif x-self.x<=3 and self.resizable then
selectedWindowForDragging = self
currentDraggingMode = draggingMode.left
elseif x-self.x>=self.width-3 and self.resizable then
selectedWindowForDragging = self
currentDraggingMode = draggingMode.right
elseif y-self.y <= 10 then
if x>=self.x+self.width-10 then
self:close()
elseif x>=self.x+self.width-20 then
self:maximize()
elseif x>=self.x+self.width-30 then
self:minimize()
else
selectedWindowForDragging = self
currentDraggingMode = draggingMode.move
self.draggedOnX = x - self.x
self.draggedOnY = y - self.y
end
end
self:clickComponents(x,y)
end
function window:clickComponents(x,y)
end
function newWindowFocused(n)
for window in ipairs(drawObjects) do
window = drawObjects[window]
if window:isWindow() then
if window:getFocusLevel() < n then
window:decreaseFocus()
end
end
end
end
function window:focus(n)
self.focusLevel = -1
newWindowFocused(n)
end
function window:minimize()
end
function window:maximize()
end
function window:close()
processes[1]:kill()
end
function on.resize()
screenx = screen:width()
screeny = screen:height()
end
function on.mouseDown(x,y)
minFocus = 0
for i = 0,#drawObjects,1 do
for windown in ipairs(drawObjects) do
window=drawObjects[windown]
if window:isWindow() then
if window:getFocusLevel() == minFocus then
if window:contains(x,y) then
window:click(x,y,minFocus)
return
end
minFocus = minFocus+1
end
end
end
end
end
function on.mouseMove(x,y)
cursor.set('default')
if selectedWindowForDragging ~= nil then
if currentDraggingMode == draggingMode.move then
selectedWindowForDragging.x = x - selectedWindowForDragging.draggedOnX
selectedWindowForDragging.y = y - selectedWindowForDragging.draggedOnY
if selectedWindowForDragging.x+selectedWindowForDragging.draggedOnX<5 then selectedWindowForDragging.x = 5-selectedWindowForDragging.draggedOnX end
if selectedWindowForDragging.x+selectedWindowForDragging.draggedOnX>screenx-5 then selectedWindowForDragging.x = screenx-selectedWindowForDragging.draggedOnX-5 end
if selectedWindowForDragging.y<0 then selectedWindowForDragging.y=0 end
if selectedWindowForDragging.y>screeny-taskbarHeight-5 then selectedWindowForDragging.y = screeny-taskbarHeight-5 end
elseif currentDraggingMode == draggingMode.top then
i = selectedWindowForDragging.draggedOnY + y
selectedWindowForDragging.height = math.max(selectedWindowForDragging.height - selectedWindowForDragging.draggedOnY - y + selectedWindowForDragging.y,20)
selectedWindowForDragging.y = i
elseif currentDraggingMode == draggingMode.bottom then
selectedWindowForDragging.height = math.max(y - selectedWindowForDragging.y,20)
elseif currentDraggingMode == draggingMode.left then
i = selectedWindowForDragging.draggedOnX + x
selectedWindowForDragging.width = math.max(selectedWindowForDragging.width - selectedWindowForDragging.draggedOnX - x + selectedWindowForDragging.x,20)
selectedWindowForDragging.x = i
elseif currentDraggingMode == draggingMode.right then
selectedWindowForDragging.width = math.max(x - selectedWindowForDragging.x,20)
end
end
minFocus = 0
for i = 0,#drawObjects,1 do
for windown in ipairs(drawObjects) do
window=drawObjects[windown]
if window:isWindow() then
if window:getFocusLevel() == minFocus then
if window:contains(x,y) then
window:checkForMouse(x,y)
return
end
minFocus = minFocus+1
end
end
end
end
end
function on.mouseUp(x,y)
selectedWindowForDragging = nil
end
local calculator = class(window)
function calculator:subclassInit()
self.width = 60
self.height = 90
self.resizable = false
self.number = ''
print(self.number)
self.button1 = rectangle(5,22,13,10)
self.button2 = rectangle(24,22,14,10)
self.button3 = rectangle(44,22,13,10)
self.button4 = rectangle(5,34,13,10)
self.button5 = rectangle(24,34,14,10)
self.button6 = rectangle(44,34,13,10)
self.button7 = rectangle(5,45,13,10)
self.button8 = rectangle(24,45,14,10)
self.button9 = rectangle(44,45,13,10)
self.button0 = rectangle(24,57,14,10)
self.buttonC = rectangle(5,57,13,10)
self.buttonDot = rectangle(44,57,13,10)
self.buttonPlus = rectangle(6,70,7,7)
self.buttonMinus = rectangle(15,70,7,7)
self.buttonMultiply = rectangle(40,70,7,7)
self.buttonDivide = rectangle(49,70,7,7)
self.buttonEquals = rectangle(24,69,14,8)
end
function calculator:drawComponents(gc)
--gc:drawImage(textures[2],self.x,self.y+10)
gc:setColorRGB(0x000000)
gc:setFont('sansserif','r',6)
if #self.number < 10 then
gc:drawString(string.sub(self.number,0,#self.number),self.x+5,self.y+13)
else
gc:drawString(string.sub(self.number,#self.number-9,#self.number),self.x+5,self.y+13)
print(self.number)
end
end
function calculator:clickComponents(x,y)
x = x-self.x
y = y-self.y-10
if self.button1:contains(x,y) then self.number = self.number..'1' elseif
self.button2:contains(x,y) then self.number = self.number..'2' elseif
self.button3:contains(x,y) then self.number = self.number..'3' elseif
self.button4:contains(x,y) then self.number = self.number..'4' elseif
self.button5:contains(x,y) then self.number = self.number..'5' elseif
self.button6:contains(x,y) then self.number = self.number..'6' elseif
self.button7:contains(x,y) then self.number = self.number..'7' elseif
self.button8:contains(x,y) then self.number = self.number..'8' elseif
self.button9:contains(x,y) then self.number = self.number..'9' elseif
self.button0:contains(x,y) then self.number = self.number..'0' elseif
self.buttonPlus:contains(x,y) then self.number = self.number..'+' elseif
self.buttonMinus:contains(x,y) then self.number = self.number..'-' elseif
self.buttonMultiply:contains(x,y) then self.number = self.number..'*' elseif
self.buttonDivide:contains(x,y) then self.number = self.number..'/' elseif
self.buttonDot:contains(x,y) then self.number = self.number..'.' elseif
self.buttonEquals:contains(x,y) then
if not pcall(function()self.number = ''..math.eval(self.number)end) then self.number = 'error' end
elseif
self.buttonC:contains(x,y) then self.number = '' end
end
function backgroundObj:draw(gc)
gc:setColorRGB(0xC4C4C4)
gc:fillRect(0,0,screenx,screeny-taskbarHeight)
--gc:drawImage(textures[0],screenx/2-50,(screeny-taskbarHeight)/2-50)
end
function backgroundObj:isWindow()
return false
end
function loadTextures()
--textures[0]=image.new(_R.IMG.logo)
--textures[1]=image.new(_R.IMG.startMenuButton)
--textures[2]=image.new(_R.IMG.calculator)
end
function on.construction()
timer.start(1/30)
checkForSetup()
checkForLogin()
end
function on.timer()
screen:invalidate()
end
function encrypt(str,key)
result = ''
for i = 1,#str,1 do
result = result..string.char(math.abs(string.byte(str:sub(i,i))+key+i)%422)
end
return result
end
function decrypt(str,key)
result = ''
for i = 1,#str,1 do
result = result..string.char(math.abs((string.byte(str:sub(i,i))-key-i)%422))
end
return result
end
function checkForLogin()
end
function checkForSetup()
if not hasBeenSetup then
print('loading textures...')
loadTextures()
print('setting up graphics...')
setupGraphics()
print('executing default setup procedure...')
print('setting up password...')
setupPassword()
print('executing custom setup procedures...')
for funct in ipairs(customSetupProcedures) do
funct()
end
end
hasBeenSetup = true
end
function setupGraphics()
processes[1] = process(
function(proc)
drawObjects[1] = backgroundObj()
end,
function()
drawObjects[1] = nil
end)
drawObjects[2] = taskbar()
end
function setupPassword()
w1 = calculator(50,100,100,100)
drawObjects[3] = w1
w2 = window(0,50,100,100)
drawObjects[4] = w2
end
--system stuff
--graphics stuff
function on.paint(gc)
if readyToDraw then
if drawObjects[1]~=nil then
drawObjects[1]:draw(gc)
end
focus = 0
for i in ipairs(drawObjects) do
window = drawObjects[i]
if window:isWindow() then
focus = math.max(focus,window:getFocusLevel())
end
end
while focus>=0 do
for i in ipairs(drawObjects) do
window = drawObjects[i]
if window:isWindow() and window:getFocusLevel()==focus then
window:draw(gc)
focus = focus-1
break
end
end
end
drawObjects[2]:draw(gc)
end
end
--graphics stuff
--default programs
--default programs
编辑:我刚刚发现,如果您正在学生软件中运行脚本,并且该脚本陷入循环中,则按F12会中断循环(就像实际计算器上的“主页”按钮一样。)
答案 0 :(得分:1)
您的问题是您有机会在on.paint
函数中进入无限循环。
您在此处进行检查:
if drawObjects[1]~=nil then
drawObjects[1]:draw(gc)
end
如果此检查为false
,则意味着以下for循环将运行0次,因为ipairs
希望首先查看索引1
或纾困:
focus = 0
for i in ipairs(drawObjects) do -- Will run 0 times.
window = drawObjects[i]
if window:isWindow() then
focus = math.max(focus,window:getFocusLevel())
end
end
这意味着focus >= 0
的while循环条件将无限期运行,因为在循环正文中将发生与ipairs(drawObjects)
相同的问题,并且focus
永远不会从0
改变< / p>
while focus>=0 do
for i in ipairs(drawObjects) do -- Will run 0 times.
window = drawObjects[i]
if window:isWindow() and window:getFocusLevel()==focus then
window:draw(gc)
focus = focus-1
break
end
end
end
您可以通过将focus
默认设置为-1
来解决此问题,另外,在使用drawObjects[2]
之前,您需要检查其是否为零。
或者,将支票更改为
if drawObjects[1] == nil then
return -- bail out of function we dont have anything to draw
end
drawObjects[1]:draw(gc)