0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Golang WalkでRadioButtonの選択をコードから変更する

Last updated at Posted at 2018-04-29

Golang Walkでラジオボタンの選択をコードから変更する方法を試しました。

package main

import (
	"fmt"
)

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

type Foo struct {
	Bar string
	Baz int
}

func main() {
	foo := &Foo{"b", 0}
	var db *walk.DataBinder
	var rbBar [3]*walk.RadioButton
	var rbBaz [3]*walk.RadioButton

	MainWindow{
		Title:   "Walk RadioButton Example",
		MinSize: Size{320, 240},
		Layout:  VBox{},
		DataBinder: DataBinder{
			AssignTo: &db,
			DataSource: foo,
			AutoSubmit: true,
			OnSubmitted: func() {
				fmt.Println(foo)
			},
		},
		Children: []Widget{
			// RadioButtonGroup is needed for data binding only.
			RadioButtonGroup{
				DataMember: "Bar",
				Buttons: []RadioButton{
					RadioButton{
						AssignTo: &rbBar[0],
						Name:  "aRB",
						Text:  "A",
						Value: "a",
					},
					RadioButton{
						AssignTo: &rbBar[1],
						Name:  "bRB",
						Text:  "B",
						Value: "b",
					},
					RadioButton{
						AssignTo: &rbBar[2],
						Name:  "cRB",
						Text:  "C",
						Value: "c",
					},
				},
			},
			Label{
				Text:    "A",
				Enabled: Bind("aRB.Checked"),
			},
			Label{
				Text:    "B",
				Enabled: Bind("bRB.Checked"),
			},
			Label{
				Text:    "C",
				Enabled: Bind("cRB.Checked"),
			},
			RadioButtonGroup{
				DataMember: "Baz",
				Buttons: []RadioButton{
					RadioButton{
						AssignTo: &rbBaz[0],
						Name:  "oneRB",
						Text:  "1",
						Value: 1,
					},
					RadioButton{
						AssignTo: &rbBaz[1],
						Name:  "twoRB",
						Text:  "2",
						Value: 2,
					},
					RadioButton{
						AssignTo: &rbBaz[2],
						Name:  "threeRB",
						Text:  "3",
						Value: 3,
					},
				},
			},
			Label{
				Text:    "1",
				Enabled: Bind("oneRB.Checked"),
			},
			Label{
				Text:    "2",
				Enabled: Bind("twoRB.Checked"),
			},
			Label{
				Text:    "3",
				Enabled: Bind("threeRB.Checked"),
			},
			PushButton{
				Text: "Apply from Code",
				OnClicked: func() {
					// ここに実装する
				},
			},
		},
	}.Run()
}

初期画面はこちら。
20180429_walk radiobutton 1.jpg

「Apply from Code」ボタンがクリックされたらfoo.Barを"c"、foo.Bazを3にセットし、ラジオボタンの選択を変更したいとします。
20180429_walk radiobutton 2.jpg

まず、fooに値をセットします。

		PushButton{
			Text: "Apply from Code",
			OnClicked: func() {
				foo.Bar = "c"
				foo.Baz = 3
			},
		},

これでラジオボタンにも反映されれば言うことなしですが、反映してくれません。
自力でラジオボタンの選択状態を更新してみます。

1. RadioButton.SetChecked(true)する方法

		PushButton{
			Text: "Apply from Code",
			OnClicked: func() {
				foo.Bar = "c"
				foo.Baz = 3

				cbBar := rbBar[0].Group().CheckedButton()
				if cbBar != nil {
					cbBar.SetChecked(false)
				}
				for _, rb := range rbBar {
					if rb.Value() == foo.Bar {
						rb.SetChecked(true)
						break
					}
				}

				cbBaz := rbBaz[0].Group().CheckedButton()
				if cbBaz != nil {
					cbBaz.SetChecked(false)
				}
				for _, rb := range rbBaz {
					if rb.Value() == foo.Baz {
						rb.SetChecked(true)
						break
					}
				}
			},
		},

RadioButtonのSetCheckedを使いました。これ一見うまくいきそうですが、rb.Group().CheckButton()がSetCheckedしたrbに書き変わらないため、実行すると奇妙な現象が起きます(チェックをオフにしたはずのラジオボタンが再び選択状態になる)

2. RadioButtonのCheckedValueプロパティを使用する方法
ソースコードを眺めていたら、きちんとrb.Group().CheckButton()を書き換えてくれるプロパティがRadioButtonにありました。
CheckedValueというプロパティです。

   rb.MustRegisterProperty("CheckedValue", NewProperty(
        func() interface{} {
            if rb.Checked() {
                return rb.value
            }

            return nil
        },
        func(v interface{}) error {
            checked := v == rb.value
            if checked {
                rb.group.checkedButton = rb
            }
            rb.SetChecked(checked)

            return nil
        },
        rb.CheckedChanged()))

これを使うと期待通りの動作をします。

		PushButton{
			Text: "Apply from Code",
			OnClicked: func() {
				foo.Bar = "c"
				foo.Baz = 3
				cbBar := rbBar[0].Group().CheckedButton()
				if cbBar != nil {
					prop := cbBar.AsWindowBase().Property("CheckedValue")
					prop.Set(foo.Bar)
				}
				for _, rb := range rbBar {
					if rb.Value() == foo.Bar {
						prop := rb.AsWindowBase().Property("CheckedValue")
						prop.Set(foo.Bar)
						break
					}
				}

				cbBaz := rbBaz[0].Group().CheckedButton()
				if cbBaz != nil {
					prop := cbBaz.AsWindowBase().Property("CheckedValue")
					prop.Set(foo.Baz)
				}
				for _, rb := range rbBaz {
					if rb.Value() == foo.Baz {
						prop := rb.AsWindowBase().Property("CheckedValue")
						prop.Set(foo.Baz)
						break
					}
				}

3. DataBinder.Reset()を使う方法
DataBinderを使っているのだから、DataSourceをUIに反映する方法があるはずだと思ってソースコードを眺めていたら、DataBinderにReset()というメソッドがありました。
次のように実装します。

		PushButton{
			Text: "Apply from Code",
			OnClicked: func() {
				foo.Bar = "c"
				foo.Baz = 3
				
				db.Reset()
			},
		},

これも期待通りの動作をします。これが正解ですね多分。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?