Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DESAMIS Go Training Season 1 Day 12

DESAMIS Go Training Season 1 Day 12

デザミス社内 Go 研修 (第1期) の12日目の資料です。
今回は Go における GUI アプリケーション開発の現状について軽く触れ、その上で Fyne というツールキットを触ってみる内容となっています。ビルドに GCC が必要なため mingw-w64 のセットアップ手順を作りましたが、ユーザー名フォルダ (C:\Users \XXX) が日本語の場合に導入に失敗することが発覚、GOPATH の移動で対処しました。

Yutaka Kato

August 10, 2021
Tweet

More Decks by Yutaka Kato

Other Decks in Technology

Transcript

  1. ݚमܭը ճ ೔࣍ ༧ఆ λΠτϧ ୈճ  Ր  (Pͷجຊ

    ୈճ  Ր  ؀ڥߏஙͱ(JU (JU)VCͷجຊ ୈճ  Ր  جຊߏจ ୈճ  Ր  ߏ଄ମɺεϥΠεɺϚοϓ ୈճ  Ր  ඪ४ϥΠϒϥϦ͸΍Ί͙Γ ୈճ  Ր  ϞδϡʔϧγεςϜͱ֎෦ϥΠϒϥϦ ୈճ  Ր  )FSPLV(Pೖ໳ ୈճ  Ր  "84-BNCEB(Pೖ໳ ୈճ  Ր  ฒߦॲཧϓϩάϥϛϯά ୈճ  Ր  ୯ମςετٕ๏ ୈճ  Ր  σʔλϕʔεΞΫηε ୈճ  Ր  'ZOFʹΑΔ(6*ΞϓϦέʔγϣϯ։ൃ ୈճ  Ր  ࣾ಺(PϓϩδΣΫτͷίʔυղઆ 
  2. (Pʹ͓͚Δબ୒ࢶ   ϥΠϒϥϦ πʔϧΩοτΤϯδϯ (JU)VC˒ GZOFJPGZOF ಠࣗ L HJUIVCDPNUIFSFDJQFRU

    2U L HJUIVCDPNXFCWJFXXFCWJFX ϒϥ΢βܥ L HJUIVCDPNBOEMBCTVJ MJCVJ L HJUIVCDPNNBYFODFDIBSSJFSFHPBQQ ϒϥ΢βܥ L HJUIVCDPNXBJMTBQQXBJMT ϒϥ΢βܥ L HJUIVCDPNBTUJDPEFHPBTUJMFDUSPO &MFDUSPO L HJUIVCDPNTDJUFSTELHPTDJUFS ϒϥ΢βܥ L HJUIVCDPNNBUUOHPHUL (5, L HJUIVCDPNHPULHPULHUL (5, L HJUIVCDPNEUZMNBOHPXE ϒϥ΢βܥ  4PVSDFIUUQTHJUIVCDPNBWFMJOPBXFTPNFHPHVJ˞ಛఆ04޲͚͸আ֎
  3. ΍ͬͯΈΑ͏    74$PEFΛىಈ͠ݚमϦϙδτϦΛ։͖·͢  Ϣʔβʔ໊ϑΥϧμҎԼʹʮEBZIFMMPʯϑΥϧμΛ࡞੒͠ɺͦͷத ʹҎԼͷ಺༰ͰʮNBJOHPʯΛ࡞੒͠·͢ package mai

    n import ( "fyne.io/fyne/v2/app " "fyne.io/fyne/v2/widget " ) func main() { a := app.New( ) w := a.NewWindow("Hello" ) w.SetContent(widget.NewLabel("Hello, world!") ) w.ShowAndRun( ) } ౷߹λʔϛφϧͰʮgo mod tidyʯͱʮgo run .ʯΛ࣮ߦ͠·͢
  4. ΍ͬͯΈΑ͏    ʮ)FMMP XPSMEʯͷจࣈྻΛʮ)FMMP ੈքʯʹมߋͯ͠࠶࣮ߦ͠·͢  จࣈ͕౾෗ʹͳͬͯ͠·͏ͷͰɺҎԼͷߦΛapp.New()ͷલʹૠೖ͠·͢ 

    ΋͏Ұ౓࣮ߦͯ͠ɺਖ਼͘͠දࣔ͞ΕΔ͜ͱΛ֬ೝ͠·͢ os.Setenv("FYNE_FONT", "C:\\Windows\\Fonts\\YuGothM.ttc") F y n e に 内蔵 さ れ て いる フ ォ ン ト は N o t o S a n s だ が、 日本語 に 対応 し た C J K で は な く 標準 の も の な の で 、 環境変数 F Y N E _ F O N T で 変更 す る
  5. )#PY 7#PY  package mai n import ( "fyne.io/fyne/v2/app "

    "fyne.io/fyne/v2/container " "fyne.io/fyne/v2/widget " ) func main() { a := app.New( ) w := a.NewWindow("Hello" ) w.SetContent(container.NewHBox ( widget.NewLabel("Label 1") , widget.NewLabel("Label 2") , ) ) w.ShowAndRun( ) } package mai n import ( "fyne.io/fyne/v2/app " "fyne.io/fyne/v2/container " "fyne.io/fyne/v2/widget " ) func main() { a := app.New( ) w := a.NewWindow("Hello" ) w.SetContent(container.NewVBox ( widget.NewLabel("Label 1") , widget.NewLabel("Label 2") , ) ) w.ShowAndRun( ) }
  6. )#PY 7#PY  w.SetContent(container.NewHBox ( widget.NewLabel("Label 1") , container.NewVBox(widget.NewLabel("Label 2"),

    widget.NewLabel("Label 3")) , )) )#PY 7#PY HBoxͷ൪໨ͷ߲໨ʹVBoxΛ௥Ճ͍ͯ͠Δ
  7. 5BC  w.SetContent(container.NewAppTabs ( container.NewTabItem("Tab 1", widget.NewLabel("Label 1")) , container.NewTabItem("Tab

    2", widget.NewLabel("Label 2")) , )) Մม௕Ҿ਺ͳͷͰ͍͘ΒͰ΋ λϒΛ௥ՃՄೳ
  8. #PSEFS (SJE  w.SetContent(container.NewBorder ( widget.NewLabel("TOP") , widget.NewLabel("BOTTOM") , widget.NewLabel("LEFT")

    , widget.NewLabel("RIGHT") , widget.NewLabel("Content") , )) w.SetContent(container.NewGridWithRows(3 , container.NewGridWithColumns(3 , widget.NewLabel("Row 1, Column 1") , widget.NewLabel("Row 1, Column 2") , ) , container.NewGridWithColumns(3 , widget.NewLabel("Row 2, Column 1") , widget.NewLabel("Row 2, Column 2") , ) , ))
  9. #VUUPO  message := widget.NewLabel("" ) w.SetContent(container.NewVBox ( widget.NewButton("Click me",

    func() { message.SetText("Clicked!" ) }) , message , )) ԡ͞Εͨͱ͖ʹݺ͹ΕΔؔ਺ ΛҾ਺ͱͯ͠౉͢ ޙͰ஋ʹΞΫηε͢Δ߲໨͸ 
 ม਺ʹͱ͓ͬͯ͘
  10. 'PSN  id := widget.NewEntry( ) password := widget.NewPasswordEntry( )

    message := widget.NewLabel("" ) w.SetContent(container.NewVBox ( widget.NewForm ( widget.NewFormItem("ID", id) , widget.NewFormItem("Password", password) , ) , widget.NewButton("Login", func() { if password.Text != "password" { message.SetText("Not authorized" ) retur n } message.SetText("Welcome, " + id.Text ) }) , message , )) Formͷ࡞੒
  11. "DDPSEJPO  w.SetContent(widget.NewAccordion ( widget.NewAccordionItem("Accordion 1", widget.NewLabel("Label 1")) , widget.NewAccordionItem("Accordion

    2", widget.NewLabel("Label 2")) , widget.NewAccordionItem("Accordion 3", widget.NewLabel("Label 3")) , )) ͲΕ͔ͭΛ։͘ͱ 
 ଞͷ։͍͍ͯΔ߲໨Λด͡Δ
  12. $BSE  w.SetContent(container.NewHBox ( widget.NewCard("Card 1", "Subtitle 1", widget.NewLabel("Label 1"))

    , widget.NewCard("Card 2", "Subtitle 2", widget.NewLabel("Label 2")) , ))
  13. ͦͷଞॾʑ  w.SetContent(container.NewHBox ( widget.NewForm ( widget.NewFormItem("Check", widget.NewCheck("Check", nil)) ,

    widget.NewFormItem("Radio", widget.NewRadioGroup(radioOptions, nil)) , widget.NewFormItem("Select", widget.NewSelect(selectOptions, nil)) , widget.NewFormItem("Hyperlink", widget.NewHyperlink("Hyperlink", nil)) , ) , widget.NewForm ( widget.NewFormItem("ProgressBar", widget.NewProgressBar()) , widget.NewFormItem("Slider", widget.NewSlider(0, 100)) , widget.NewFormItem("Toolbar", widget.NewToolbar ( widget.NewToolbarAction(theme.ContentAddIcon(), nil) , widget.NewToolbarAction(theme.ContentCopyIcon(), nil) , widget.NewToolbarAction(theme.ContentClearIcon(), nil) , widget.NewToolbarAction(theme.ContentCutIcon(), nil) , )) , ) , )) ˞͜ΕͰશ෦Ͱ͸ͳ͍
  14. μΠΞϩάͷجຊ  w.SetContent(container.NewVBox ( widget.NewButton("Info dialog", func() { dialog.NewInformation("Info", "Message",

    w).Show( ) }) , widget.NewButton("Confirm dialog", func() { dialog.NewConfirm("Confirm", "Message", func(b bool) { fmt.Println(b) }, w).Show( ) }) , widget.NewButton("Error dialog", func() { dialog.NewError(errors.New("Message"), w).Show( ) }) , widget.NewButton("Custom dialog", func() { dialog.NewCustom("Custom", "OK", widget.NewIcon(theme.FyneLogo()), w).Show( ) }) , )) :FT/Pͷ݁Ռ͕CPPMͰฦΔ
  15. ϑΝΠϧૢ࡞μΠΞϩά  w.SetContent(widget.NewButton("File open dialog", func() { dw := a.NewWindow("Dialog

    window" ) dw.Resize(fyne.NewSize(500, 350) ) dialog.NewFileOpen(func(f fyne.URIReadCloser, err error) { defer dw.Close( ) if err != nil || f == nil { retur n } defer f.Close( ) fmt.Println("file:", f.URI() ) }, dw).Show( ) dw.Show( ) })) ϑΝΠϧૢ࡞ܥμΠΞϩά͸ 
 େ͖ͳදࣔྖҬ͕ඞཁ 
 ผ΢Οϯυ΢Ͱ։͘ͷ͕ 
 ͓͢͢Ί NewFileOpen()
 NewFileSave()
 NewFolerOpen() 
 ͷछྨ͕͋Δ
  16. $BOWBT  raster := canvas.NewRasterWithPixels ( func(_, _, w, h

    int) color.Color { return color.RGBA { R: uint8(rand.Intn(255)) , G: uint8(rand.Intn(255)) , B: uint8(rand.Intn(255)) , A: 0xff , } } ) w.SetContent(raster ) w.Resize(fyne.NewSize(150, 100)) circle := canvas.NewCircle(color.RGBA{G: 128} ) circle.StrokeColor = color.Gray{Y: 0x99 } circle.StrokeWidth = 5 w.SetContent(circle ) w.Resize(fyne.NewSize(150, 100)) w ͘͝؆୯ͳਤܗ΍ը૾ͷඳը͕Ͱ͖Δ
  17. ύοέʔδϯά  w ΞΠίϯΛઃఆ࣮ͨ͠ߦϑΝΠϧΛ࡞੒͢Δ͜ͱ͕Ͱ͖Δ w Πϯετʔϧํ๏ 
 go install fyne.io/fyne/v2/cmd/fyne@latest


    
 (࣮ߦόΠφϦ͕ <ϗʔϜσΟϨΫτϦ>/go/bin/ ҎԼʹ֨ೲ͞Ε·͢)  w ࣮ߦํ๏  ద౰ͳΞΠίϯΛ༻ҙͯ͠ʮ*DPOQOHʯͱ͍͏໊લͰอଘ͠·͢  ౷߹λʔϛφϧͰʮ~\go\bin\fyne packageʯʻ5BCʼʻ&OUFSʼ 
 Λ࣮ߦ͠·͢˞ ˞$PNNBOE1SPNQUͷ৔߹ 
 ɹ%USERPROFILE%\go\bin\fyne package
  18. ࿅श໰୊ w ࿅श՝୊<ϑΥϧμ໊EBZDMPDL> w ݱࡏ࣌ࠁΛʮʯͷΑ͏ʹදࣔ͢Δ࣌ܭΞϓϦΛ࡞͍ͬͯͩ͘͞ w ώϯτ w.ShowAndRun()ΑΓ΋લͷஈ֊Ͱ࣌ܭͷදࣔΛߋ৽͢Δ ΰϧʔνϯΛ্ཱͪ͛Δඞཁ͕͋Γ·͢ w

    ࿅श՝୊<ϑΥϧμ໊EBZHPPHMF> w ΩʔϫʔυΛೖྗ͢ΔͱɺͦͷΩʔϫʔυͷ(PPHMFݕࡧ݁ՌΛϒϥ΢ βͰ։͘πʔϧΛ࡞͍ͬͯͩ͘͞ w ώϯτ ϓϩάϥϜ͔Βϒϥ΢βΛ։͘ํ๏ 
 exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() 
  19. ίʔυΛॻ͖ऴ͑ͨΒ w ʮϢʔβʔ໊QSBDUJDFʯϒϥϯνͰ࡞ۀ͍ͯ͠Δ͜ͱΛ֬ೝ͍ͯͩ͘͠͞ w 74$PEFͷҰ൪ࠨԼʹදࣔ͞Ε͍ͯ·͢ w มߋΛεςʔδ͠ɺίϛοτ͍ͯͩ͘͠͞ w 74$PEFͷࠨϝχϡʔͷʮιʔε؅ཧʯ͔Βૢ࡞ w

    ίʔυΛ(JU)VCʹϓογϡ͍ͯͩ͘͠͞ w 74$PEFͷҰ൪ࠨԼͷϒϥϯν໊ͷ͙͢ӈʹ͋ΔΞΠίϯ͔Βૢ࡞ ্ਤ  w ϓϧϦΫΤετΛ࡞੒͍ͯͩ͘͠͞ w ʮιʔε؅ཧʯͷ্෦ʹΞΠίϯ͕͋Γ·͢