Gox语言例4:图形化界面(GUI)的登录对话框

Gox语言利用内置的Sciter库,可以直接编写图形界面(GUI),运行时仅需随gox主程序附带一个运行库文件(例如,Windows下是名为sciter.dll的动态运行库文件),该文件可以从Gox语言官网下载,或直接运行gox -initgui自动下载。

本例就展示了一个麻雀虽小而又五脏俱全的GUI编程示例,包括了如何使用Sciter库展示一个登录对话框,然后获取用户输入的信息后又弹出另一个对话框展示出来。下面话不多说直接上代码,当然其中有详尽的注释:

// 本例代码完整演示了在Gox语言中如何使用Sciter包
// 来显示一个图形化(GUI)的登录对话框
// 并获得用户输入的信息供以后使用
// 主要知识点包括:
// 1、初始化图形界面环境
// 2、使用HTML+TIScript来构建对话框界面和界面操作
// 3、获得屏幕大小并使对话框窗口居中的两种方法
// 4、如何从对话框获取用户录入的信息以便后续使用
// 5. Gox语言和Sciter方式的图形界面如何互相调用其中的函数
//    并进行参数传递

// 设定用到的Sciter包和screenshot包的简称
// 使用github.com/kbinani/screenshot包的原因是
// 使用其中的获取屏幕分辨率的函数
// 这是第一种让对话框居中的方法中用到的
sciter = github_scitersdk_gosciter
window = github_scitersdk_gosciter_window
screenshot = github_kbinani_screenshot

// Gox语言中使用图形化界面(GUI)编程能力时
// 均需要调用initGUI()函数来进行初始化
initGUI()

// Sciter的图形界面编程,可以简单地理解为
// 类似Electron等,用一个内置的浏览器执行
// HTML+CSS+JavaScript制作的网页作为界面
// 只不过Sciter将JavaScript换成了类似的TIScript
// 下面的htmlT就是定义了用HTML+CSS+TIScript制作的
// 登录对话框界面
// 具备JavaScript的知识的话,TIScript应该很好理解
// TIScript已经将类似JQuery的功能集成在其中了
htmlT := `
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Calculator</title>
</head>
<body>
    <div style="margin-top: 10px; margin-bottom: 10px;">
        <span>请输入用户名和密码登录……</span>
    </div>
    <div style="margin-top: 10px; margin-bottom: 10px;">
        <label for="userNameID" >用户名: </label><input id="userNameID" type=text />
    </div>
    <div style="margin-top: 10px; margin-bottom: 10px;">
        <label for="userNameID" >密码: </label><input id="passwordID" type=password />
    </div>
    <div>
        <button id="btnLoginID">登录</button>
        <button id="btnClose">关闭</button>
    </div>

    <script type="text/tiscript">
        $(#btnLoginID).on("click", function() {
            var userNameT = $(#userNameID).value.trim();
            var passwordT = $(#passwordID).value.trim();

            view.setResult(userNameT, passwordT);
            view.close();
        });
 
        $(#btnClose).on("click", function() {
            view.close();
        });
    </script>
</body>
</html>
`

// 锁定图形界面在当前线程中,以免出现异常
runtime.LockOSThread()

// 获取当前屏幕(第一块屏幕)的分辨率及区域
// 返回结果类似 image.Rectangle{Min:image.Point{X:0, Y:0}, Max:image.Point{X:1920, Y:1080}}
// 其中Max中的X、Y可以分别理解为屏幕的宽和高
bounds := screenshot.GetDisplayBounds(0)

// 计算我们准备展示的登录框的尺寸和位置
// 对话框宽高分别为400*300,然后根据屏幕尺寸
// 计算居中时对话框的x,y坐标(左上角)
w = 400
h = 300
left = bounds.Max.X/2 - w/2
top = bounds.Max.Y/2 - h/2

// 按计算的结果创建对话框窗口
w, err := window.New(sciter.DefaultWindowCreateFlag, &sciter.Rect{Left: int32(left), Top: int32(top), Right: int32(left + w), Bottom: int32(top + h)})

// 如果创建错误则中止代码执行
checkError(err)

// 加载前面设计的网页界面
// 第二个参数可以设定一个网页根路径,
// 作为页面中使用相对路径的超级链接的根路径
w.LoadHtml(htmlT, "")

// 设置窗口标题
w.SetTitle("登录窗口")

// 设置用于接收登录框中用户输入信息的变量
userNameT = ""
passwordT = ""

// 定义准备在TIScript调用的Gox语言函数
// setResult将把对话框中用户输入的
// 用户名和密码传到变量userNameT和passwordT中
w.DefineFunction("setResult", func(args) {
    // args是TIScript中调用setResult函数时传入的参数
    // 可以是多个,Gox中按位置索引进行访问
    userNameT = args[0].String()
    passwordT = args[1].String()

    // 最后一定要返回一个值,空字符串也可以
    return sciter.NewValue("")
})

// 将对话框显示出来
w.Show()

// 开始运行图形界面,以便可以接受界面操作
w.Run()

// 此处第一个对话框已经退出,
// 输出接收到的用户输入信息
pln("用户名:", userNameT, ", 密码:", passwordT)

// 在新建一个窗口,先使用默认的位置和大小(将在屏幕左上方)
// 然后在对话框加载网页是通过TIScript的代码进行位置和大小调整
w, err := window.New(sciter.DefaultWindowCreateFlag, sciter.DefaultRect)

checkError(err)

// 下面是新窗口的网页内容,其中id为mainSpanID的SPAN标签
// 演示了如何用插入字符串的方式直接将Gox语言中
// 所需传递的信息传入Sciter界面
htmlT = `
<html>
<head>
</head>
<body>
    <div>
        <span id="mainSpanID">`+spr("用户名:%v, 密码:%v", userNameT, passwordT)+`</span>
    </div>
</body>
<script type="text/tiscript">
    function moveToCenter() {
        var (w, h) = view.screenBox(#frame, #dimension)

        view.move((w-480)/2, (h-200)/2, 480, 200);

        return String.printf("%v|%v", w, h);
    }

    function self.ready() {
        $(#mainSpanID).value = view.getText();
    }
</script>

</html>
`

// 定义了getText函数演示以另一种方式传入信息到Sciter界面
// 由于self.ready()函数将在Sciter网页被加载后立即执行
// 因此本对话框中显示的信息应该是密码在前的
w.DefineFunction("getText", func(args) {
    return sciter.NewValue(spr("密码:%v, 用户名:%v", passwordT, userNameT))
})

w.LoadHtml(htmlT, "")

w.SetTitle("结果")

// 在显示对话框之前先调用TIScript定义的函数
// moveToCenter来将对话框的位置和大小改变
// 这次的大小是480*200
result, _ := w.Call("moveToCenter")

// moveToCenter函数还会返回Sciter中获取到的
// 屏幕尺寸,我们将其展示出来
listT = strSplit(result.String(), "|")

pl("屏幕宽度:%v,屏幕高度: %v", listT[0], listT[1])

w.Show()

w.Run()

代码中有详细的解释,可以看出,Gox语言制作GUI界面是非常方便的,也具有充足的(图形界面与Gox语言代码之间的)交互能力。

代码运行的效果如下:

image.png

点击登录按钮后:

image.png

把本段代码中的screenshot包去掉(因为仅在Windows下测试正常,也许是因为远程X窗口调用的关系),在Linux也可以正常运行,效果如下:

image.png

如果需要查阅Sciter的开发文档,直接去Gox官网下载sciterTools.zip包,用其中的scapp工具查看doc子目录下的main.html即是入口。包中也有Sciter界面的调试工具inspector。


注意:

  • Gox语言是脱胎于Go语言(Golang)的开源脚本语言,解释执行,但相比Go语言更贴近高级语言,语法硬性限制也少一些;是一门偏向快速应用的语言,也可以说是一个集成工具;

  • Gox语言主要优势有三点:

    • 第一,Gox语言本身只有一个可执行文件,绿色免配置,下载即可使用,无需安装Go语言环境,无需编译,非常适合快速制作原型以及云服务器上的远程开发;
    • 第二,Gox中可以直接使用绝大多数Go语言标准库中的对象和方法函数,也内置了很多常用、优秀的第三方库,充分发挥Go语言多年积累的资源优势;
    • 第三,与很多其他主流语言不同,Gox语言着力解决了GUI图形界面编程的问题,内置了基于Sciter的图形界面编程库,直接可以进行快捷高效的跨平台图形界面开发(Sciter只需下载一个动态链接库文件,执行和分发时附带上即可,放置在系统路径中或者与Gox主程序相同目录下即可),特别适合编写演示原型系统,也经历了一些中小型系统的检验,尤其是作为轻量级的微服务后台。

作为脚本语言,Gox语言性能肯定不如Go语言这样的编译型语言快,但在大多数使用场景下性能也足够用。并且,由于Gox语言与Go语言的紧密联系,Gox语言编写的脚本可以很容易的改写成Go语言代码,编译执行后就可以发挥Go语言的速度优势了。因此,Gox语言也比较适合做初期的Go语言调试。

Gox的官网在这里,也可以在浏览器搜索引擎中直接搜索“gox语言”,Github页面在这里,在这里可以看到很多Gox语言的学习指南和实际应用实例。

如果人生是一场旅行,我愿沿途播撒花朵。

推荐阅读更多精彩内容