0


Go 图形库 fyne

文章目录

跨平台的图形化界面库,底层也是C写的东西

安装环境

  1. Install Go
  2. Install Gcc
  3. go get fyne.io/fyne/v2 or go get -u fyne.io/fyne 这两个版本是不一样的建议只装第一个

Hello World

package main  
  
import("fyne.io/fyne""fyne.io/fyne/app""fyne.io/fyne/widget")funcmain(){//创建一个窗口  
   a := app.New()//窗口标题  
   w := a.NewWindow("hello world!")//写入文本  
   w.SetContent(widget.NewLabel("Hello world"))//设置窗口大小  
   w.Resize(fyne.NewSize(200,200))//展示窗口  
   w.ShowAndRun()}

实际上

myWin.ShowAndRun()

等价于

myWin.Show()
myApp.Run()
myWin.Show()

显示窗口,

myApp.Run()

开启事件循环。

注意一点,

fyne

默认窗口大小是根据内容的宽高来设置的。上面我们调用

myWin.Resize()

手动设置了大小。否则窗口只能放下字符串

Hello World!

fyne的包结构

fyne

将功能划分到多个子包中:

  • fyne.io/fyne:提供所有fyne应用程序代码共用的基础定义,包括数据类型和接口;
  • fyne.io/fyne/app:提供创建应用程序的 API;
  • fyne.io/fyne/canvas:提供Fyne使用的绘制 API;
  • fyne.io/fyne/dialog:提供对话框组件;
  • fyne.io/fyne/layout:提供多种界面布局;
  • fyne.io/fyne/widget:提供多种组件,fyne所有的窗体控件和交互元素都在这个子包中。

常用函数介绍

Title

w := a.NewWindow(“hello world!”)
就从上面hello world中看

//窗口标题  
w := a.NewWindow("hello world!")

窗口的默认大小

//设置窗口大小  
w.Resize(fyne.NewSize(200,200))

widget 组件

Label

一个简单的控件,可以用来显示字符串. 类似canvas.Text ,不同之处在于Label可以用来处理简单的格式化问题

package main  
  
import("fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/widget")funcmain(){  
   a := app.New()  
   Mywin := a.NewWindow("Label")  
  
   Mywin.SetContent(widget.NewLabel("name"))  
   Mywin.Resize(fyne.Size{800,500})//设置窗口居中  
   Mywin.CenterOnScreen()  
   Mywin.ShowAndRun()}

Button

按钮 ,可以让用户点击的. Button可以包含文本,图标.

widget.NewButton()

创建一个默认的文本按钮,传入文本和一个无参的回调函数。
带图标的按钮需要调用

widget.NewButtonWithIcon()

,传入文本和回调参数,还需要一个

fyne.Resource

类型的图标资源.

package main  
  
import("fmt""fyne.io/fyne/theme""fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/layout""fyne.io/fyne/v2/widget")funcmain(){  
   a := app.New()  
  
   Mywin := a.NewWindow("test Button")  
  
   Label := widget.NewLabel("输出:")  
   button1 := widget.NewButton("Button1",func(){  
      fmt.Println("test button ")  
      Label.SetText("button")})  
  
   button2 := widget.NewButtonWithIcon("Button2", theme.HomeIcon(),func(){  
      fmt.Println("icon button")  
      Label.SetText("icon Button")})  
  
   container := fyne.NewContainerWithLayout(layout.NewVBoxLayout(), button1, button2, Label)  
   Mywin.SetContent(container)  
   Mywin.Resize(fyne.Size{800,500})  
   Mywin.CenterOnScreen()  
   Mywin.ShowAndRun()}

Box

一个盒子
其实就是一个简单的水平或垂直的容器.在内部,Box对子控件采用盒状布局
(Box Layout).我们可以通过传入控件对象给

widget.NewHBox()

widget.NewVBox()

创建盒子。或者调用已经创建好的

widget.Box

对象的

Append()

Prepend()

向盒子中添加控件。前者在尾部追加,后者在头部添加。

package main  
  
import(  
   fyne1 "fyne.io/fyne""fyne.io/fyne/app"   widget1 "fyne.io/fyne/widget")funcmain(){  
   a := app.New()  
  
   Mywin := a.NewWindow("Box test")//在v2版本是没有的  
   content := widget1.NewVBox(  
      widget1.NewLabel("The top of Vbox"),  
      widget1.NewHBox(  
         widget1.NewLabel("Label 1"),  
         widget1.NewLabel("Lable 2"),),)  
   content.Append(widget1.NewButton("Append",func(){  
      content.Append(widget1.NewLabel("Append"))}))  
   content.Append(widget1.NewButton("Prepend",func(){  
      content.Prepend(widget1.NewLabel("Prepended"))}))  
  
   Mywin.SetContent(content)  
   Mywin.Resize(fyne1.Size{800,500})  
   Mywin.CenterOnScreen()  
   Mywin.ShowAndRun()}

注意这其中的版本问题

Entry 输入框

输入框是用于用户输入简单的文本内容的.调用widget.NewEntry()即可创建一个输入框组件.我们一般保存输入框控件的引用,以便访问其Text字段来获取内容. 注册OnChanged 回调函数. 每当内容有修改的时候, Onchanged就会被调用.我们可以调用SetReadOnly(true)来设置输入框的只读属性 . 方法SetPlaceHolder()用来设置占位字符串,设置字段Multiline让输入框接收多行文本.另外,我们可以使用NewPasswordEntry()创建一个密码输入框,输入的文本是不会以明文显示的.

package main  
  
import("fmt""fyne.io/fyne""fyne.io/fyne/app""fyne.io/fyne/layout""fyne.io/fyne/widget")funcmain(){  
   a := app.New()  
   mywin := a.NewWindow("test Entry")  
  
   nameentry := widget.NewEntry()  
  
   nameentry.SetPlaceHolder("input name")  
   nameentry.OnChanged =func(content string){  
      fmt.Println("name", nameentry.Text,"entry")}  
  
   passentry := widget.NewPasswordEntry()  
   passentry.SetPlaceHolder("input passwd")  
  
   nameBox := widget.NewHBox(widget.NewLabel("name"), layout.NewSpacer(), nameentry)  
   passwdBox := widget.NewHBox(widget.NewLabel("password"), layout.NewSpacer(), passentry)  
  
   loginBtn := widget.NewButton("Login",func(){  
      fmt.Println("name", nameentry.Text,"password", passentry,"login in")})  
  
   multiEntry := widget.NewEntry()  
   multiEntry.SetPlaceHolder("please entry\n your description")  
  
   multiEntry.MultiLine =true  
  
   content := widget.NewVBox(nameBox, passwdBox, loginBtn, multiEntry)  
   mywin.SetContent(content)  
   mywin.Resize(fyne.Size{800,500})  
   mywin.CenterOnScreen()  
   mywin.ShowAndRun()}

添加一个容器、条目、按钮

package main  
  
import("fyne.io/fyne""fyne.io/fyne/app""fyne.io/fyne/container""fyne.io/fyne/widget")type App struct{  
   output *widget.Label  
}var Myapp App  
  
funcmain(){  
   a := app.New()  
   Mywindow := a.NewWindow("Hello world!")//三个组件:输出点,输入点,按钮  
   output, entry, btn := Myapp.makeUI()//创建一个容器,容器中的VBox填入三个组件  
   Mywindow.SetContent(container.NewVBox(output, entry, btn))  
   Mywindow.Resize(fyne.Size{Width:500, Height:500})  
   Mywindow.ShowAndRun()}func(app *App)makeUI()(*widget.Label,*widget.Entry,*widget.Button){  
   output := widget.NewLabel("Hello world!")  
   entry := widget.NewEntry()  
   btn := widget.NewButton("Enter",func(){  
      app.output.SetText(entry.Text)})  
   app.output = output  
   //高亮按钮(让按钮变得重要,按钮会变成蓝色)  
   btn.Importance = widget.HighImportance  
  
   return output, entry, btn  
}

一个简单的markdown编辑器

从中学到:

  • 比较少的代码
  • 创建一个菜单栏
  • 打开,保存文件操作
  • 关于主题的东西。

Step1

窗口雏形

package main  
  
import("fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/container""fyne.io/fyne/v2/widget")type config struct{  
   EditWidget    *widget.Entry    //编辑窗口  
   PreviewWidget *widget.RichText //预览窗口,RichText是一个富文本编辑器  
   CurrentFile   fyne.URI         //当前的文件  
   SaveMenuItem  *fyne.MenuItem   //文件保存的菜单  }var cfg config  
  
funcmain(){//创建一个fyneAPP  
   a := app.New()// 给这个APP创建一个窗口  
   win := a.NewWindow("Markdown")//拿到用户的接口  
   edit, preview := cfg.MakeUI()// 设置窗口的内容  
   win.SetContent(container.NewHSplit(edit, preview))//展示窗口并启动应用  
   win.Resize(fyne.Size{Width:800, Height:500})//窗口居中  
   win.CenterOnScreen()  
   win.ShowAndRun()}func(app config)MakeUI()(*widget.Entry,*widget.RichText){// 这个函数会返回Markdown的编辑页面和预览页面  // 创建一个多行的编辑组件  
   edit := widget.NewMultiLineEntry()//创建预览窗口组件  
   preview := widget.NewRichTextFromMarkdown("")  
   app.EditWidget = edit  
   app.PreviewWidget = preview  
  
   edit.OnChanged = preview.ParseMarkdown  
  
   return edit, preview  
  
}

在这里插入图片描述

Step2

添加菜单
在这里插入图片描述

这是成品
看看代码:

cfg.CreateMenuItem(win)

调用创建菜单函数

// 创建菜单项  func(app config)CreateMenuItem(win fyne.Window){//打开菜单项  
   openMenuItem := fyne.NewMenuItem("Open..",func(){})//保存菜单项  
   saveMenuItem := fyne.NewMenuItem("save",func(){})//保存为菜单项,也就是另存为.  
   saveAsMenuItem := fyne.NewMenuItem("save as .....",func(){})// 创建一个菜单:  
   fileMenu := fyne.NewMenu("File", openMenuItem, saveMenuItem, saveAsMenuItem)// 表示文件菜单有三个选项  
   menu := fyne.NewMainMenu(fileMenu)// 设置主菜单  
   win.SetMainMenu(menu)}

可以看见NewMenuItem是创建展开后的小项,NewMenu是创建一个在菜单栏中可以看见点击的菜单.

可以看到在菜单项中的函数没有内容,想想就知道,这里写的内容就是点击了之后产生的操作.

//打开菜单  
   openMenuItem := fyne.NewMenuItem("Open..",func(){})//保存菜单  
   saveMenuItem := fyne.NewMenuItem("save",func(){})//保存为菜单  
   saveAsMenuItem := fyne.NewMenuItem("save as .....",func(){})

接着就是写这里的内容了
不过为了保持代码整洁,我可以把这三个函数写在外面.用的时候调用就行.

//过滤只能打开md文件  var filter = storage.NewExtensionFileFilter([]string{".md",".MD"})func(app *config)saveFunc(win fyne.Window)func(){returnfunc(){//当前文件不是空的时候才可以保存  if app.CurrentFile !=nil{  
         writer, err := storage.Writer(app.CurrentFile)if err !=nil{  
            dialog.ShowError(err, win)return}  
         writer.Write([]byte(app.EditWidget.Text))defer writer.Close()}}}// 创建一个返回值是函数的方法.  func(app *config)saveAsFunc(win fyne.Window)func(){// fyne是跨平台的,在保存文件的时候,不需要考虑操作系统的区别.  returnfunc(){  
      saveDialog := dialog.NewFileSave(func(write fyne.URIWriteCloser, err error){//出现错误就直接返回,错误处理模块  if err !=nil{  
            dialog.ShowError(err, win)return}if write ==nil{// 用户点击了取消保存  return}if!strings.HasSuffix(strings.ToLower(write.URI().String()),".md"){  
            dialog.ShowInformation("error","please name your file with a .md extension", win)return}//保存文件  _, err = write.Write([]byte(app.EditWidget.Text))if err !=nil{return}  
         app.CurrentFile = write.URI()deferfunc(write fyne.URIWriteCloser){  
            err := write.Close()if err !=nil{}}(write)//保存文件后就来改变下窗口的Title  
         win.SetTitle(win.Title()+"-"+ write.URI().Name())  
         app.SaveMenuItem.Disabled =false}, win)//设置默认文件名  
      saveDialog.SetFileName("untitled.md")//设置文件后缀过滤  
      saveDialog.SetFilter(filter)//展示出来  
      saveDialog.Show()}}//打开文件的函数编写.  func(app *config)openFunc(win fyne.Window)func(){returnfunc(){  
      openDialog := dialog.NewFileOpen(func(read fyne.URIReadCloser, err error){if err !=nil{  
            dialog.ShowError(err, win)return}if read ==nil{return}defer read.Close()  
         data, err := ioutil.ReadAll(read)if err !=nil{  
            dialog.ShowError(err, win)return}  
         app.EditWidget.SetText(string(data))  
  
         app.CurrentFile = read.URI()  
  
         win.SetTitle(win.Title()+"-"+ read.URI().Name())  
         app.SaveMenuItem.Disabled =false}, win)//设置过滤  
      openDialog.SetFilter(filter)  
      openDialog.Show()}}
标签: golang ui

本文转载自: https://blog.csdn.net/qq_42702981/article/details/129129914
版权归原作者 ~羽~. 所有, 如有侵权,请联系我们删除。

“Go 图形库 fyne”的评论:

还没有评论