[GO language foundation] Go language GUI programming: GTK2, GTK+3 and QT (15)

Article Directory

GUI programming

Many mature and easy-to-use third-party GUI interface libraries have emerged on the Internet.
https://github.com/avelino/awesome-go#gui

GTK2

GTK+ is an object-oriented API (applicationprogramming interface). Glib is the foundation of GTK+, and this "object-oriented system" is provided by "Glib". GTK+ is a function library used to help make graphical interactive interfaces, and it also complies with the LGPL license.
GTK2: https://github.com/mattn/go-gtk

  • Tool: Glade
  1. layout

Insert picture description here

Common control selection area: Lists commonly used controls. There are three commonly used controls: top layer (main window, etc.), container (various layout containers, etc.), control and display (buttons, notes, picture controls, etc.)

Interface editing area: Drag and drop the controls here to carry out the corresponding layout

Control monitoring area: you can see all the controls on the interface, and at the same time, select this control, you can see the specific type of this control

Attribute editing area: Edit the common attributes of the selected control, such as window setting title, window type, display position on the screen, etc.

Toolbar: The following buttons are commonly used

New: Create a new glade file.
Open: Open an existing glade file.
Save: Save a glade file.
Select: Press this button to select the control.
Drag and resize: Press this button to move the position of the control and change the control's size. size

  1. Glade operation

When selecting a control, you must first press the "Select" button on the toolbar
. When operating, it supports window shortcuts such as undo (Ctrl+z) and restore (Ctrl+y)

The process of operation and layout are the same:

1. Select the main window and set the corresponding properties of the window as needed

  1. Choose a layout container
  2. Select the corresponding control according to your needs, and set the corresponding properties of the control according to your needs
  • Environment setup (windows)
  1. Download and install msys2

Official website: http://www.msys2.org/

  1. Install required software
    安装gtk3:
    pacman -S mingw-w64-x86_64-gtk3

    安装gtk2:
    pacman -S mingw-w64-x86_64-gtk2

    安装glade
    pacman -S mingw-w64-x86_64-glade

    安装帮助文档
    pacman -S mingw-w64-x86_64-devhelp

    安装MinGW
    pacman -S mingw-w64-x86_64-toolchain base-devel
  1. Configure environment variables
    配置:
    PATH:
    C:\msys64\usr\bin
    C:\msys64\mingw64\bin

    测试:
    pkg-config --cflags gtk+-2.0
    make -v
  1. Download dependency
    //官方
    # go get github.com/mattn/go-gtk/gtk

    //国内  放在GOPATH目录src下
    # git clone  https://github.com/mattn/go-gtk
    # cd go-gtk
    # make install
    # make example
    # ./example/demo/demo
  1. Run the official demo
    # cd $GOPATH/github.com/mattn/go-gtk/example/demo
    # go build demo.go
    # demo.exe

Insert picture description here

  1. Import dependencies
    import (
        "github.com/mattn/go-gtk/gdkpixbuf"
        "github.com/mattn/go-gtk/glib"
        "github.com/mattn/go-gtk/gtk"
    )
  • Control

Controls are the encapsulation of data and methods. The control has its own properties and methods. Attributes refer to the characteristics of the control. Methods refer to some simple and visible functions of the control

The controls in GTK are mainly divided into two categories: container controls and non-container controls.

  1. Container control: It can hold other controls, we can understand it as a box, and the box is used to hold things. Container controls are divided into two categories. One category can only hold one control, such as windows and buttons; the other category can hold multiple controls, such as layout controls.
  2. Non-container control: It cannot hold other controls, such as label and row editing.
Put:
func (v *Fixed) Put(w IWidget, x, y int)
功能:固定布局容器添加控件
参数:
    widget:要添加的控件
    x, y:控件摆放位置的起点坐标

ShowAll:
func (v *Widget) ShowAll()
功能:显示所有的控件,如果窗口放入一个容器,这时,容器上的所有控件也会跟着显示。
package main

import (
    "os"
    "github.com/mattn/go-gtk/gtk"
)

func main() {
    gtk.Init(&os.Args)
    /*
        gtk.Init(&os.Args):所有 GTK应用程序都要调用该函数,
        而且必须在控件定义之前使用,它为我们设置一些缺省值
        ( 例如视觉和颜色 )映射这个函数将函数库初始化,设置
        缺省的信号处理函数,并检查通过命令行传递给应用程序的
        参数,自动完成一些必要的初始化工作。
    */

    //--------------------------------------------------------
    // 主窗口
    //--------------------------------------------------------
    window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
    /*
        gtk.NewWindow(gtk.WINDOW_TOPLEVEL):创建一个窗口并
        返回这个窗口的控件指针。gtk.WINDOW_TOPLEVEL指明窗口
        的类型为最上层的主窗口(则带边框的窗口),它最常用。
    */
    window.SetPosition(gtk.WIN_POS_CENTER)       //设置窗口居中显示
    window.SetTitle("Minor Six Ren")                   //设置标题
    window.SetSizeRequest(300, 200)              //设置窗口的宽度和高度

    //--------------------------------------------------------
    // GtkFixed
    //--------------------------------------------------------
    layout := gtk.NewFixed() //创建固定布局

    //--------------------------------------------------------
    // GtkButton
    //--------------------------------------------------------
    b1 := gtk.NewButton() //新建按钮
    b1.SetLabel("^_@")    //设置内容
    //b1.SetSizeRequest(100, 50) //设置按钮大小

    b2 := gtk.NewButtonWithLabel("@_~") //新建按钮,同时设置内容
    b2.SetSizeRequest(100, 50)          //设置按钮大小

    //--------------------------------------------------------
    // 添加布局、添加容器
    //--------------------------------------------------------
    window.Add(layout) //把布局添加到主窗口中

    layout.Put(b1, 0, 0)    //设置按钮在容器的位置
    layout.Move(b1, 50, 50) //移动按钮的位置,必须先put,再用move

    layout.Put(b2, 50, 100)

    window.ShowAll() //显示所有的控件
    /*
        window.Show():显示上一步创建的窗口控件。
        window.ShowAll():显示所有的控件,如果窗口放入一个容器,这时,容器上的所有控件也会跟着显示

在这个简单例子里,所有事件都被忽略。用鼠标点击窗口右上角的“×”按钮也不能将窗口关闭。可通过任务管理器关闭。
    */

    gtk.Main() //主事件循环,等待用户操作
    /*
        gtk.Main():它是在每个Gtk应用程序都要调用的
        函数。程序运行停在这里等待事件(如键盘事件或
        鼠标事件)的发生,等待用户来操作窗口。
    */
}
  • Signal processing
    "signal" can be regarded as a sign of interruption in GTK
Signal identification Triggering conditions
clicked Triggered when the button is pressed
pressed Triggered when the button is pressed
released Triggered when the button is released
destroy Triggered when the close window button is pressed
信号注册函数说明:

func (v *Widget) Connect(s string, f interface{}, datas ...interface{}) int
功能:信号注册
参数:
    v: 信号发出者,可以认为我们操作的控件,如按下按钮,这个就为按钮指针
    s:信号标志,如"pressed"
    f:回调函数的名称,
    datas:给回调函数传的参数,尽管是可变参数,但是只能传递一个参数,可变参数的目的为了让用户多个选择(可以传参,或者不传)
返回值:
    注册函数的标志
    package main
    import (
        "fmt"
        "os"

        "github.com/mattn/go-gtk/glib"
        "github.com/mattn/go-gtk/gtk"
    )

    //按钮b1信号处理的回调函数
    func HandleButton(ctx *glib.CallbackContext) {
        arg := ctx.Data()   //获取用户传递的参数,是空接口类型
        p, ok := arg.(*int) //类型断言
        if ok {             //如果ok为true,说明类型断言正确
            fmt.Println("*p = ", *p) //用户传递传递的参数为&tmp,是一个变量的地址
            *p = 250                 //操作指针所指向的内存
        }
        fmt.Println("按钮b1被按下")

        //gtk.MainQuit() //关闭gtk程序
    }

    func main() {
        gtk.Init(&os.Args)

        window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
        window.SetPosition(gtk.WIN_POS_CENTER)
        window.SetTitle("GTK Go!")
        window.SetSizeRequest(300, 200)
        layout := gtk.NewFixed()

        b1 := gtk.NewButton()
        b1.SetLabel("按钮1")

        b2 := gtk.NewButtonWithLabel("按钮2")
        b2.SetSizeRequest(100, 50)

        window.Add(layout)
        layout.Put(b1, 0, 0)
        layout.Move(b1, 50, 50) //移动按钮的位置,必须先put,再用move
        layout.Put(b2, 50, 100)

        //--------------------------------------------------------
        // 信号处理
        //--------------------------------------------------------
        //按钮按下自动触发"pressed",自动调用HandleButton, 同时将 &tmp 传递给HandleButton
        tmp := 10
        b1.Connect("pressed", HandleButton, &tmp)

        //回调函数为匿名函数,推荐写法
        //按钮按下自动触发"pressed",自动调用匿名函数,
        b2.Connect("pressed", func() {
            fmt.Println("b2被按下")
            fmt.Println("tmp = ", tmp)
        }) //注意:}和)在同一行

        window.ShowAll()

        gtk.Main()
    }

GTK+3

GTK+3:https://github.com/gotk3/gotk3

    import (
        "github.com/gotk3/gotk3/glib"
        "github.com/gotk3/gotk3/gtk"
    )

package main

import (
    "fmt"
    "github.com/gotk3/gotk3/glib"
    "github.com/gotk3/gotk3/gtk"
    "log"
    "os"
)

//这部分是相同的
func main() {
    const appId = "com.guidemo.example"
    //每个gtk3程序都需要一步
    app, err := gtk.ApplicationNew(appId, glib.APPLICATION_FLAGS_NONE)
    /*
        gtk.ApplicationNew()接受两个参数一个是 应用标识,其一般
        使用你域名的倒序形式。另一个是GApplicationFlags,其为了
        满足你对应用的特定需求。通常就像实例代码一样写
        glib.APPLICATION_FLAGS_NONE就可以了。
    */

    if err != nil {
        log.Fatal("Could not create application.", err)
    }

    //为activate事件绑定函数, activate会在程序启动时触发,也就是app.Run()时
    app.Connect("activate", func() {
        onActivate(app)
    } )

    //运行gtkApplication
    app.Run(os.Args)
}


func onActivate(application *gtk.Application) {
    appWindow, err := gtk.ApplicationWindowNew(application) //创建window控件
    if err != nil {
        log.Fatal("Could not create application window.", err)
    }
    //设置窗口属性
    appWindow.SetTitle("Basic Application.")
    appWindow.SetDefaultSize(400, 400)

    buttonBox, err := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2)     //以水平布局创建一个容器, 第二个参数是其中控件的像素间隔
    if err != nil {
        log.Fatal(err)
    }
    appWindow.Add(buttonBox)    //将布局添加到window中

    button, err := gtk.ButtonNewWithLabel("Hello World")        //创建一个按钮
    if err != nil {
        log.Fatal(err)
    }
    buttonBox.Add(button)       //将按钮添加到box容器中

    button.Connect("clicked", func() {  //让我们为按钮点击添加一个函数,每次点击都会在命令行输出Hello World
        fmt.Println("Hello World")
        appWindow.Destroy()     //摧毁窗口
    })


    appWindow.ShowAll()     //与Show()不同在于,它会输出Window中的子控件。你可以修改,查看不同的效果
}

QT

QT: https://github.com/therecipe/qt
Reference: https://github.com/therecipe/qt/wiki/Installation

  • installation
  1. Install the complete Qt5 in the $HOME directory
    https://download.qt.io/official_releases/online_installers/

  2. Configure Qt's environment

# ~/.bash_profile
# therecipe/qt 需要的环境变量
export QT_DIR='/home/用户名/Qt5.11.1' # 安装Qt的目录
export QT_VERSION='5.11.1'           # Qt的版本号
export QT_DEBUG=false                # 是否启用debug
export QT_STUB=false                 # 内存低于2Gb或32位系统才需要设置true

# go1.10 cgo environments 使用go1.10时需要的设置
export CGO_CXXFLAGS_ALLOW=".*"
export CGO_LDFLAGS_ALLOW=".*"
export CGO_CFLAGS_ALLOW=".*"

  1. Completion of dependencies:

g++5.0+ and some OpenGL dependencies

# Debian/Ubuntu的安装命令
sudo apt-get -y install build-essential libglu1-mesa-dev libpulse-dev libglib2.0-dev

# Fedora/RHEL/CentOS
sudo yum -y groupinstall "C Development Tools and Libraries"
sudo yum -y install mesa-libGLU-devel gstreamer-plugins-base pulseaudio-libs-devel glib2-devel

# openSUSE
sudo zypper -n install -t pattern devel_basis

# Arch Linux
sudo pacman -S base-devel

Install qt-tools:

go get -u -v github.com/therecipe/qt/cmd/...

Install bindings and remember to stay away from sudo! ! ! (Longer time)

$GOPATH/bin/qtsetup

  • Compile
    reference: https://github.com/therecipe/qt/wiki/Available-Tools

You cannot use go build directly, because qt uses moc technology (meta-object compiler), and additional processing is required for some of the extended syntax of Qt

qtdeploy build [target] [path/to/your/project]

说明:
target是指定的目标平台,编译完成后的程序将可以在target指定的平台上运行。

    如果也可以将target设为desktop,qtdeploy将会根据本地环境选择相对应的target。以下是部分可用的target选项:
                    desktop
                    windows
                    linux
                    android
                    android-emulator
                    ios
                    ios-simulator
                    sailfish
                    sailfish-emulator
                    rpi1
                    rpi2
                    rpi3

Guess you like

Origin blog.csdn.net/weixin_54707168/article/details/114006114