In diesem Tutorial wird nicht die Scriptsprache Lua beigebracht, sondern speziell Lua für den TI-Nspire. Wer jedoch kundig in der allgemeinen Programmierung ist, wird die Quelltexte verstehen und selbst anwenden können.
  1. Grundlagen
  2. Klassen
    1. Vererbung
    2. Polymorphie
    3. Methoden der Elternklasse aufrufen
  3. Objektlisten
  4. Texteditor
    1. Formeldarstellung
    2. Textlistener
  5. Interaktion mit dem TI-Nspire
    1. Informationsaustausch
    2. Berechnungen
  6. Quellen

Grundlagen

Lua ist eine Interpretersprache welche auf der Interpreterkonsole sozusagen ins 'Nichts' geschrieben werden kann und sofort ausgeführt wird. Zum Beispiel:

a = 1
print(a)    -- 1
a = a + 1
print(a)    -- 2

Nspire-Lua ist jedoch eventbasiert. Das heißt das Nspire-System ruft in einer Schleife und abhängig von Systemzuständen eine überschaubare Anzahl von Event-Methoden auf:

while(Exit)
-- ...
 buffer:captureDataFromKeyPad()
if buffer.charInput ~= "" then
    on.charIn(buffer.charInput)    -- Event-Methode für Zeicheneingabe
    buffer.charInput= ""
end
if buffer.arrowKey ~= "" then
    on.arrowKey(buffer.arrowKey)   -- Event-Methode für Pfeiltaste
    buffer.arrowKey = ""
end
----- etc ...  
if platform.window.isInvalidate then
    local gc = platform.gc()
     gc:begin()
     on.paint(gc)                  -- Event-Methode für Zeichenoperationen
     gc:finish()
     platform.window.isInvalidate = false
end
----- End of Event link
end
Der obige Codeblock ist Pseudo-Systemcode von Nspire und ist für die Praxis irrelevant.

Der Nutzercode kann also nicht einfach ins 'Nichts' geschrieben werden, sondern nur in die vorgegebenen Event-Methoden. Natürlich kann auch außerhalb der Event-Methoden Code geschrieben werden. Dieser Muss jedoch aus den Event-Methoden heraus aufgerufen werden. Ein Beispiel:

local text = "Hallo Welt"   -- allgemeiner Code

function on.paint(gc)
  gc:drawString(text,10,20) -- in Event aufgerufener Code
end

Die wichtigsten Event-Methoden wären:

  • on.construction() - (einmalig) Start der Anwendung
  • on.paint(gc) - Neuzeichnen des Grafikkontext gc
  • on.resize(w,h) - neue Fenstergröße
  • on.timer() - Durchlauf des Timers
  • on.charIn(char) - Eingabe eines Zeichens über die Tastatur
  • on.enterKey() / returnKey() / backspaceKey() / tabKey() / backtabKey() / deleteKey() / clearKey() / escapeKey() / arrowKey(key) - Sondertasten
  • on.arrowUp() / arrowDown() / arrowLeft() / arrowRight() - Pfeiltasten
  • on.mouseDown(x,y) / mouseUp(x,y) - Maustaste gedrückt / losgelassen
  • on.mouseMove(x,y) - Mausbewegung
  • on.getFocus() / loseFocus() - Fokus bekommen / verloren

Klassen

In Nspire Lua kann teilweise objektorientiert gearbeitet werden. Funktionen und Variablen können für eine Klasse deklariert werden, von welcher Objekte erzeugt werden können.


-- Klasse Wuerfel

Wuerfel = class()      -- Klassendeklaration 'Wuerfel'

function Wuerfel:init(x,y,size) -- Konstruktor
  self.x = x           -- Schreiben von Klassenvariablen
  self.y = y
  self.size = size
end

function Wuerfel:zeichne(gc)    -- beliebige Nutzermethode
  gc:drawRect(self.x,self.y,self.size,self.size)
end

-- Programmcode

w1 = Wuerfel(30,30,50) -- Klasseninstanz erzeugen

function on.paint(gc)
  w1:zeichne(gc)       -- Methodenaufruf von w1
end

Vererbung

A = class()
B = class(A)                   -- B erbt alles von A

function A:hello(gc)
  gc:drawString("Hello",10,20)
end

function B:world(gc)           -- für B wird nur die Funktion 'world(gc)' definiert
  gc:drawString("World",10,40)
end

function on.paint(gc)
  B:hello(gc)         -- Funktion von A geerbt
  B:world(gc)         -- Funktionen können auch direkt von der Klasse aufgerufen werden
end

Polymorphie

Der Quelltext vom Beispiel der Vererbung wird erweitert:

function B:hello(gc)           -- Klassen können Funktionen überschreiben
  gc:drawString("Holla",10,20)
end

local bi = B()

function bi:world(gc)          -- Objekte können Funktionen überschreiben
  gc:drawString("Welt",10,40)
end

function on.paint(gc)
  bi:hello(gc)                 -- Holla
  bi:world(gc)                 -- Welt
end

Methoden der Elternklasse aufrufen

A = class()
B = class(A)

function A:init(x)
  self.x = x
end

function B:init(x,y)
  A.init(self,x)      -- Konstruktor von A wird mit X aufgerufen
                     -- Beachte: Methodenaufruf mit Punkt anstatt Doppelpunkt
                     -- Funktioniert mit jeder Methode
  self.y = y
end

Objektlisten

Der Quelltext baut auf das Beispiel von Klassen auf:

w1 = Wuerfel(10,10,30)
w2 = Wuerfel(50,40,10)
w3 = Wuerfel(80,80,80)

wuerfelListe = {w1, w2, w3}              -- Liste von Würfeln

function on.paint(gc)
 for _, obj in ipairs(wuerfelListe) do  -- für jedes Wuerfel-Objekt in wuerfelListe...
    obj:zeichne(gc)
 end

 -- eine Alternative

 for i=1, #wuerfelListe do
    wuerfelListe[i]:zeichne(gc)
 end
end

Texteditor

Formeldarstellung

Durch das Umgeben der Formel mit dem Tag \0el{<formel>}

-- Hilfsmethode zur Darstellung als Formel
function box(expression)
 return "\\0el {"..expression.."}"
end

-- Hilfsmethode zum Entfernen der Formeltags
function unbox(expression)
 return (expresssion:gsub("\\0el {(.-)}","%1"))
 -- der Reguläre Ausdruck gibt nur Inhalte innerhalb der geschweiften Klammern zurück
 -- der gesamte Ausdruck (gsub) gibt mehrere Rückgabewerte zurück, daher
 -- muss er in Klammern stehen, um nur den ersten Return-Wert von gsub auszugeben
end

Textlistener

Der Changelistener als Callback-Methode selber sollte immer eine Inline-Funktion sein, da nur innerhalb der Inline-Funktion auf den Objektkontext zugegriffen werden kann. Innerhalb der Inline-Funktion können immer noch Objektmethoden aufgerufen werden, sogar mit weiteren Parametern, was über die reine Callback-Methode nicht möglich ist.

-- set text change listener
-- e.g. for printing input on console
local box = D2Editor.newRichText()
box:setTextChangeListener( function(ed) self:objMethod(ed:getExpression(), foo) end ) --- inline function

Interaktion mit dem TI-Nspire

Informationsaustausch

-- Variable in TR speichern
var.store("varName", value)

-- Variable von TR abrufen
value = var.restore("varName")

-- Funktion in TR 'speichern'
math.evalStr("f(x):=x^2/5")

Berechnungen

math.eval("3/4") -- gibt 0.75 als approximierte Zahl zurück
math.evalStr("3/4") -- gibt 3/4 als String-Ausdruck zurück

Quellen

Tags:
Erstellt von ThomasS am 2014/07/31 12:53
    
Copyright 2004-2021 XWiki
7.4.5