GO-圖形使用者介面

super_lixiang發表於2018-09-17

 

圖形使用者介面1:初識Walk

Go與GUI——GO語言的圖形介面Walk

GO沒有原生的介面庫,所以不能直接用來寫GUI介面。但最近網際網路上已經湧現出不少成熟、好用的第三方介面庫。使用它們,就同樣可以寫出同C#、C++的介面。而且效率還更勝一籌。

關於Walk介面庫(官方介紹):Walk是一個寫給Golang的Window應用程式庫套件,它主要用於桌面GUI的開發,但也有更多的東西。

安裝Walk

在瀏覽這部分前,請確定已經配置安裝完畢go語言的環境。如果沒有,可以參考go官網的Install幫助。另外,注意:這個Walk庫只能執行在Go 1.1.x及以上。

要安裝Walk很簡單,只要執行命令:go get github.com/lxn/walk

等待命令執行完畢,這時候檢查GOPATH的src與pkg下,是否有符合自己計算機環境的walk目錄。(我的電腦的CPU架構為AMD64,則會在%GOPATH%\windows_amd64\github.com\lxn下出現一個walk資料夾與編譯完成的a檔案,另外在%GOPATH%\src\github.com\lxn下也會出現walk的原始碼)

我們還要安裝一個工具rsrc,以完成後期的打包工作,執行命令:go get github.com/akavel/rsrc 
等待命令執行完成,然後檢查,步驟與上文相仿,不再多說。

例項

匯入依賴

import (
    //引入walk包
    "github.com/lxn/walk"
    //declarative包下包含大量控制元件,加一個點:使用包內的成員時可以省略包名
    ."github.com/lxn/walk/declarative"
    "strings"
)
  • 官方的入門Demo
func main() {

    //宣告兩個文字域控制元件
    var inTE, outTE *walk.TextEdit

    //配置主視窗,並執行起來
    MainWindow{

        //視窗標題
        Title:   "尖叫的Demo",

        //可拉伸的最小尺寸
        MinSize: Size{600, 400},

        //主佈局:垂直佈局
        Layout:  VBox{},

        //視窗中的所有控制元件
        Children: []Widget{

            //水平分割器(水平小布局)
            HSplitter{

                //區域性水平排列的控制元件們
                Children: []Widget{
                    //文字輸入框
                    TextEdit{
                        //繫結到inTE變數
                        AssignTo: &inTE},

                    //文字輸出框
                    TextEdit{
                        AssignTo: &outTE,
                        //只讀的文字框
                        ReadOnly: true},
                },

            },

            //普通按鈕
            PushButton{

                //按鈕文字
                Text: "動動我試試",

                //響應函式
                OnClicked: func() {
                    inputStr := inTE.Text()
                    outputStr := strings.ToUpper(inputStr)
                    outTE.SetText(outputStr)
                },
            },

        },

    }.Run()
}

圖形使用者介面2:常用控制元件

認識幾種常用控制元件

  • 按鈕
  • 選單
  • 工具欄
  • 介面佈局
  • 列表
  • 顯示圖片

匯入依賴

import (
    "github.com/lxn/walk"
    . "github.com/lxn/walk/declarative"
    "os"
    "strings"
    "io/ioutil"
    "fmt"
    "log"
)

定義全域性資料

// 全域性應用的選單項
var myAction *walk.Action
//自定義的主視窗
var myWindow *MyMainWindow

//自定義視窗
type MyMainWindow struct {
    *walk.MainWindow
    te *walk.TextEdit

    //listbox使用的資料
    model *EnvModel
    //listbox控制元件
    listBox *walk.ListBox
}

定義列表資料模型

//環境變數條目資料模型
type EnvItem struct {
    //環境變數的名字和值
    name  string
    value string
}

//列表資料模型
type EnvModel struct {
    //繼承ListModelBase
    walk.ListModelBase

    //環境變數數集合
    items []EnvItem
}

//列表資料模型的工廠方法
func NewEnvModel() *EnvModel {
    env := os.Environ()
    m := &EnvModel{items: make([]EnvItem, len(env))}
    for i, e := range env {
        j := strings.Index(e, "=")
        if j == 0 {
            continue
        }

        name := e[0:j]
        value := strings.Replace(e[j+1:], ";", "\r\n", -1)

        m.items[i] = EnvItem{name, value}
    }

    return m
}

定義列表相關的監聽和系統回撥介面

//定義列表專案的單擊監聽
func (mw *MyMainWindow) lb_CurrentIndexChanged() {
    i := mw.listBox.CurrentIndex()
    item := &mw.model.items[i]

    mw.te.SetText(item.value)

    fmt.Println("CurrentIndex: ", i)
    fmt.Println("CurrentEnvVarName: ", item.name)
}

//定義列表專案的雙擊監聽
func (mw *MyMainWindow) lb_ItemActivated() {
    value := mw.model.items[mw.listBox.CurrentIndex()].value

    walk.MsgBox(mw, "Value", value, walk.MsgBoxIconInformation)
}

//列表的系統回撥方法:獲得listbox的資料長度
func (m *EnvModel) ItemCount() int {
    return len(m.items)
}

//列表的系統回撥方法:根據序號獲得資料
func (m *EnvModel) Value(index int) interface{} {
    return m.items[index].name
}

定義普通事件回撥

//顯示訊息視窗
func ShowMsgBox(title, msg string) int {
    return walk.MsgBox(myWindow, "天降驚喜", "你老婆跟人跑了!", walk.MsgBoxOK)
}

//一個普通的事件回撥函式
func TiggerFunc() {
    ShowMsgBox("天降驚喜", "你老婆跟人跑了!")
}

主調函式

func main() {
    defer func() {
        if err := recover(); err != nil {
            errMsg := fmt.Sprintf("%#v", err)
            ioutil.WriteFile("fuck.log", []byte(errMsg), 0644)
        }
    }()

    myWindow = &MyMainWindow{model: NewEnvModel()}

    if _, err := (MainWindow{
        AssignTo: &myWindow.MainWindow,
        Title:    "常用控制元件",

        //視窗選單
        MenuItems: []MenuItem{
            //主選單一
            Menu{
                Text: "川菜",

                //選單項
                Items: []MenuItem{
                    //選單項一
                    Action{
                        AssignTo: &myAction,
                        Text:     "魚香肉絲",
                        //選單圖片
                        Image: "img/open.png",

                        //快捷鍵
                        Shortcut: Shortcut{walk.ModControl, walk.KeyO},

                        OnTriggered: func() {
                            ShowMsgBox("已下單", "我是選單項")
                        },
                    },

                    //分隔線
                    Separator{},

                    //選單項二
                    Action{
                        //文字
                        Text: "水煮魚",

                        //響應函式
                        OnTriggered: func() {
                            ShowMsgBox("已下單", "您要的菜馬上就去買")
                        },
                    },
                },
            },

            //主選單二
            Menu{
                Text: "粵菜",

                //選單項
                Items: []MenuItem{
                    //選單項一
                    Action{

                        Text: "魚香肉絲",
                        //選單圖片
                        Image: "img/open.png",

                        //快捷鍵
                        Shortcut: Shortcut{walk.ModControl, walk.KeyO},

                        OnTriggered: func() {
                            ShowMsgBox("已下單", "我是選單項")
                        },
                    },

                    //分隔線
                    Separator{},

                    //選單項二
                    Action{
                        //文字
                        Text: "水煮魚",

                        //響應函式
                        OnTriggered: func() {
                            ShowMsgBox("已下單", "您要的菜馬上就去買")
                        },
                    },
                },
            },
        },

        //工具欄
        ToolBar: ToolBar{
            //按鈕風格:圖片在字的前面
            ButtonStyle: ToolBarButtonImageBeforeText,

            //工具欄中的工具按鈕
            Items: []MenuItem{
                //引用現成的Action
                ActionRef{&myAction},

                Separator{},
                //自帶子選單的工具按鈕
                Menu{
                    //工具按鈕本身的圖文和監聽
                    Text:        "工具按鈕2",
                    Image:       "img/document-properties.png",
                    OnTriggered: TiggerFunc,

                    //附帶一個子選單
                    Items: []MenuItem{
                        Action{
                            Text:        "X",
                            OnTriggered: TiggerFunc,
                        },
                        Action{
                            Text:        "Y",
                            OnTriggered: TiggerFunc,
                        },
                        Action{
                            Text:        "Z",
                            OnTriggered: TiggerFunc,
                        },
                    },
                },
                Separator{},

                //普通工具按鈕
                Action{
                    Text:  "工具按鈕3",
                    Image: "img/system-shutdown.png",
                    OnTriggered: func() {
                        ShowMsgBox("天降驚喜", "你老婆跟人跑了!")
                    },
                },
            },
        },

        MinSize: Size{600, 400},
        Layout:  VBox{},

        //控制元件們
        Children: []Widget{
            //水平區域性
            HSplitter{

                MinSize: Size{600, 300},
                Children: []Widget{
                    ListBox{
                        StretchFactor: 1,
                        //賦值給myWindow.listBox
                        AssignTo: &myWindow.listBox,
                        //要顯示的資料
                        Model: myWindow.model,

                        //單擊監聽
                        OnCurrentIndexChanged: myWindow.lb_CurrentIndexChanged,
                        //雙擊監聽
                        OnItemActivated: myWindow.lb_ItemActivated,
                    },
                    TextEdit{
                        StretchFactor: 1,
                        AssignTo:      &myWindow.te,
                        ReadOnly:      true,
                    },
                },
            },

            HSplitter{
                MaxSize:Size{600,50},
                Children: []Widget{
                    //影象
                    ImageView{
                        Background: SolidColorBrush{Color: walk.RGB(255, 191, 0)},
                        //圖片檔案位置
                        Image: "img/open.png",
                        //和四周的邊距
                        Margin: 5,
                        //定義最大拉伸尺寸
                        MinSize: Size{50, 50},

                        //顯示模式
                        Mode: ImageViewModeZoom,
                    },

                    //按鈕
                    PushButton{
                        StretchFactor:8,
                        Text: "摸我有驚喜",
                        OnClicked: func() {
                            ShowMsgBox("天降驚喜", "你老婆跟人跑了!")
                        },
                    },
                },
            },
        },
    }.Run()); err != nil {
        log.Fatal(err)
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相關文章