這是我前幾年作為學習/練習的例子。
看過與C交互後,接著來看看一個更實際應用的例子。不過不用C,來用Java。
為甚麼呢?Java自帶一個跨平台的視窗開發套組,本身也有豐富的函式庫可用,第三方函式庫也眾多,作為宿主語言是蠻好的標的。不過不直接使用原本的Lua,需要使用LuaJ。
其實最初只是因為Android App使用Java開發。而當時Android Studio編譯APK實在太慢,才會有為啥不能先用其他方式寫邏輯、開發,為啥不先嵌入一個腳本語言?才去做的一個練習,之後我使用的套件也確實有用於Android App開發上。
是的,如果你是正在開發Android,不管是以前主要用Java還是後來的Kotlin,今天應該都還是可以使用LuaJ。
LuaJ已經停滯好一段時間了,本次範例的為GitHub上另一個分支。基本上遵循Lua 5.2的規則,也就是本系列有部份是Lua 5.3、5.4的語法並不能使用於之。
本次範例主要目標:一個含有GUI的簡易計算機。其包含:
使用Lua的好處之一,在不確定要以和總平台開發前,是可以先使Lua撰寫邏輯,最後在嵌入到某個平台或框架。
first_number = 0 -- 累積數字(上個結果)
input_number = 0 -- 當前將處理數字
op = "" -- 運算操作子(+-*/)
最簡單的處理數值輸入的方式,就是當前數字乘十,在加上輸入數字:
function on_number_click(number)
input_number = input_number*10 + number
end
function on_op_click(set_op)
------------------------
-- 處理運算輸入,保存狀態
------------------------
op = set_op -- 設置運算處理
first_number = input_number -- 保留數字
input_number = 0 -- 等待新數字
end
function on_EQ_click()
------------------
-- 處理實際運算
-- 可以處理 +, -, *, /
------------------
if(op == "+")then
input_number = first_number + input_number
elseif(op == "-") then
input_number = first_number - input_number
elseif(op == "*") then
input_number = first_number * input_number
elseif(op == "/") then
input_number = first_number / input_number
else
error("op is "..op..[[, but want get "*", "+", "-" or "/"]])
end
first_number = 0
op = ""
end
pcall(dofile,"extend.txt")
※ 注意!本文程式內容是拆分說明的,你可能無法分段執行,你可以參考最後附上的完整示例。
GUI.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUI{
public static void main(String[] args){
cal c = new cal();
c.main();
}
}
class cal {
JFrame demo = new JFrame("計算機");
// JButton exitBtn = new JButton("Exit");
JPanel panel = new JPanel(new FlowLayout());
JLabel display = new JLabel("顯示器", SwingConstants.RIGHT);
JButton[] number = {
new JButton("1"),
new JButton("2"),
new JButton("3"),
new JButton("4"),
new JButton("5"),
new JButton("6"),
new JButton("7"),
new JButton("8"),
new JButton("9"),
new JButton("0")
};
JButton eqBtn = new JButton("=");
JButton cBtn = new JButton("C");
JButton acBtn = new JButton("AC");
JButton addBtn = new JButton("+");
JButton minBtn = new JButton("-");
JButton divBtn = new JButton("/");
JButton douBtn = new JButton("*");
JButton backBtn = new JButton("←");
JButton[] opBtn = {addBtn, minBtn, divBtn, douBtn};
public void main() {
demo.setSize(400, 300);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagLayout GBLayout = new GridBagLayout();
panel.setLayout(new GridBagLayout());
demo.getContentPane().add(BorderLayout.NORTH, display);
demo.add(panel);
int x = 0,y = 1;
for(JButton btn:number){
int width = 1,height = 1;
if (btn.getText().equals("0")){
x++;
}
GridBagConstraints c = new GridBagConstraints();
c.gridx = x;
c.gridy = y;
c.gridwidth = width;
c.gridheight = height;
c.weightx = 0.003;
c.weighty = 0.003;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
panel.add(btn, c);
x++;
if (x%3 == 0){
x = 0;
y++;
}
}
x = 4;
y = 1;
for(JButton btn:opBtn){
int width = 1,height = 1;
GridBagConstraints c = new GridBagConstraints();
c.gridx = x;
c.gridy = y;
c.gridwidth = width;
c.gridheight = height;
c.weightx = 0.003;
c.weighty = 0.003;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
panel.add(btn, c);
y++;
}
GridBagConstraints c = new GridBagConstraints();
c.gridx = 2;
c.gridy = 4;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 0.003;
c.weighty = 0.003;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.CENTER;
panel.add(eqBtn,c);
c.gridx = 3;
c.gridy = 0;
panel.add(cBtn,c);
c.gridx = 4;
c.gridy = 0;
panel.add(acBtn,c);
c.gridx = 0;
c.gridy = 4;
panel.add(backBtn,c);
//
demo.setVisible(true);
}
}
/****************
import LuaJ
******************/
import org.luaj.vm2.*;
import org.luaj.vm2.lib.jse.*;
/*******************************/
public void main() {
/*Loading lua evn*/
_G.get("require").call(LuaValue.valueOf("cal"));
for(JButton btn:number){
final String num = btn.getText();
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
_G.get("on_number_click").call(LuaValue.valueOf(num));
updateScreen();
}
});
}
for(JButton btn:opBtn){
final String op = btn.getText();
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
_G.get("on_op_click").call(LuaValue.valueOf(op));
updateScreen();
}
});
}
eqBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
_G.get("on_EQ_click").call();
updateScreen();
}
});
acBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
_G.get("on_AC_click").call();
updateScreen();
}
});
cBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
_G.get("on_C_click").call();
updateScreen();
}
});
backBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
_G.get("on_back_click").call();
//JOptionPane.showMessageDialog(null, "test");
updateScreen();
}
});
}
void updateScreen(){
LuaValue result = _G.get("input_number");
display.setText(result.toString());
}
JAVA-calculator可以看到完整示例,你也可以直接從Release頁面下載來使用看看。
完整示例包含一些開發測試比較方便的函數,還有讓Lua呼叫Java函數的能力的示例。
在後來,我將Lua邏輯移植到Kotlin+JavaFX裡,可以於我的GitHub頁面看到。
本文同步發表於個人網站