本文以實例來講解了在Gox語言和Gotx中使用Sciter來進(jìn)行GUI圖形界面編程時如何進(jìn)行調(diào)試断箫。
Gox語言是脫胎于Go語言(Golang)的開源腳本語言拂酣,解釋執(zhí)行,但相比Go語言更貼近高級語言仲义,語法硬性限制也少一些婶熬;是一門偏向快速應(yīng)用的語言,也可以說是一個集成工具光坝;
Gox語言主要優(yōu)勢有三點:
第一尸诽,Gox語言本身只有一個可執(zhí)行文件,綠色免配置盯另,下載即可使用性含,無需安裝Go語言環(huán)境,無需編譯鸳惯,非常適合快速制作原型以及云服務(wù)器上的遠(yuǎn)程開發(fā)商蕴;
第二,Gox中可以直接使用絕大多數(shù)Go語言標(biāo)準(zhǔn)庫中的對象和方法函數(shù)芝发,也內(nèi)置了很多常用绪商、優(yōu)秀的第三方庫,充分發(fā)揮Go語言多年積累的資源優(yōu)勢辅鲸;
第三格郁,與很多其他主流語言不同,Gox語言著力解決了GUI圖形界面編程的問題,內(nèi)置了基于Giu(imgui)例书、LCL锣尉、Sciter的三套圖形界面編程庫,直接可以進(jìn)行快捷高效的圖形界面開發(fā)(LCL决采、Sciter只需分別下載一個動態(tài)鏈接庫文件自沧,執(zhí)行和分發(fā)時附帶上即可),特別適合編寫演示原型系統(tǒng)树瞭。
作為腳本語言拇厢,Gox語言性能不如Go語言這樣的編譯型語言快,但由于Gox語言與Go語言的緊密聯(lián)系晒喷,Gox語言編寫的腳本可以很容易的改寫成Go語言代碼孝偎,編譯執(zhí)行后就可以發(fā)揮Go語言的速度優(yōu)勢了。因此凉敲,Gox語言也比較適合做初期的Go語言調(diào)試邪媳,還有一個更直接的方式是使用Gotx(在Gox官網(wǎng)上也有下載),這是使用完全和Go語言一樣語法的解釋器荡陷,可以理解成集成了Go語言標(biāo)準(zhǔn)庫和不少第三方庫的解釋執(zhí)行的Go語言,一樣也不需要搭建Go語言環(huán)境迅涮。Gotx與Gox的區(qū)別在于废赞,Gotx仍然遵循Go語言的文法,代碼相對復(fù)雜一些叮姑,限制也多一些唉地,但改寫回Go語言準(zhǔn)備編譯執(zhí)行時,基本上沒有成本传透。
Gox的官網(wǎng)在這里耘沼,也可以在瀏覽器搜索引擎中直接搜索“gox語言”,Github頁面在這里朱盐,在這里可以看到很多Gox語言的學(xué)習(xí)指南和實際應(yīng)用實例群嗤。
Gox語言和Gotx都支持使用Sciter來進(jìn)行GUI圖形界面編程,Sciter是經(jīng)過商用實踐檢驗的跨平臺界面開發(fā)包兵琳。
Sciter包主要利用HTML/CSS/TiScript來進(jìn)行圖形界面開發(fā)狂秘,可以開發(fā)本地GUI界面;Gox中通過Go語言的綁定包來與Sciter互動躯肌,可以互相傳遞數(shù)據(jù)或者調(diào)用函數(shù)者春;也可以通過Gox代碼控制界面中的DOM元素,甚至執(zhí)行回調(diào)函數(shù)清女;
Gox語言和Gotx中使用Sciter包钱烟,只需要在執(zhí)行或分發(fā)時附帶一個動態(tài)鏈接庫文件,Windows下已經(jīng)隨Gox的壓縮包一起提供了,也可以用gox -initgui或gotx -initgui命令自動獲取最新的DLL文件拴袭;Linux或MacOS下請參看這里的安裝說明读第,只需進(jìn)行前兩步安裝動態(tài)鏈接庫的步驟即可;
盡管Sciter內(nèi)置的HTML+CSS+TiScript方式與內(nèi)嵌通用WebView控件的方式有所不同稻扬,主要是不支持JavaScript卦方,但Sciter已被證明是非常優(yōu)秀的跨平臺GUI圖形界面編程庫,經(jīng)過很多公司和商用產(chǎn)品的實際檢驗泰佳,穩(wěn)定可靠盼砍。我們常見的包括TeamViewer,Symantec逝她,Vmware浇坐,Evernote,360等公司或產(chǎn)品都使用了Sciter來制作界面黔宛,可見Sciter相當(dāng)值得信賴近刘。
下面我們來看看在用Sciter制作GUI圖形界面時,如何進(jìn)行有關(guān)的調(diào)試臀晃。
Sciter包下載解壓縮后觉渴,目錄結(jié)構(gòu)大概是這樣的,
以Windows平臺為例徽惋,目前基本都已經(jīng)是64位的案淋,因此進(jìn)入bin.win文件夾中,找到x64目錄(如果是amd CPU的需要選擇amd64)险绘,
將其中的sciter.dll復(fù)制出來踢京,拷貝到Gox或者Gotx主程序所在的相同目錄,也可以復(fù)制到系統(tǒng)路徑中的目錄下宦棺,例如c:\windows\system32目錄下瓣距,這樣即可支持在Gox或Gotx中進(jìn)行Sciter圖形界面編程了。
我們來做一個最簡單的例子代咸,下面是一個用Gox語言編寫Sciter界面的代碼:
// 設(shè)置兩個Sciter包的簡稱
sciter = github_scitersdk_gosciter
window = github_scitersdk_gosciter_window
// htmlT中將是在Sciter界面中載入的HTML頁面文本
// 其中self.ready()函數(shù)類似JQuery中的$(document).ready函數(shù)
// 在其中定義了按鈕2點擊后的回調(diào)函數(shù)蹈丸,調(diào)用了Gox語言中定義的prints函數(shù)
htmlT = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Sciter演示</title>
<script type="text/tiscript">
function self.ready() {
$(#btn2).onClick = function() {
view.prints("按鈕2被點擊了");
this.html = "已點擊";
};
}
</script>
</head>
<body>
<button id="btn1">按鈕1</button>
<button id="btn2">按鈕2</button>
<button id="btn3">按鈕3</button>
</body>
</html>
`
// 鎖死GUI線程,理論上所有圖形界面操作應(yīng)該在一個線程中進(jìn)行
runtime.LockOSThread()
// 創(chuàng)建Sciter對象呐芥,并設(shè)置大小位置為默認(rèn)
w, err := window.New(sciter.DefaultWindowCreateFlag, sciter.DefaultRect)
if err != nil {
log.Fatal(err)
}
// 載入HTML文本
w.LoadHtml(htmlT, "")
// 設(shè)置圖形窗口標(biāo)題
w.SetTitle("Sciter演示")
// 設(shè)定一個Gox語言函數(shù)供TiScript中調(diào)用
// 注意輸入輸出參數(shù)的轉(zhuǎn)換方式
w.DefineFunction("prints", func(args) {
fmt.Println(args[0].String())
return sciter.NewValue("")
})
// 選擇界面中的根元素
root, _ := w.GetRootElement()
// 選取id為btn1的元素白华,即按鈕1
btn1, _ := root.SelectById("btn1")
// 設(shè)置按鈕1點擊后的Gox語言回調(diào)函數(shù)
btn1.OnClick(func() {
fmt.Println("btn1被點擊了")
btn1.SetStyle("color", "#FF0000")
fmt.Println(btn1.Html(true))
btn1.SetHtml("已點擊", sciter.SIH_REPLACE_CONTENT)
})
// 顯示Sciter圖形界面并開始運行之
w.Show()
w.Run()
代碼中注釋很詳細(xì),執(zhí)行后效果如下:
點擊按鈕1和按鈕2后贩耐,都會有相應(yīng)的反應(yīng)弧腥。
上面的例子用Gotx來編寫同樣的功能代碼(實際上就是Go語言代碼)如下:
package main
import (
"fmt"
"log"
"runtime"
"github.com/sciter-sdk/go-sciter"
"github.com/sciter-sdk/go-sciter/window"
)
func main() {
// htmlT中將是在Sciter界面中載入的HTML頁面文本
// 其中self.ready()函數(shù)類似JQuery中的$(document).ready函數(shù)
// 在其中定義了按鈕2點擊后的回調(diào)函數(shù),調(diào)用了Gotx語言中定義的prints函數(shù)
htmlT := `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Sciter演示</title>
<script type="text/tiscript">
function self.ready() {
$(#btn2).onClick = function() {
view.prints("按鈕2被點擊了");
this.html = "已點擊";
};
}
</script>
</head>
<body>
<button id="btn1">按鈕1</button>
<button id="btn2">按鈕2</button>
<button id="btn3">按鈕3</button>
</body>
</html>
`
// 鎖死GUI線程潮太,理論上所有圖形界面操作應(yīng)該在一個線程中進(jìn)行
runtime.LockOSThread()
// 創(chuàng)建Sciter對象管搪,并設(shè)置大小位置為默認(rèn)
w, err := window.New(sciter.DefaultWindowCreateFlag, sciter.DefaultRect)
if err != nil {
log.Fatal(err)
}
// 載入HTML文本
w.LoadHtml(htmlT, "")
// 設(shè)置圖形窗口標(biāo)題
w.SetTitle("Sciter演示")
// 設(shè)定一個Go語言函數(shù)供TiScript中調(diào)用
// 注意輸入輸出參數(shù)的轉(zhuǎn)換方式
w.DefineFunction("prints", func(args ...*sciter.Value) *sciter.Value {
fmt.Println(args[0].String())
return sciter.NewValue("")
})
// 選擇界面中的根元素
root, _ := w.GetRootElement()
// 選取id為btn1的元素虾攻,即按鈕1
btn1, _ := root.SelectById("btn1")
// 設(shè)置按鈕1點擊后的Go語言回調(diào)函數(shù)
btn1.OnClick(func() {
fmt.Println("btn1被點擊了")
btn1.SetStyle("color", "#FF0000")
fmt.Println(btn1.Html(true))
btn1.SetHtml("已點擊", sciter.SIH_REPLACE_CONTENT)
})
// 顯示Sciter圖形界面并開始運行之
w.Show()
w.Run()
}
用Gotx來執(zhí)行這段代碼后的效果也是完全一樣的:
下面來說如何調(diào)試,由于Gox語言和Gotx是基本類似的(從前面代碼也可以看出來更鲁,除了開頭的包聲明和引用聲明霎箍,兩者區(qū)別主要在prints函數(shù)的定義上,Gox語言中無需指定參數(shù)類型澡为,也無需指定返回值)漂坏,因此下面將僅以Gotx代碼即Go語言(Golang)為例來演示。
首先媒至,如果準(zhǔn)備將調(diào)試信息都輸出到命令行界面上顶别,可以直接用上面例子中定義的prints方法。在Gox語言或Gotx中定義的函數(shù)拒啰,傳遞給Sciter后驯绎,均可以直接作為全局對象view的成員函數(shù)調(diào)用。由于這樣定義的函數(shù)谋旦,參數(shù)需要做類型轉(zhuǎn)換剩失,因此實現(xiàn)printf這樣的可變個數(shù)參數(shù)存在問題,所以最好TiScript中實現(xiàn)可變參數(shù)處理册着,TiScript也是功能齊全的腳本語言拴孤,處理這些自然不成問題。這樣的話甲捏,prints函數(shù)不用變乞巧,在TiScript則將輸出信息時的語句改成類似下面的即可:
view.prints(String.printf("按鈕2被點擊了: %s", new Date()));
這里使用了TiScript中的String對象的printf函數(shù),功能類似于其他語言中的sprintf函數(shù)摊鸡,支持可變參數(shù),Date對象則是獲取當(dāng)前系統(tǒng)時間用的蚕冬,執(zhí)行效果如下:
然后免猾,Sciter也支持類似一般瀏覽器中的開發(fā)者調(diào)試模式,這需要使用Sciter提供的調(diào)試工具Inspector囤热,這個工具也是隨著Sciter SDK包下載時附帶在其中的猎提。
還是以64位Windows為例,在Sciter SDK包解壓縮后的bin.win/x32子目錄下可以找到inspector.exe這個就是Sciter提供的調(diào)試工具Inspector了旁蔼。
注意锨苏,即使是64位Windows,也需要到32位的目錄下找到這個工具棺聊。運行它之后伞租,看到下面的界面,就可以開始調(diào)試Sciter代碼了限佩。
在Inpector啟動的界面上葵诈,已經(jīng)有了如何使用的簡單說明裸弦,最主要有兩個方式讓Sciter程序連接Inspector,第一是直接在運行圖形界面程序時按Ctrl-Shift+I組合鍵即可作喘,第二則是在TiScript中加上如下的代碼:
if (view.connectToInspector) {
view.connectToInspector(rootElement, inspectorIpAddress);
}
例如理疙,我們剛才的例子程序運行時,按Ctrl+Shift+I組合鍵就可以看到Inspector中展現(xiàn)了如下的界面泞坦。
熟悉Web開發(fā)的人馬上就會知道這就是很熟悉的開發(fā)者調(diào)試界面了窖贤,可以查看Sciter界面的HTML的DOM樹與CSS等,也有控制臺贰锁。與一般的Web調(diào)試界面和Javascript不同的是赃梧,Sciter中向控制臺輸出的腳本命令有所不同。
我們來修改按鈕2的點擊回調(diào)函數(shù)為:
$(#btn2).onClick = function() {
view.prints(String.printf("按鈕2被點擊了: %s", new Date()));
stdout.println("1 + 2 = ", 1+2);
var result = 1.61 / 2.23;
debug info ( result = {result});
debug alert ( this is a warning {2*5});
this.html = "已點擊";
};
再次執(zhí)行Gotx例子代碼并點擊按鈕2之后看到Inspector中控制臺的輸出如下:
Sciter調(diào)試中李根,在TiScript中支持stdout槽奕、stderr和stdin,而它們和一般語言一樣支持printf房轿、pringln等函數(shù)粤攒,可以在控制臺輸出信息。
另外囱持,Sciter不支持Javascript中的console.log()函數(shù)夯接,但支持功能更強的debug關(guān)鍵字,格式是:
debug [log | info | warning | alert] : <space-separated-list-of-expressions> ;
或者
debug [log | info | warning | alert] ( <stringizer-function-parameters> )
第二種寫法使用到了Sciter支持的特殊的stringizer寫法纷妆,在后面括號中盔几,無需像其他語言中一樣給字符串加上雙引號,直接寫就行了掩幢,花括號中才是需要替換的變量或者表達(dá)式逊拍。請仔細(xì)參看例子中的寫法。
debug也支持log际邻、info芯丧、warning世曾、alert四種類型的信息缨恒,分別用不同的圖標(biāo)來表示。