刚开始研究 Go 和 Fyne。使用从示例中获得的信息编写测试 CRUD 程序后,我需要解决以下问题:
我需要一个初始对话框或类似的,以便允许选择现有记录或“新”来指示新记录。我现有的对话框不能充分处理这个问题。
如果数据没有更改,我需要能够启用/禁用提交按钮以允许或禁止更新。
该程序编译没有错误,但是“go vet”和 VsCode 指示(例如 for line):
{"Given Names:", arwWidgets[I_NDX_GIVEN]},
go vet shows:
ERROR: "unknown field 'Key' in struct literal of type widget.FormItem",
however, if I include a key, compiler fails.
- 作为 Go 和 Fyne 的新手,可能存在根本性错误。
测试程序如下:
package main
// Dependency: local directory "data".
import (
"errors"
"io/ioutil"
"log"
"os"
"strings"
"fyne.io/fyne"
"fyne.io/fyne/app"
"fyne.io/fyne/dialog"
"fyne.io/fyne/layout"
"fyne.io/fyne/widget"
)
const BY_SEP byte = byte('|')
const I_ARRAY_LEN int = 10
const I_NDX_GIVEN int = 0
const I_NDX_FAMILY int = 1
const I_NDX_TITLE int = 2
const I_NDX_ADDR1 int = 3
const I_NDX_ADDR2 int = 4
const I_NDX_ADDR3 int = 5
const I_NDX_STATE int = 6
const I_NDX_ZIP int = 7
const I_NDX_TELE1 int = 8
const I_NDX_TELE2 int = 9
var _arsOldData [I_ARRAY_LEN]string
var _arsNewData [I_ARRAY_LEN]string
var _tfDataHasChanged bool
var _sKey string
var _arwEntryWidgets [I_ARRAY_LEN]*widget.Entry
var _wApp fyne.App
var _wWindow fyne.Window
var _wModal widget.PopUp
var _wFormKeyEntry widget.Form
//-------------------------------------------------------------------------------
func main() {
log.Println("In fytest01")
_, err := os.Stat("./data/")
if err != nil {
log.Println("You need to create directory: 'data'")
os.Exit(1)
}
//fnReadData()
_wApp := app.New()
_wWindow := _wApp.NewWindow("Customer Details")
//_wFormKeyEntry := fnCreateKeyForm()
wFormMain := fnCreateMainForm()
//_wModal := widget.NewModalPopUp(_wFormKeyEntry, _wWindow.Canvas())
_wWindow.Resize(fyne.NewSize(500, 400))
_wWindow.CenterOnScreen()
_wWindow.SetContent(widget.NewVBox(
wFormMain,
widget.NewGroup("",
fyne.NewContainerWithLayout(layout.NewGridLayout(2),
widget.NewButton("Exit", func() {
_wApp.Quit()
}),
widget.NewButton("Submit", func() {
log.Println("Submit button pressed")
err := fnUpdateData()
if err == nil {
dialog.ShowInformation("Information", "Data was updated", _wWindow)
wEntryForKey := widget.NewEntry()
wEntryForKey.SetPlaceHolder("Enter Key (4) : ")
wEntryForKey.OnChanged = func(sKey string) {
log.Println("Entered", sKey)
if len(sKey) == 4 {
_sKey = sKey
}
if len(_sKey) == 4 {
dialog.ShowInformation("Information", "Key "+_sKey+" has been entered - press OK", _wWindow)
fnReadData()
fnRefreshWidgetData()
}
}
dialog.ShowCustom("Enter Customer Key", "OK", wEntryForKey, _wWindow)
} else {
dialog.ShowError(err, _wWindow)
}
}),
))),
)
//fnShowKeyEntryDialog()
wEntryForKey := widget.NewEntry()
wEntryForKey.SetPlaceHolder("Enter Key (4) : ")
wEntryForKey.OnChanged = func(sKey string) {
log.Println("Entered", sKey)
if len(sKey) == 4 {
_sKey = sKey
}
if len(_sKey) == 4 {
dialog.ShowInformation("Information", "Key "+_sKey+" has been entered - press OK", _wWindow)
fnReadData()
fnRefreshWidgetData()
}
}
dialog.ShowCustom("Enter Customer Key", "OK", wEntryForKey, _wWindow)
_wWindow.ShowAndRun()
//_wModal.Show()
}
//-------------------------------------------------------------------------------
func fnCreateAllEntryWidgets() {
_arwEntryWidgets[I_NDX_GIVEN] = fnCreateSingleEntryWidget(I_NDX_GIVEN)
_arwEntryWidgets[I_NDX_FAMILY] = fnCreateSingleEntryWidget(I_NDX_FAMILY)
_arwEntryWidgets[I_NDX_TITLE] = fnCreateSingleEntryWidget(I_NDX_TITLE)
_arwEntryWidgets[I_NDX_ADDR1] = fnCreateSingleEntryWidget(I_NDX_ADDR1)
_arwEntryWidgets[I_NDX_ADDR2] = fnCreateSingleEntryWidget(I_NDX_ADDR2)
_arwEntryWidgets[I_NDX_ADDR3] = fnCreateSingleEntryWidget(I_NDX_ADDR3)
_arwEntryWidgets[I_NDX_STATE] = fnCreateSingleEntryWidget(I_NDX_STATE)
_arwEntryWidgets[I_NDX_ZIP] = fnCreateSingleEntryWidget(I_NDX_ZIP)
_arwEntryWidgets[I_NDX_TELE1] = fnCreateSingleEntryWidget(I_NDX_TELE1)
_arwEntryWidgets[I_NDX_TELE2] = fnCreateSingleEntryWidget(I_NDX_TELE2)
}
//-------------------------------------------------------------------------------
func fnCreateSingleEntryWidget(iNdxData int) *widget.Entry {
wEntry := widget.NewEntry()
wEntry.SetText(_arsOldData[iNdxData])
wEntry.OnChanged = func(sText string) {
_arsNewData[iNdxData] = sText
fnCheckIfDataHasChanged()
}
return wEntry
}
//-------------------------------------------------------------------------------
func fnCreateFormFields(arwWidgets [I_ARRAY_LEN]*widget.Entry) []*widget.FormItem {
return []*widget.FormItem{
{"Given Names:", arwWidgets[I_NDX_GIVEN]},
{"Family Name: ", arwWidgets[I_NDX_FAMILY]},
{"Title: ", arwWidgets[I_NDX_TITLE]},
{"Address Ln 1: ", arwWidgets[I_NDX_ADDR1]},
{" '' Ln 2: ", arwWidgets[I_NDX_ADDR2]},
{" '' Ln 3: ", arwWidgets[I_NDX_ADDR3]},
{" '' State ", arwWidgets[I_NDX_STATE]},
{" '' Zip: ", arwWidgets[I_NDX_ZIP]},
{"Telephone 1: ", arwWidgets[I_NDX_TELE1]},
{"Telephone 2: ", arwWidgets[I_NDX_TELE2]},
}
}
//-------------------------------------------------------------------------------
func fnCheckIfDataHasChanged() {
var tfChanged bool = false
for iNdxData := 0; !tfChanged && iNdxData < len(_arsOldData); iNdxData++ {
tfChanged = (_arsNewData[iNdxData] != _arsOldData[iNdxData])
}
if tfChanged != _tfDataHasChanged {
_tfDataHasChanged = tfChanged
if tfChanged {
// COULD NOT CREATE _wBtnSubmitMain AS A GLOBAL VARIABLE.
//_wBtnSubmitMain.Show()
//_wBtnSubmitMain.Enable()
} else {
//_wBtnSubmitMain.Disable()
//_wBtnSubmitMain.Hide()
}
}
}
//-------------------------------------------------------------------------------
func fnReadData() {
_tfDataHasChanged = false
log.Println("fnReadData: Key = " + _sKey)
var sData string
if len(_sKey) > 0 {
arbData, _ := ioutil.ReadFile("./data/" + _sKey)
if arbData != nil {
sData = string(arbData)
}
}
log.Println("fnReadData: sData = " + sData)
/* CLEAR OLD DATA */
for iNdxData := 0; iNdxData < I_ARRAY_LEN; iNdxData++ {
_arsOldData[iNdxData] = ""
}
/* POPULATE DATA IF ANY */
var iNdx1 int = 0
var iNdxData int = 0
var iLen int = len(sData)
for iNdx2 := 0; iNdx2 < len(sData); iNdx2++ {
if sData[iNdx2] == BY_SEP {
_arsOldData[iNdxData] = sData[iNdx1:iNdx2]
iNdx1 = iNdx2 + 1
iNdxData++
} else if iNdx2 == (iLen - 1) {
_arsOldData[iNdxData] = sData[iNdx1 : iNdx2+1]
}
}
for iNdx := 0; iNdx < I_ARRAY_LEN; iNdx++ {
_arsNewData[iNdx] = _arsOldData[iNdx]
}
}
//-------------------------------------------------------------------------------
func fnUpdateData() error {
if !_tfDataHasChanged {
return errors.New("Data has not changed")
}
if len(_sKey) < 1 {
_sKey = "9999"
//dialog.ShowInformation("Information", "Default key of 9999 was used", _wWindow) // CAUSES ERROR
}
var sNewData string = ""
for iNdxData, sVal := range _arsNewData {
if strings.Index(sVal, "|") >= 0 {
sVal = strings.ReplaceAll(sVal, "|", ":")
}
if iNdxData != I_ARRAY_LEN-1 {
sNewData += sVal + string(BY_SEP)
} else {
sNewData += sVal
}
}
log.Println("New Data = " + sNewData)
var err error = ioutil.WriteFile("./data/"+_sKey, []byte(sNewData), 0644)
if err == nil {
for iNdxData := 0; iNdxData < len(_arsNewData); iNdxData++ {
_arsOldData[iNdxData] = _arsNewData[iNdxData]
}
fnCheckIfDataHasChanged()
}
return err
}
//-------------------------------------------------------------------------------
func fnCreateKeyForm() *widget.Form {
wEntryKey := widget.NewEntry()
return &widget.Form{
Items: []*widget.FormItem{
{"Key:", wEntryKey}},
OnSubmit: func() {
_sKey = wEntryKey.Text
log.Println("Key = " + _sKey)
fnReadData()
log.Println("Data has been read")
fnRefreshWidgetData()
_wFormKeyEntry.Hide()
//_wModal.Hide()
},
}
}
//-------------------------------------------------------------------------------
//func fnCreateMainWindow() {
// log.Println("Creating Main Window Form")
// wFormMain := fnCreateMainForm()
// log.Println("Creating Main Window Window")
// _wWindow.SetContent( //widget.NewVBox(
// wFormMain,
// )
//}
//-------------------------------------------------------------------------------
func fnCreateMainForm() *widget.Form {
log.Println("Create form1 widgets")
fnCreateAllEntryWidgets()
log.Println("Create form1 FormFields")
arwFormFields := fnCreateFormFields(_arwEntryWidgets)
log.Println("Creating Form1")
return &widget.Form{
Items: arwFormFields,
}
}
//-------------------------------------------------------------------------------
func fnRefreshWidgetData() {
for iNdx := 0; iNdx < I_ARRAY_LEN; iNdx++ {
_arwEntryWidgets[iNdx].SetText(_arsNewData[iNdx])
}
}