Golang Fyne项目实战(含源码)
生活随笔
收集整理的這篇文章主要介紹了
Golang Fyne项目实战(含源码)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Golang Fyne項目實戰(含源碼)
- 項目介紹
- 效果圖
- 功能介紹
- 步驟介紹
- 代碼區域
- 項目結構
- 下載fyne包以及Fyne工具包
- 追加靜態資源,程序設置圖標
- 完整代碼
- 結尾
項目介紹
效果圖
功能介紹
主要實現了根據文本文件里面的內容,自動更名所選文件夾里面的文件名稱
步驟介紹
1.創建txt文本文件,輸入內容程序界面中"目錄文件"選擇目前創建的文本文件
例:
2.選擇需要批量更改名字的文件夾
3.選擇路徑后,程序點擊"開始更名",便會自動更名
4.結果
代碼區域
項目結構
下載fyne包以及Fyne工具包
命令:
1.go get fyne.io/fyne/v2
2.go get fyne.io/fyne/cmd/fyne
追加靜態資源,程序設置圖標
1.將靜態資源編譯為 go 文件 (在自己的項目目錄打開終端執行):fyne bundle fav.png >> bundled.go
2. 打開 bundled.go 文件會看到一個變量 resourceFavPng
3.設置窗口圖標,任務欄圖標
//主要代碼
a := app.New()
a.SetIcon(resourceFavPng) //本地運行的注釋,否則報錯,打包的時候在把此行代碼打開
完整代碼
package mainimport ("YHSoft/Demo/GUIDemo/FyneDemo/02_RenameFileName/models" //更換成自己的項目路徑"errors""fmt""fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/container""fyne.io/fyne/v2/dialog""fyne.io/fyne/v2/layout""fyne.io/fyne/v2/storage""fyne.io/fyne/v2/widget""github.com/flopp/go-findfont""io/ioutil""log""os""path/filepath""strconv""strings""time""unicode" )func main() {//新建一個appa := app.New()//設置窗口欄,任務欄圖標a.SetIcon(resourceIconPng)//新建一個窗口w := a.NewWindow("自動化更名程序V1.0")//主界面框架布局MainShow(w)//尺寸w.Resize(fyne.Size{Width: 500, Height: 100})//w居中顯示w.CenterOnScreen()//循環運行w.ShowAndRun()err := os.Unsetenv("FYNE_FONT")if err != nil {return} }var tileInfo string var done = make(chan bool) var stop = make(chan int, 1) var num int64// MainShow 主界面函數 func MainShow(w fyne.Window) {//var ctrl *beep.Ctrltitle := widget.NewLabel("自動化更名程序")hello := widget.NewLabel("目錄文件:")entry1 := widget.NewEntry() //文本輸入框//entry1.SetText("E:\\rename_temp2\\123.txt")dia1 := widget.NewButton("打開", func() { //回調函數:打開選擇文件對話框fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {if err != nil {dialog.ShowError(err, w)return}if reader == nil {log.Println("Cancelled")return}entry1.SetText(reader.URI().Path()) //把讀取到的路徑顯示到輸入框中}, w)fd.SetFilter(storage.NewExtensionFileFilter([]string{".txt"})) //打開的文件格式類型fd.Show() //控制是否彈出選擇文件目錄對話框})text := widget.NewMultiLineEntry() //多行輸入組件//text.Disable() //禁用輸入框,不能更改數據labelLast := widget.NewLabel("發飆的蝸牛 ALL Right Reserved")//labelLast := widget.NewLabel(" ")label4 := widget.NewLabel("文件路徑:")entry2 := widget.NewEntry()//entry2.SetText("E:\\rename_temp2\\寶崗路停車場項目幕墻施工圖PDF")dia2 := widget.NewButton("打開", func() {dialog.ShowFolderOpen(func(list fyne.ListableURI, err error) {if err != nil {dialog.ShowError(err, w)return}if list == nil {log.Println("Cancelled")return}//設置輸入框內容entry2.SetText(list.Path())}, w)})//開始更名按鈕bt3 := widget.NewButton("開始 更名", func() {go func() {if (entry1.Text != "") && (entry2.Text != "") {text.SetText("")text.Refresh()if num != 0 {stop <- 1return} else {err := generateTxt(entry1.Text, entry2.Text, text)if err != nil {dialog.ShowError(err, w)}text.Refresh()}} else {dialog.ShowError(errors.New("讀取TXT文件錯誤"), w)}}()})//停止更名按鈕bt4 := widget.NewButton("停止 更名", func() {go func() {done <- false}()})head := container.NewCenter(title)v1 := container.NewBorder(layout.NewSpacer(), layout.NewSpacer(), hello, dia1, entry1)v4 := container.NewBorder(layout.NewSpacer(), layout.NewSpacer(), label4, dia2, entry2)v5 := container.NewHBox(bt3, bt4)v5Center := container.NewCenter(v5)ctnt := container.NewVBox(head, v1, v4, v5Center, text, labelLast) //控制顯示位置順序w.SetContent(ctnt) }//設置字體 func init() {fontPaths := findfont.List()for _, fontPath := range fontPaths {//fmt.Println(fontPath)//楷體:simkai.ttf//黑體:simhei.ttf//微軟雅黑:msyh.ttcif strings.Contains(fontPath, "simkai.ttf") {err := os.Setenv("FYNE_FONT", fontPath)if err != nil {return}break}} }//讀取數據校驗數據 func generateTxt(inPath, outPath string, text *widget.Entry) error {//標題tileInfo += "開始處理,正在讀取文件...\n"text.SetText(tileInfo)nameList,err := models.GetStrList(inPath)if err != nil{tileInfo += "讀取文件出錯...\n"text.SetText(tileInfo)}//獲取文件路徑的文件files, _ := ioutil.ReadDir(outPath)var fileNameList []stringfor _, file := range files {// 帶擴展名的文件名fullFilename := file.Name()//添加文件數據到切片中fileNameList = append(fileNameList, fullFilename)}if len(nameList) == 0 || len(fileNameList) == 0{tileInfo += "已停止處理...\n"text.SetText(tileInfo) //設置多行顯示控件中的內容return errors.New("找不到路徑或路徑下不存在此文件")}if len(nameList) != len(fileNameList) {tileInfo += "已停止處理...\n"text.SetText(tileInfo) //設置多行顯示控件中的內容return errors.New("目錄行數與文件行數不相等,請檢查!")}renameFile(nameList, fileNameList, outPath, text)return nil }//操作更名文件 func renameFile(nameList []string, fileNameList []string, outPath string, text *widget.Entry) {var newName string//遍歷更改for index, fullFilename := range fileNameList {select {case <-done: //讀管道中內容,沒有內容前,阻塞//擴展名fileExt := filepath.Ext(fullFilename)//fmt.Println("nameList[index]=",nameList[index])defaultName := nameList[index] //文本文件初始名稱var defaultNameCode []stringvar defaultNameNewCode stringrune := []rune(defaultName)for i := len(rune); i > 0; i-- {if !unicode.Is(unicode.Han, rune[i-1]) {defaultNameCode = append(defaultNameCode, string(rune[i-1]))} else {break}}//重新編排名稱編號for i := len(defaultNameCode); i > 0; i-- {defaultNameNewCode += defaultNameCode[i-1]}//fmt.Println("defaultName=", defaultName)//重組新名稱newName = strconv.Itoa(index+1) + " " + strings.ReplaceAll(defaultName, defaultNameNewCode, "") + " " + defaultNameNewCode// 不帶擴展名的文件名//filenameOnly := strings.TrimSuffix(fullFilename, fileExt)//將每個文件名后面加上1,擴展名不變err := os.Rename(outPath+`\`+fullFilename, outPath+`\`+newName+fileExt)if err != nil {fmt.Println("err=", err)}tileInfo += "處理數據文件:" + fullFilename + "\n"time.Sleep(time.Second * 1)text.SetText(tileInfo) //設置多行顯示控件中的 內容tileInfo += "停止更名...\n"text.SetText(tileInfo) //設置多行顯示控件中的內容num = num + 1<-stop //讀管道中內容,沒有內容前,阻塞default://擴展名fileExt := filepath.Ext(fullFilename)//fmt.Println("nameList[index]=",nameList[index])defaultName := nameList[index] //文本文件初始名稱var defaultNameCode []stringvar defaultNameNewCode stringrune := []rune(defaultName)for i := len(rune); i > 0; i-- {if !unicode.Is(unicode.Han, rune[i-1]) {defaultNameCode = append(defaultNameCode, string(rune[i-1]))} else {break}}//重新編排名稱編號for i := len(defaultNameCode); i > 0; i-- {defaultNameNewCode += defaultNameCode[i-1]}//fmt.Println("defaultName=", defaultName)//重組新名稱newName = strconv.Itoa(index+1) + " " + strings.ReplaceAll(defaultName, defaultNameNewCode, "") + " " + defaultNameNewCode// 不帶擴展名的文件名//filenameOnly := strings.TrimSuffix(fullFilename, fileExt)//將每個文件名后面加上1,擴展名不變err := os.Rename(outPath+`\`+fullFilename, outPath+`\`+newName+fileExt)if err != nil {fmt.Println("err=", err)}tileInfo += "處理數據文件:" + fullFilename + "\n"//time.Sleep(time.Second * 1)text.SetText(tileInfo) //設置多行顯示控件中的 內容}}tileInfo += "處理完畢!"text.SetText(tileInfo) //設置多行顯示控件中的內容num = 0 } package modelsimport ("bufio""fmt""github.com/axgle/mahonia""io""os""strings" )//讀取txt文件,自動判斷編碼格式 func GetStrList(path string)([]string,error){f, err := os.Open(path) //打開目錄路徑txt文件if err != nil {return nil, err}defer f.Close() //最后關閉文件r := bufio.NewReader(f)buf := make([]byte, 1024)var res string_, err = r.Read(buf)if err != nil && err != io.EOF {return nil,err}res = GetStrCoding(buf)if res == "UTF8" {return GetTextContentUTF8(path),nil} else {return GetTextContentGbk(path),nil} }//讀取gbk編碼格式的文件 func GetTextContentGbk(txtPath string) []string {f, err := os.Open(txtPath) //打開目錄路徑txt文件if err != nil {fmt.Println("err=", err)}defer f.Close()decoder := mahonia.NewDecoder("gbk")r := bufio.NewReader(decoder.NewReader(f))chunks := []byte{}buf := make([]byte, 1024)for {n, err := r.Read(buf)if err != nil && err != io.EOF {panic(err)}if 0 == n {break}chunks = append(chunks, buf[:n]...)}nameStr := strings.ReplaceAll(string(chunks), "\r\n", ",")return strings.Split(nameStr, ",") }//讀取utf8編碼格式的文件 func GetTextContentUTF8(txtPath string) []string {f, err := os.Open(txtPath) //打開目錄路徑txt文件if err != nil {fmt.Println("err=", err)}defer f.Close()r := bufio.NewReader(f)chunks := []byte{}buf := make([]byte, 1024)for {n, err := r.Read(buf)if err != nil && err != io.EOF {panic(err)}if 0 == n {break}chunks = append(chunks, buf[:n]...)}nameStr := strings.ReplaceAll(string(chunks), "\r\n", ",")return strings.Split(nameStr, ",") }const (GBK string = "GBK"UTF8 string = "UTF8"UNKNOWN string = "UNKNOWN" )//判斷文本文件格式 func GetStrCoding(data []byte) string {if isUtf8(data) == true {return UTF8} else if isGBK(data) == true {return GBK} else {return UNKNOWN} }func isGBK(data []byte) bool {length := len(data)var i = 0for i < length {if data[i] <= 0x7f {//編碼0~127,只有一個字節的編碼,兼容ASCII碼i++continue} else {//大于127的使用雙字節編碼,落在gbk編碼范圍內的字符if data[i] >= 0x81 &&data[i] <= 0xfe &&data[i+1] >= 0x40 &&data[i+1] <= 0xfe &&data[i+1] != 0xf7 {i += 2continue} else {return false}}}return true }func preNUm(data byte) int {var mask byte = 0x80var num int = 0//8bit中首個0bit前有多少個1bitsfor i := 0; i < 8; i++ {if (data & mask) == mask {num++mask = mask >> 1} else {break}}return num }func isUtf8(data []byte) bool {i := 0for i < len(data) {if (data[i] & 0x80) == 0x00 {// 0XXX_XXXXi++continue} else if num := preNUm(data[i]); num > 2 {// 110X_XXXX 10XX_XXXX// 1110_XXXX 10XX_XXXX 10XX_XXXX// 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX// 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX// 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX// preNUm() 返回首個字節的8個bits中首個0bit前面1bit的個數,該數量也是該字符所使用的字節數i++for j := 0; j < num-1; j++ {//判斷后面的 num - 1 個字節是不是都是10開頭if (data[i] & 0xc0) != 0x80 {return false}i++}} else {//其他情況說明不是utf-8return false}}return true }結尾
代碼可能不是最完美的,但是能實現想要的功能,也感謝各路大神的項目案列,也讓自己有了相關代碼的參考!
取之于民,用之于民!最后也歡迎各位的指教,共同交流進步!
總結
以上是生活随笔為你收集整理的Golang Fyne项目实战(含源码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kubernetes 菜鸟_菜鸟系列k8
- 下一篇: Java实现圆面积计算