ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

fyne编写简单桌面应用

2022-07-20 14:04:23  阅读:205  来源: 互联网

标签:widget 桌面 New fyne NewSpacer 编写 container layout


应用的效果图

fyne项目解决问题

1. 中文字体

// 设置系统环境的字体常量
os.Setenv("FYNE_FONT", path)

2. 动态绑定

//先用string切片, string中##连接属性,再分割成struct
var vmStrList binding.ExternalStringList
vmStrList = binding.BindStringList(&[]string{})

项目主要代码

main.go

package main

import (
	"image/color"
	"log"
	"os"
	"runtime"
	"strings"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/driver/desktop"
	"fyne.io/fyne/v2/layout"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"github.com/flopp/go-findfont"
	"github.com/go-vgo/robotgo"

	"ovirtClient/application"
)

var logger *log.Logger

var colorDanger = color.NRGBA{207, 19, 34, 255}
var colorSuccess = color.NRGBA{56, 158, 13, 255}
var colorFail = color.NRGBA{144, 147, 153, 255}
var colorWarning = color.NRGBA{212, 136, 6, 255}

func init() {
	// 设置中文字体
	fontPaths := findfont.List()
	for _, path := range fontPaths {
		if strings.Contains(path, "cangerw02.ttf") || strings.Contains(path, "simhei.ttf") || strings.Contains(path, "simsun.ttc") || strings.Contains(path, "simkai.ttf") {
			os.Setenv("FYNE_FONT", path)
			break
		}
	}
	// 日志文件
	file := "./vmclient" + time.Now().Format("20180102") + ".log"
	logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
	if err != nil {
		panic(err)
	}
	logger = log.New(logFile, "", log.LstdFlags)
}

func main() {

	app := app.New()
	// 自定义主题
	// app.Settings().SetTheme(&ThemeDefault{})
	themeDiy := theme.LightTheme()
	app.Settings().SetTheme(themeDiy)

	// 窗口设置
	var window fyne.Window
	if runtime.GOOS == "linux" {
		drv, _ := app.Driver().(desktop.Driver)
		window = drv.CreateSplashWindow()
		window.SetTitle("ovirtClient-v1.0.0")
		// 屏幕最大值
		width, height := robotgo.GetScreenSize()
		window.Resize(fyne.NewSize(float32(width), float32(height-1)))
	} else {
		window = app.NewWindow("ovirtClient-v1.0.0")
	}
	window.SetIcon(resourceStaticAppPng)

	// 数据预处理
	// 获取本地登录信息
	strUsername := binding.NewString()
	strPassword := binding.NewString()
	strDatacenter := binding.NewString()
	resultLoginInfo := application.LoginInfoGet()
	// ######################虚拟机选择#######################
	var vmStrList binding.ExternalStringList
	vmStrList = binding.BindStringList(&[]string{})
	// 用户自动登录
	if resultLoginInfo.ErrorCode <= 0 && resultLoginInfo.Info.Username != "" {
		vmListResult := application.VmList()
		logger.Println("自动登录vmList=", vmListResult.VmList)
		vmStrList.Set([]string{})
		for _, vmInfo := range vmListResult.VmList {
			vmStrList.Append(vmInfo.Name + "##" + vmInfo.System + "##" + vmInfo.Status + "##" + vmInfo.Description)
		}
	} else {
		vmStrList.Append("##" + "##no_login##")
	}

	// 系统icon
	// imgWin7 := canvas.NewImageFromResource(resourceWindows7Png)
	// imgWin7.FillMode = canvas.ImageFillContain
	// imgWin7.SetMinSize(fyne.NewSize(26, 26))
	// imgWin10 := canvas.NewImageFromResource(resourceWindows10Png)
	// imgWin10.FillMode = canvas.ImageFillContain
	// imgWin10.SetMinSize(fyne.NewSize(26, 26))
	// vmList
	vmListDiv := widget.NewListWithData(vmStrList,
		func() fyne.CanvasObject {
			return container.New(layout.NewGridLayout(5),
				widget.NewLabelWithStyle("主机名", fyne.TextAlignCenter, fyne.TextStyle{}),
				widget.NewLabelWithStyle("系统", fyne.TextAlignCenter, fyne.TextStyle{}),
				canvas.NewText("状态", nil),
				container.NewHBox(
					widget.NewButton("重启", nil),
					widget.NewButton("关机", nil),
					widget.NewButton("开机", nil)),
				container.NewCenter(
					widget.NewButton("登录主机", nil)),
			)
		},
		func(item binding.DataItem, obj fyne.CanvasObject) {
			vmStr, _ := item.(binding.String).Get()
			vmArr := strings.Split(vmStr, "##")
			// 主机名
			labelHostName := obj.(*fyne.Container).Objects[0].(*widget.Label)
			if len(vmArr[0]) > 14 {
				nameRune := []rune(vmArr[0])
				labelHostName.SetText(string(nameRune[:14]))
			} else {
				labelHostName.SetText(vmArr[0])
			}
			// 系统
			obj.(*fyne.Container).Objects[1].(*widget.Label).SetText(vmArr[1])
			// 状态
			labelVmStatus := obj.(*fyne.Container).Objects[2].(*canvas.Text)
			labelVmStatus.TextSize = 16
			labelVmStatus.TextStyle = fyne.TextStyle{
				Bold: true,
			}
			var vmStatus string
			switch vmArr[2] {
			case "up":
				vmStatus = "已开机"
				labelVmStatus.Color = colorSuccess
			case "down":
				vmStatus = "已关机"
				labelVmStatus.Color = colorFail
			case "wait_for_launch":
				vmStatus = "准备中..."
				labelVmStatus.Color = colorWarning
			case "powering_up":
				vmStatus = "开机中..."
				labelVmStatus.Color = colorDanger
			case "reboot_in_progress":
				vmStatus = "重启中..."
				labelVmStatus.Color = colorDanger
			case "no_vm":
				vmStatus = "没有主机记录"
				labelVmStatus.Color = colorWarning
			case "no_login":
				vmStatus = "请先登录账号"
			}
			labelVmStatus.Text = vmStatus
			// 操作按钮
			btnReboot := obj.(*fyne.Container).Objects[3].(*fyne.Container).Objects[0].(*widget.Button)
			btnShutdown := obj.(*fyne.Container).Objects[3].(*fyne.Container).Objects[1].(*widget.Button)
			btnStart := obj.(*fyne.Container).Objects[3].(*fyne.Container).Objects[2].(*widget.Button)
			btnConnect := obj.(*fyne.Container).Objects[4].(*fyne.Container).Objects[0].(*widget.Button)
			if vmArr[2] == "down" {
				btnReboot.Show()
				btnShutdown.Show()
				btnStart.Show()
				btnConnect.Show()

				btnReboot.Disable()
				btnShutdown.Disable()
				btnConnect.Disable()
				// 开机
				btnStart.Enable()
				btnStart.OnTapped = func() {
					startResult := application.VmStart(vmArr[0])
					dialog.ShowInformation("", startResult.Message, window)
					if startResult.ErrorCode <= 0 {
						go application.TimerTask(5*time.Second, 20, func() {
							vmListRes := application.VmList()
							vmStrList.Set([]string{})
							for _, vmInfo := range vmListRes.VmList {
								vmStrList.Append(vmInfo.Name + "##" + vmInfo.System + "##" + vmInfo.Status + "##" + vmInfo.Description)
							}
							// logger.Println("定时刷新vmlist=", vmListRes.VmList)
						})
					}
				}
			} else if vmArr[2] == "up" {
				btnReboot.Show()
				btnShutdown.Show()
				btnStart.Show()
				btnConnect.Show()
				btnStart.Disable()
				// 重启
				btnReboot := obj.(*fyne.Container).Objects[3].(*fyne.Container).Objects[0].(*widget.Button)
				btnReboot.Enable()
				btnReboot.OnTapped = func() {
					cnf := dialog.NewConfirm("", "确认重启吗?", func(b bool) {
						if b != true {
							return
						}
						rebootResult := application.VmReboot(vmArr[0])
						dialog.ShowInformation("", rebootResult.Message, window)
						if rebootResult.ErrorCode <= 0 {
							go application.TimerTask(5*time.Second, 20, func() {
								vmListRes := application.VmList()
								vmStrList.Set([]string{})
								for _, vmInfo := range vmListRes.VmList {
									vmStrList.Append(vmInfo.Name + "##" + vmInfo.System + "##" + vmInfo.Status + "##" + vmInfo.Description)
								}
								// logger.Println("定时刷新vmlist=", vmListRes.VmList)
							})
						}
					}, window)
					cnf.SetDismissText("取消")
					cnf.SetConfirmText("确认")
					cnf.Show()
				}
				btnShutdown.Enable()
				btnShutdown.OnTapped = func() {
					cnf := dialog.NewConfirm("", "确认关机吗?", func(b bool) {
						rebootResult := application.VmShutdown(vmArr[0])
						dialog.ShowInformation("", rebootResult.Message, window)
						if rebootResult.ErrorCode <= 0 {
							go application.TimerTask(5*time.Second, 20, func() {
								vmListRes := application.VmList()
								vmStrList.Set([]string{})
								for _, vmInfo := range vmListRes.VmList {
									vmStrList.Append(vmInfo.Name + "##" + vmInfo.System + "##" + vmInfo.Status + "##" + vmInfo.Description)
								}
								// logger.Println("定时刷新vmlist=", vmListRes.VmList)
							})
						}
					}, window)
					cnf.SetDismissText("取消")
					cnf.SetConfirmText("确认")
					cnf.Show()
				}
				// 登录
				btnConnect := obj.(*fyne.Container).Objects[4].(*fyne.Container).Objects[0].(*widget.Button)
				btnConnect.Enable()
				btnConnect.OnTapped = func() {
					// dialog.ShowInformation("", "登录中...", window)
					connectResult := application.VmConnect(vmArr[0])
					if connectResult.ErrorCode > 0 {
						dialog.ShowInformation("", connectResult.Message, window)
					}
				}
			} else if vmArr[2] == "no_login" || vmArr[2] == "no_vm" {
				btnReboot.Hide()
				btnShutdown.Hide()
				btnStart.Hide()
				btnConnect.Hide()
			} else {
				btnReboot.Show()
				btnShutdown.Show()
				btnStart.Show()
				btnConnect.Show()
				btnReboot.Disable()
				btnShutdown.Disable()
				btnStart.Disable()
				btnConnect.Disable()
			}

		})
	vmListDivContain := container.New(layout.NewGridWrapLayout(fyne.NewSize(800, 560)), vmListDiv)

	vmListTopBtn := widget.NewButton("刷新", func() {
		vmListResult := application.VmList()
		logger.Println("手动刷新vmlistResult=", vmListResult)
		if vmListResult.ErrorCode > 0 {
			dialog.ShowInformation("", vmListResult.Message, window)
			return
		}
		vmStrList.Set([]string{})
		for _, vmInfo := range vmListResult.VmList {
			vmStrList.Append(vmInfo.Name + "##" + vmInfo.System + "##" + vmInfo.Status + "##" + vmInfo.Description)
		}
		logger.Println("手动刷新vmlist=", vmListResult.VmList)
	})

	vmListTopContain := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), widget.NewLabel("主机列表"), vmListTopBtn, layout.NewSpacer())

	vmListTitleContain := container.New(layout.NewGridLayout(5),
		widget.NewLabelWithStyle("主机名", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
		widget.NewLabelWithStyle("系统", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
		widget.NewLabelWithStyle("状态", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
		widget.NewLabelWithStyle("操作", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
		widget.NewLabelWithStyle("登录", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
	)
	vmListWrap := container.New(layout.NewVBoxLayout(), vmListTopContain, vmListTitleContain, vmListDivContain)
	// tabs.Append(container.NewTabItemWithIcon("主机", theme.ComputerIcon(), vmListWrap))
	// ######################登录页面#######################
	// 自动填充
	if resultLoginInfo.ErrorCode <= 0 && resultLoginInfo.Info.Username != "" {
		strUsername.Set(resultLoginInfo.Info.Username)
		strPassword.Set(resultLoginInfo.Info.Password)
		strDatacenter.Set(resultLoginInfo.Info.Datacenter)
	}
	entryUsername := widget.NewEntryWithData(strUsername)
	entryUsername.SetPlaceHolder("请输入账号")
	entryPassword := widget.NewEntryWithData(strPassword)
	entryPassword.SetPlaceHolder("请输入密码")
	entryDatacenter := widget.NewEntryWithData(strDatacenter)
	entryDatacenter.SetPlaceHolder("请输入地址,如192.168.0.246:443")

	formLogin := &widget.Form{
		BaseWidget: widget.BaseWidget{},
		Items: []*widget.FormItem{
			{Text: "登录账号: ", Widget: entryUsername},
			{Text: "登录密码: ", Widget: entryPassword},
			{Text: "平台地址: ", Widget: entryDatacenter},
		},
		OnSubmit: func() { // optional, handle form submission
			// 检查
			if len(entryUsername.Text) == 0 || len(entryPassword.Text) == 0 {
				dialog.ShowInformation("", "请输入账号和密码", window)
				return
			}
			if len(entryDatacenter.Text) == 0 {
				dialog.ShowInformation("", "请输入平台地址", window)
				return
			}

			loginResult := application.Login(entryUsername.Text, entryPassword.Text, entryDatacenter.Text)
			logger.Println("首次登录loginResult=", loginResult)
			dialog.ShowInformation("", loginResult.Message, window)
			if loginResult.ErrorCode > 0 {
				return
			}
			vmListResult := application.VmList()
			logger.Println("首次登录vmList=", vmListResult.VmList)
			vmStrList.Set([]string{})
			for _, vmInfo := range vmListResult.VmList {
				vmStrList.Append(vmInfo.Name + "##" + vmInfo.System + "##" + vmInfo.Status + "##" + vmInfo.Description)
			}

		},
		OnCancel:   nil,
		SubmitText: "保存登录账号",
		CancelText: "",
	}
	// 测试平台
	entryIp := widget.NewEntry()
	entryIp.SetPlaceHolder("请输入IP, 如192.168.0.246")
	entryPort := widget.NewEntry()
	entryPort.SetPlaceHolder("请输入端口号, 默认443")
	formDatacenter := &widget.Form{
		Items: []*widget.FormItem{
			{Text: "平台的IP: ", Widget: entryIp},
			{Text: "平台端口: ", Widget: entryPort},
		},
		SubmitText: "连接平台测试",
		OnSubmit: func() { // optional, handle form submission
			addResult := application.DatacenterTest(entryIp.Text, entryPort.Text)
			dialog.ShowInformation("", addResult.Message, window)
		},
	}
	datacenterTopContain := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), widget.NewLabel("平台连接测试"), layout.NewSpacer())
	datacenterAddDiv := container.New(layout.NewGridWrapLayout(fyne.NewSize(380, 100)), formDatacenter)
	datacenterWrap := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), datacenterAddDiv, layout.NewSpacer())

	formLoginDiv := container.New(layout.NewGridWrapLayout(fyne.NewSize(380, 230)), formLogin)
	formLoginWrap := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), formLoginDiv, layout.NewSpacer())
	loginTopContain := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), widget.NewLabel("登录账号设置"), layout.NewSpacer())
	loginWrap := container.New(layout.NewVBoxLayout(), loginTopContain, formLoginWrap, datacenterTopContain, datacenterWrap)
	// tabs.Append(container.NewTabItemWithIcon("登录", theme.AccountIcon(), loginWrap))
	// ######################设置#######################
	// settingTopContain := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), widget.NewLabel("设置"), layout.NewSpacer())
	// settingWrap := container.New(layout.NewVBoxLayout(), settingTopContain)
	// tabs.Append(container.NewTabItemWithIcon("设置", theme.SettingsIcon(), settingWrap))
	// ######################关于#######################
	aboutDiv := container.New(layout.NewHBoxLayout(), widget.NewLabel("适用于oVirt4.x"), widget.NewLabel("版本: v1.0.0-20220707"), widget.NewLabel("微信: timeispower7"))
	aboutTopContain := container.New(layout.NewHBoxLayout(), layout.NewSpacer(), widget.NewLabel("关于"), layout.NewSpacer())
	aboutWrap := container.New(layout.NewVBoxLayout(), aboutTopContain, aboutDiv)

	// 窗口内容
	// 选项卡
	tabs := container.NewAppTabs(
		container.NewTabItemWithIcon("主机", theme.ComputerIcon(), vmListWrap),
		container.NewTabItemWithIcon("登录", theme.AccountIcon(), loginWrap),
		container.NewTabItemWithIcon("关于", theme.DocumentIcon(), aboutWrap),
	)
	if resultLoginInfo.ErrorCode > 0 {
		tabs.SelectTabIndex(1)
	}

	tabs.SetTabLocation(container.TabLocationLeading)
	tabsWithBorder := container.NewBorder(application.MakeCell(10), application.MakeCell(10), application.MakeCell(10), application.MakeCell(10), tabs)

	tabsWithBg := container.New(layout.NewMaxLayout(), canvas.NewRectangle(&color.NRGBA{255, 255, 255, 255}), tabsWithBorder)
	tabsWrap := container.NewCenter(tabsWithBg)

	windowBgImg := canvas.NewImageFromResource(resourceStaticAppbgJpg)
	windowContent := container.New(layout.NewMaxLayout(), windowBgImg, tabsWrap)
	window.SetContent(windowContent)
	// window.SetFullScreen(true)
	window.ShowAndRun()
}

标签:widget,桌面,New,fyne,NewSpacer,编写,container,layout
来源: https://www.cnblogs.com/sentangle/p/16497726.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有