常用控件集合

本章介绍并学习路线中弹窗之前(包含弹窗)的所有控件

一、认识控件

本章将要学习的控件列表如下图所示,逐一讲解使用方法;

go语言项目实战 go 语言 gui_golang

二、预备知识

2.1 控件结构体中通用字段

  • AssignTo :绑定该控件类型指针,目的是后续业务中可以控制该控件属性;
  • ToolTipText :作用是当鼠标移到该控件时,会浮窗显示提示信息;

三、控件使用

3.1 TextLabel

TextLabel{
	AssignTo: &myMain.TextLabel,
	Text:     "我是文本标签",
},

3.2 TextEdit

TextEdit{
	AssignTo:   &myMain.TextEdit,
	Text:       "我是文本框",
	ReadOnly:   false, // false:文本框只读  true:文本框可读可写
	ColumnSpan: 9,
},

3.3 Label

Label{
	AssignTo: &myMain.Label,
	Text:     "我是标签",
},

3.4 NumberLabel

NumberLabel{
	AssignTo: &myMain.NumberLabel,
	Value:    float64(521), //警告:这里给的默认值,一定要强转为int64,否则NumberLabel.Create时,断言失败就是0了。
},

3.5 NumberEdit

NumberEdit{
	AssignTo: &myMain.NumberEdit,
	Value:    float64(10), //警告:这里给的默认值,一定要强转为int64,否则NumberLabel.Create时,断言失败就是0了。
},

3.6 LineEdit

LineEdit{
	AssignTo:  &myMain.LineEdit,
	Text:      "我是行编辑",
	TextColor: walk.Color(walk.RGB(100, 100, 100)),
	Enabled:   true, // false:文本框只读  true:文本框可读可写
	PasswordMode: true, //可选,输入内容后密文,显示******
	MaxLength: 5, //设置最大输入字符数
	TextColor:walk.RGB(218, 8, 9),//设置文本颜色
	ReadOnly: true,//设置文本只读
},
// 获取输入框内容
myMain.LineEdit.Text()

3.7 CheckBox

CheckBox{
	AssignTo:    &myMain.CheckBox,
	Text:        "复选框",
	ToolTipText: "单选、复选框",
	Checked:     true,  //注意:true 默认选中,false:默认未选
},
// 在事件触发接口中,实现多个单选框使用时逻辑:
func OK_Clicked() {
	switch {
	case myMain.CheckBox_english.Checked():
		le.SetText("英语系")
	case myMain.CheckBox_sport.Checked():
		le.SetText("体育系")
	case myMain.CheckBox_maths.Checked():
		le.SetText("数学系")
	}
}

3.8 PushButton

PushButton{
	Text: "按钮",
	OnClicked: func() {
		walk.MsgBox(nil, "我是弹框", "测试button", walk.MsgBoxIconInformation)
		// 此处实现你想要做的业务
		// ......
	},
},

3.9 ComboBox

第一种,简单用法,默认显示选中苹果
ComboBox{
	AssignTo:     &myMain.ComboBox,
	Model:        []string{"苹果", "草莓", "香蕉"}, //下拉菜单数据源
	CurrentIndex: 0, // 默认显示model数据的索引
	// 选中下拉菜单中某个选项时触发
	OnCurrentIndexChanged: func() {
		// 打印最新索引id
		logger.Println(myMain.ComboBox.CurrentIndex())
	},
},
第二种,绑定数据
animal := new(Animal)
Composite{
	DataBinder: DataBinder{
		AssignTo:       &db,
		Name:           "animal",
		DataSource:     animal,
		ErrorPresenter: ToolTipErrorPresenter{},
	},
	Layout: Grid{Columns: 2},
	Children: []Widget{
		ComboBox{
            // 和DataBinder.DataSource字段关联,当前则是关联animal.SpeciesId字段,即选择下拉菜单中id对应值刷新到DataBinder.DataSource字段中
            // SelRequired{} 作用是约束该选项不允许为空,否则会强制提示;
			Value:         Bind("SpeciesId", SelRequired{}), 
			BindingMember: "Id", // 绑定数据字段名(和Model字段关联)
			DisplayMember: "Name", // 显示数据字段名(和Model字段关联)
			Model:         KnownSpecies(),
		},
		PushButton{
			AssignTo: &acceptPB,
			Text:     "OK",
			// 手动更新绑定数据,点击OK按钮时才更新
			OnClicked: func() {
				walk.MsgBox(nil, "修改前", fmt.Sprintf("%+v", animal), walk.MsgBoxIconInformation)
				// 此处手动提交更新绑定数据
				if err := db.Submit(); err != nil {
					log.Print(err)
					return
				}
				walk.MsgBox(nil, "结果", fmt.Sprintf("%+v", animal), walk.MsgBoxIconInformation)
			},
		},
	},
},

type Animal struct {
	Name          string
	ArrivalDate   time.Time
	SpeciesId     int
	Speed         int
	Sex           Sex
	Weight        float64
	PreferredFood string
	Domesticated  bool
	Remarks       string
	Patience      time.Duration
}

type Species struct {
	Id   int
	Name string
}
func KnownSpecies() []*Species {
	return []*Species{
		{1, "Dog"},
		{2, "Cat"},
		{3, "Bird"},
		{4, "Fish"},
		{5, "Elephant"},
	}
}

3.10 RadioButton

RadioButton{
	AssignTo:    &myMain.RadioButton,
	Text:        "单选按钮",
	ToolTipText: "单选按钮",
},

3.11 RadioButtonGroup

// 首先定义该按钮要绑定的数据结构
type Fool struct {
	Bar string
	Baz int
}
// 声明一个变量
fooBox := Fool{"box", 0}
Composite{
	Layout: HBox{},
	DataBinder: DataBinder{
		DataSource: &foo, // 变量名 此处必须是指针
		Name:       "foo",// 变量名
		AutoSubmit: true,// 自动提交,意思是选中后,变量fooBox.Baz 字段值会自动更新;
		// 每次操作选中后,自动触发该接口调用,所以对应业务就可以在这里实现,案例中只是打印了变量内容;
		OnSubmitted: func() {
			logger.Printf("foo:%v", foo)
		},
	},
	Children: []Widget{
		RadioButtonGroup{
			DataMember: "Baz",//指定绑定变量中的字段名,和上面的DataBinder是配套的;
			Buttons: []RadioButton{
				RadioButton{
					Name:  "oneRB",
					Text:  "one", //界面显示的选项名
					Value: 1, // 选择选项后的值,此处绑定的是fooBox.Baz字段值
				},
				RadioButton{
					Name:  "twoRB",
					Text:  "two",
					Value: 2,
				},
				RadioButton{
					Name:  "threeRB",
					Text:  "three",
					Value: 3,
				},
			},
		},
	},
},

3.12 RadioButtonGroupBox

用法逻辑:
        1. 根据业务创建自己的结构体,例如
                 type Fool struct
                        Bar string
                        Baz int
                 }
       2. 创建一个结构体变量fooBox ;
       3. 将该结构体变量中的字段和按钮进行绑定,比如Baz字段;
       4.当点击按钮选中时,变量fooBox 的字段值就会被更新;

// 首先定义该按钮要绑定的数据结构
type Fool struct {
	Bar string
	Baz int
}
// 声明一个变量
fooBox := Fool{"box", 0}
// 创建控件
Composite{
	Layout: HBox{},
	// 绑定数据
	DataBinder: DataBinder{
		DataSource: &fooBox, //变量名,此处必须是指针
		Name:       "fooBox",//变量名
		AutoSubmit: true,    //自动提交,意思是选中后,变量fooBox.Baz 字段值会自动更新;
		// 每次操作选中后,自动触发该接口调用,所以对应业务就可以在这里实现,案例中只是打印了变量内容;
		OnSubmitted: func() {
			logger.Printf("foo:%v", fooBox)
		},
	},
	Children: []Widget{
		RadioButtonGroupBox{
			Title:      "box",//组框的名称,界面会显示
			Layout:     HBox{},
			DataMember: "Baz", //指定绑定变量中的字段名,和上面的DataBinder是配套的;
			Buttons: []RadioButton{
				{Text: "Male", Value: 5},// Text按钮名称,Value按钮对应点击后的值
				{Text: "Female", Value: 6},
				{Text: "Hermaphrodite", Value: 7},
			},
		},
	},
},

3.13 TableView

追加:表格记录右键子菜单功能

go语言项目实战 go 语言 gui_golang_02

mdTableView := NewStudentModel()
Composite{
	Layout: HBox{},
	// 该节点作用是添加表格右键子菜单
	ContextMenuItems: []MenuItem{
		Action{
			Text: "I&nfo",
			// OnTriggered: mw.tv_ItemActivated,
		},
		Action{
			Text: "E&xit",
			OnTriggered: func() {
				//此处实现逻辑
				// mw.Close()
			},
		},
	},
	Children: []Widget{
		TableView{
			AssignTo:         &myMain.TableView,
			ToolTipText:      "表格数据",
			ColumnsOrderable: true, // 列支持排序
			MultiSelection:   true, // 可以同时选中多行
			// 表格内容列
			Columns: []TableViewColumn{
				{Title: "序号"},
				{Title: "姓名"},
				{Title: "年龄"},
				{Title: "录入时间", Width: 200}},//可单独指定某列宽度
			Model: mdTableView,//绑定数据源
		},
	},
},

type StudentInfo struct {
	SeqNo      int  // 序号
	Name       string // 名字
	Age        int // 年龄
	CreateTime string // 录入时间
	checked    bool //是否被选中,下面SetChecked接口调用时设置
}

type StudentModel struct {
	walk.TableModelBase
	walk.SorterBase
	sortColumn int
	sortOrder  walk.SortOrder
	items      []*StudentInfo // 存放数据,后续通过修改该字段内容,实现界面的数据刷新
}

func NewStudentModel() *StudentModel {
	m := new(StudentModel)
	m.ResetRows()
	return m
}

// 用户自己定义的,生成测试数据
func (m *StudentModel) ResetRows() {
	m.items = make([]*StudentInfo, 10, 20)
	// 注意,这里一定不能写成m.items = make([]*StudentInfo, 20),否则会panic,除了当前写法,也可以把for循环长度改为20即可
	for i := 0; i < 10; i++ {
		m.items[i] = &StudentInfo{i, "xiaoming", i + 2, "2020-10-10 10:10:10", false}
	}
	m.PublishRowsReset() //手动触发界面刷新,数据变更时根据需要调用。
}

// 控件刷新时调用
func (m *StudentModel) RowCount() int {
	logger.Println("len:", len(m.items), cap(m.items))
	return len(m.items)
}

//  当TableView需要为给定单元格显示文本时,由TableView调用
func (m *StudentModel) Value(row, col int) interface{} {
	item := m.items[row]

	switch col {
	case 0:
		return item.SeqNo

	case 1:
		return item.Name

	case 2:
		return item.Age

	case 3:
		return item.CreateTime
	}

	panic("unexpected col")
}

// 由TableView调用以检索是否选中了给定行。
func (m *StudentModel) Checked(row int) bool {
	return m.items[row].checked
}

// 当用户切换给定行的复选框时由TableView调用
func (m *StudentModel) SetChecked(row int, checked bool) error {
	m.items[row].checked = checked

	return nil
}

// 由TableView调用以对模型进行排序
func (m *StudentModel) Sort(col int, order walk.SortOrder) error {
	logger.Println("sort..............", m.items)
	return nil
}

3.14 ListBox

listBoxMd := NewEnvModel()
ListBox{
	AssignTo:    &myMain.ListBox,
	ToolTipText: "列表控件",
	Model:       listBoxMd,
	OnItemActivated: func() {
		name := listBoxMd.items[myMain.ListBox.CurrentIndex()].name
		value := listBoxMd.items[myMain.ListBox.CurrentIndex()].value
		walk.MsgBox(nil, name, value, walk.MsgBoxIconInformation)
	},
},
type EnvModel struct {
	walk.ListModelBase
	items []EnvItem
}
type EnvItem struct {
	name  string
	value string
}

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
}

// 获取节点数,即有多少条数据,由ListBox调用
func (m *EnvModel) ItemCount() int {
	return len(m.items)
}

// 显示每一行时由ListBox调用
func (m *EnvModel) Value(index int) interface{} {
	if m.items[index].name == "" {
		return "null"
	}

	return m.items[index].name
}

3.15 Slider

// 当前实现的是,拖动滑动条,在指定NumberEdit控件中显示实时数据
Slider{
	AssignTo:    &myMain.Slider,
	ToolTipText: "滑动条",
	MaxValue:    1000, // 滑动条最大值
	MinValue:    0, // 滑动条最小值
	Orientation: Horizontal, // 滑动条方向,垂直或者水平,当前水平
	// 点击某一个位置时触发
	OnValueChanged: func() {
		v := myMain.Slider.Value()
		myMain.NumberEdit.SetValue(float64(v))
	},
	// 拖动滑动条过程即触发
	OnMouseMove: func(x, y int, button walk.MouseButton) {
		v := myMain.Slider.Value()
		myMain.NumberEdit.SetValue(float64(v))
	},
},

3.16 StatusBarItem

StatusBarItem{
	AssignTo: &myMain.StatusBarItem,
	Icon:     icon1, // 可选 显示图标 
	Text:     "click", // 显示名字
	Width:    80, // 宽度
	//点击该状态栏是,图标来回切换
	OnClicked: func() {
		if myMain.StatusBarItem.Text() == "click" {
			myMain.StatusBarItem.SetText("again")
			myMain.StatusBarItem.SetIcon(icon2)
		} else {
			myMain.StatusBarItem.SetText("click")
			myMain.StatusBarItem.SetIcon(icon1)
		}
	},
},
StatusBarItem{
	Text:        "left",
	ToolTipText: "no tooltip for me",
},
StatusBarItem{
	Text: "\tcenter",
},
StatusBarItem{
	Text: "\t\tright",
},
StatusBarItem{
	Icon:        icon1,
	ToolTipText: "An icon with a tooltip",
},