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()
}
「Apply from Code」ボタンがクリックされたらfoo.Barを"c"、foo.Bazを3にセットし、ラジオボタンの選択を変更したいとします。
まず、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()
},
},
これも期待通りの動作をします。これが正解ですね多分。