【留档备查】Gox语言中使用OpenGL库进行GUI图形界面编程-GX24

由于Gox 1.56a版本之后已经不支持Giu库,因此本文档仅用作留存参考

Gox中使用Giu库进行GUI图形界面编程比较方便,唯一需要注意的是该库依赖于GLFW和OpenGL,有些虚拟机可能不支持,此时,Gox语言也支持LCL库(请参见本系列有关文章),如何选择可以按自己所需考虑。

Gox中使用该库引用gui包即可,也是无需全路径名。

我们直接来看例子,实现一个简单计算器的代码如下:

// text1 used to hold the string value of the text input
// notice: text1 is a pointer
text1 = new(string)

onButton1Click = fn() {
    // evaluate the expression in the text input
    rs = eval(*text1)

    // set the result back into the text input
    setValue(text1, rs)//string(rs)
}

// close the window, also terminate the application
onButton2Click = fn() {
    exit()
}

// main window loop
loop = fn() {

    // set the layout of GUI
    layoutT = []gui.Widget{
        gui.Label("Enter an expression."), 
        gui.InputText("", 0, text1), 

        // widgets in line layout is aligned left to right 
        gui.Line(gui.Button("Calculate", onButton1Click), 
            gui.Button("Close", onButton2Click)),
    }

    gui.SingleWindow("Calculator", layoutT)
}

// setup the title, size (width and height, 400*200), style and font-loading function of main window, 
mainWindow = gui.NewMasterWindow("Calculator", 400, 200, gui.MasterWindowFlagsNotResizable, nil)

// show the window and start the message loop
gui.LoopWindow(mainWindow, loop)


执行的效果如下:

界面布局的代码很好理解,具体界面控件的文档和例子请参考Giu的Github页面。另外需要注意,text1是一个字符串指针,所以取值要用“*”,而设置值需要用setValue内置函数。

下面是一个简单的代码编辑器的例子,支持中文,支持文件的打开、保存和另存,支持命令行打开代码,支持代码加密解密和运行,唯一不足大概就是还不支持语法高亮和代码自动完成了:

argsG = os.Args

lenT = len(argsG)

editFileNameG = ""
editFileCleanFlagG = ""
editSecureCodeG = new(string)

fcT = ""

if lenT < 3 {
    editFileNameG = ""
    editFileCleanFlagG = "*"
} else {
    editFileNameG = argsG[2]
    fcT = tk.LoadStringFromFile(editFileNameG)

    if tk.IsErrorString(fcT) {
        gui.SimpleError("错误提示", "载入文件时发生错误:%v", tk.GetErrorString(fcT))
        return
    }

    editFileCleanFlagG = ""

}


// hold the text in main edit control
text1 = new(string)

setValue(text1, fcT)

onEditChange = func() {
    editFileCleanFlagG = "*"
}

onButtonLoad = func() {
    if editFileCleanFlagG != "" {
        rs = gui.GetConfirm("请确认", "文件已被修改,确认要打开另一个文件吗?")

        if rs == false {
            return
        }
    }

    fileNameNewT = gui.SelectFile("请选择要打开的文件", "所有文件", "*")

    if tk.IsErrorString(fileNameNewT) {
        if tk.EndsWith(fileNameNewT, "Cancelled") {
            gui.MessageBox("信息", tk.Spr("操作被用户取消"))
            return
        }

        gui.MessageBox("错误提示", tk.Spr("选择文件失败:%v", tk.GetErrorString(fileNameNewT)))
        return
    }

    fcT = tk.LoadStringFromFile(fileNameNewT)

    if tk.IsErrorString(fcT) {
        gui.MessageBox("错误提示", tk.Spr("载入文件内容失败:%v", tk.GetErrorString(fileNameNewT)))
        return
    }

    editFileNameG = fileNameNewT
    
    setValue(text1, fcT)

    editFileCleanFlagG = ""

}

onButtonRunClick = func() {
    rs = runScript(*text1, "")

    gui.MessageBox("运行结果", tk.Spr("%v", rs))
}

editorSaveAs = func() {
    fileNameNewT = gui.SelectSaveFile("请选择要保存的文件", "所有文件", "*")

    if tk.IsErrorString(fileNameNewT) {
        if tk.EndsWith(fileNameNewT, "Cancelled") {
            gui.MessageBox("信息", tk.Spr("操作被用户取消"))
            return
        }

        gui.MessageBox("错误提示", tk.Spr("选择文件失败:%v", tk.GetErrorString(fileNameNewT)))
        return
    }

    editFileNameG = fileNameNewT

    rs1 = tk.SaveStringToFile(*text1, editFileNameG)

    if rs1 != "" {
        gui.MessageBox("错误提示", tk.Spr("保存文件失败:%v", rs))
        return
    }

    gui.MessageBox("信息", tk.Spr("文件已被保存至:%v", editFileNameG))

    editFileCleanFlagG = ""

}

editorSave = func() {
    if editFileNameG == "" {
        editorSaveAs()

        return
    }

    rs = false

    if tk.IfFileExists(editFileNameG) {
        rs = gui.GetConfirm("请确认", "文件已存在,是否要覆盖?")
    }

    if rs == true {
        rs1 = tk.SaveStringToFile(*text1, editFileNameG)

        if rs1 != "" {
            gui.MessageBox("错误提示", tk.Spr("保存文件失败:%v", rs))
            return
        }

        gui.MessageBox("信息", tk.Spr("文件已被保存至:%v", editFileNameG))

        editFileCleanFlagG = ""
    }

}

editEncrypt = func() {
    gui.CloseCurrentPopup()

    sourceT = *text1

    encStrT = tk.EncryptStringByTXDEF(sourceT, *editSecureCodeG)

    if tk.IsErrorString(encStrT) {
        gui.SimpleError("错误提示", tk.Spr("加密失败:%v", tk.GetErrorString(encStrT)))
        return
    }

    setValue(text1, "//TXDEF#" + encStrT)
    editFileCleanFlagG = "*"

    setValue(editSecureCodeG, "")
}

editEncryptClick = func() {
    gui.OpenPopup("请输入密码##EncryptInputSecureCode")
}

editDecrypt = func() {
    gui.CloseCurrentPopup()

    sourceT = tk.Trim(*text1)

    encStrT = tk.DecryptStringByTXDEF(sourceT, *editSecureCodeG)

    if tk.IsErrorString(encStrT) {
        gui.SimpleError("错误提示", tk.Spr("解密失败:%v", tk.GetErrorString(encStrT)))
        return
    }

    setValue(text1, encStrT)
    editFileCleanFlagG = "*"
    setValue(editSecureCodeG, "")

}

editDecryptClick = func() {
    gui.OpenPopup("请输入密码##DecryptInputSecureCode")
}


onButtonCloseClick = func() {
    exit()
}

loop = func() {

    layoutT = make(gui.Layout)

    layoutT = append(layoutT, gui.Label(editFileNameG + editFileCleanFlagG))
    layoutT = append(layoutT, gui.InputTextMultiline("InputTextMultiline001", text1, -1, -30, 0, nil, onEditChange))
    layoutT = append(layoutT, gui.Line(gui.Button("打开", onButtonLoad), gui.Button("保存", editorSave), gui.Button("另存为", editorSaveAs), gui.Button("加密", editEncryptClick), gui.Button("解密", editDecryptClick), gui.Button("运行", onButtonRunClick), gui.Button("关闭", onButtonCloseClick)))

    layoutT = append(layoutT, gui.PopupModal("请输入密码##EncryptInputSecureCode", []gui.Widget{gui.Line(gui.Label("密码"), gui.InputTextV("", 40, editSecureCodeG, gui.InputTextFlagsPassword, nil, nil)),
        gui.Line(gui.Button("确定", editEncrypt), gui.Button("取消", func() { gui.CloseCurrentPopup() })),
    }))

    layoutT = append(layoutT, gui.PopupModal("请输入密码##DecryptInputSecureCode", []gui.Widget{
        gui.Line(gui.Label("密码"),
            gui.InputTextV("", 40, editSecureCodeG, gui.InputTextFlagsPassword, nil, nil)),
        gui.Line(gui.Button("确定", editDecrypt),
            gui.Button("取消", func() { gui.CloseCurrentPopup() })),
    }))


    // add this to the layout if you would use gui.MessageBox function later
    layoutT = append(layoutT, gui.PrepareMessageBox())

    gui.SingleWindow("Gox编辑器", layoutT)
}

osNameT = tk.GetOSName()

if tk.Contains(osNameT, "darwin") {
    setVar("Font", "/Library/Fonts/Microsoft/SimHei.ttf")
} else {
    setVar("Font", "c:/Windows/Fonts/simsun.ttc")
}

setVar("FontRange", "COMMON")
setVar("FontSize", "15")

mainWindow = gui.NewMasterWindow("Gox编辑器", 800, 600, 0, gui.LoadFont)

gui.LoopWindow(mainWindow, loop)

运行效果如下:

注意,代码中的text1用于存放代码,editSecureCodeG用于存放密码框密码,都需要使用字符串指针,留意它们的写法。

最后,注意图形界面编程的统一禁忌是:只能在一个线程中操作图形界面。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269