做的好的大學(xué)生旅行有哪些網(wǎng)站好seo優(yōu)化策略
本文檔注意參考官網(wǎng)(developer.fyne.io/) 編寫, 只保留基本用法
go代碼展示為Go 1.16
?及更高版本,?ide
為goland2021.2???????
?這是一個(gè)系列文章:
Fyne ( go跨平臺(tái)GUI )中文文檔-入門(一)-CSDN博客
Fyne ( go跨平臺(tái)GUI )中文文檔-Fyne總覽(二)-CSDN博客
Fyne ( go跨平臺(tái)GUI )中文文檔-繪圖和動(dòng)畫(三)-CSDN博客
Fyne ( go跨平臺(tái)GUI )中文文檔-容器和布局 (四)-CSDN博客
Fyne ( go跨平臺(tái)GUI )中文文檔-小部件 (五)-CSDN博客
Fyne ( go跨平臺(tái)GUI )中文文檔- 數(shù)據(jù)綁定 (六)-CSDN博客
Fyne ( go跨平臺(tái)GUI )中文文檔- 擴(kuò)展Fyne (七)-CSDN博客
Fyne ( go跨平臺(tái)GUI )中文文檔- 架構(gòu) (八)完結(jié)-CSDN博客
2.Fyne總覽
2.1 Canvas(畫布) and CanvasObject
在 Fyne 中Canvas
是在其中繪制應(yīng)用程序的區(qū)域。每個(gè)窗口都有一個(gè)您可以通過Window.Canvas()
訪問的Canvas
,但通常您會(huì)在上面找到Window
避免訪問畫布的功能。
可以在?Fyne
中繪制的所有內(nèi)容都是CanvasObject
. 這里的示例打開一個(gè)新窗口,然后通過設(shè)置窗口畫布的內(nèi)容來顯示不同類型的原始圖形元素。如文本和圓形示例所示,可以通過多種方式自定義每種類型的對(duì)象。
除了更改顯示Canvas.SetContent()
的內(nèi)容外,還可以更改當(dāng)前可見的內(nèi)容。例如,如果您更改FillColour
矩形的 ,則可以使用 請(qǐng)求刷新此現(xiàn)有組件rect.Refresh()
。
package mainimport ("image/color""time""fyne.io/fyne/v2""fyne.io/fyne/v2/app""fyne.io/fyne/v2/canvas"
)func main() {myApp := app.New()myWindow := myApp.NewWindow("Canvas")myCanvas := myWindow.Canvas()blue := color.NRGBA{R: 0, G: 0, B: 180, A: 255}rect := canvas.NewRectangle(blue)myCanvas.SetContent(rect)go func() {time.Sleep(time.Second)green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}rect.FillColor = greenrect.Refresh()}()myWindow.Resize(fyne.NewSize(100, 100))myWindow.ShowAndRun()
}
我們可以用同樣的方式繪制很多不同的繪圖元素,比如圓形和文字。
func setContentToText(c fyne.Canvas) {green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}text := canvas.NewText("Text", green)text.TextStyle.Bold = truec.SetContent(text)
}func setContentToCircle(c fyne.Canvas) {red := color.NRGBA{R: 0xff, G: 0x33, B: 0x33, A: 0xff}circle := canvas.NewCircle(color.White)circle.StrokeWidth = 4circle.StrokeColor = redc.SetContent(circle)
}
小部件(Widget)
fyne.Widget
是一種特殊類型的畫布對(duì)象,它具有與之關(guān)聯(lián)的交互元素。在小部件中,邏輯與其外觀(也稱為?WidgetRenderer
)是分開的。
小部件也是CanvasObject
一種類型,因此我們可以將窗口的內(nèi)容設(shè)置為單個(gè)小部件。在這個(gè)例子中看看我們?nèi)绾蝿?chuàng)建一個(gè)新的?widget.Entry
并將其設(shè)置為窗口的內(nèi)容。
package mainimport ("fyne.io/fyne/v2/app""fyne.io/fyne/v2/widget"
)func main() {myApp := app.New()myWindow := myApp.NewWindow("Widget")myWindow.SetContent(widget.NewEntry())myWindow.ShowAndRun()
}
2.2 Container and Layouts(容器和布局)
在前面的示例中,我們看到了如何將?CanvasObject
?設(shè)置為Canvas
的內(nèi)容,但只顯示一個(gè)視覺元素并不是很有用。為了顯示多個(gè)項(xiàng)目,我們使用Container
類型。
由于fyne.Container
也是?fyne.CanvasObject
,我們可以將其設(shè)置為fyne.Canvas
?的內(nèi)容。在本例中,我們創(chuàng)建了 3 個(gè)文本對(duì)象,然后使用container.NewWithoutLayout()
函數(shù)將它們放入容器中。由于沒有布局集,我們可以用text2.Move()
移動(dòng)元素。
fyne.Layout
實(shí)現(xiàn)了一種在容器內(nèi)組織項(xiàng)目的方法。通過取消注釋container.New()
此示例中的行,您可以更改容器以使用具有 2 列的網(wǎng)格布局。運(yùn)行此代碼并嘗試調(diào)整窗口大小以查看布局如何自動(dòng)配置窗口的內(nèi)容。另請(qǐng)注意,text2布局代碼忽略了手動(dòng)位置。
要查看更多信息,您可以查看Layout list
.
2.3 小部件(Widget)列表
2.3.1 標(biāo)準(zhǔn)小部件(widget
包)
手風(fēng)琴(Accordion )
Accordion 顯示 AccordionItems 列表。每個(gè)項(xiàng)目都由一個(gè)按鈕表示,點(diǎn)擊該按鈕會(huì)顯示詳細(xì)視圖。
按鈕(Button)
按鈕小部件具有文本標(biāo)簽和圖標(biāo),兩者都是可選的。
卡片(Card)
卡片小部件使用標(biāo)題和子標(biāo)題對(duì)元素進(jìn)行分組,所有這些都是可選的。
復(fù)選框(Check )
檢查小部件有一個(gè)文本標(biāo)簽和一個(gè)選中(或未選中)的圖標(biāo)。
輸入框(Entry)
輸入框小部件允許在獲得焦點(diǎn)時(shí)輸入簡單的文本。
PasswordEntry 小部件隱藏文本輸入并添加一個(gè)按鈕來顯示文本。
文件圖標(biāo)(FileIcon)
FileIcon 為各種類型的文件提供有用的標(biāo)準(zhǔn)圖標(biāo)。它將文件類型顯示為指示器圖標(biāo)并顯示文件類型的擴(kuò)展名。
表單(Form)
表單小部件是兩列網(wǎng)格,其中每一行都有一個(gè)標(biāo)簽和一個(gè)小部件(通常是一個(gè)輸入)。最后一行將包含適當(dāng)?shù)谋韱慰刂瓢粹o。
超鏈接(Hyperlink)
超鏈接小部件是具有適當(dāng)填充和布局的文本組件。單擊后,URL 將在您的默認(rèn) Web 瀏覽器中打開。
圖標(biāo)(Icon)
圖標(biāo)小部件是一個(gè)基本的圖像組件,它加載其資源以匹配主題。
標(biāo)簽(Label )
標(biāo)簽小部件是具有適當(dāng)填充和布局的標(biāo)簽組件。
進(jìn)度條(ProgressBar)
ProgressBar 小部件創(chuàng)建一個(gè)指示進(jìn)度的水平面板。
ProgressBarInfinite 小部件創(chuàng)建一個(gè)水平面板,指示無限進(jìn)度條 0% -> 100% 重復(fù)循環(huán),直到調(diào)用 Stop()。
單選框組(RadioGroup)
RadioGroup 小部件有一個(gè)文本標(biāo)簽列表和每個(gè)旁邊的單選檢查圖標(biāo)。
下拉選擇框(Select)
選擇小部件有一個(gè)選項(xiàng)列表,顯示當(dāng)前選項(xiàng),并在單擊時(shí)觸發(fā)事件函數(shù)。
下拉選擇框可輸入選擇(SelectEntry)
小部件將可編輯組件添加到下拉選擇框小部件。用戶可以選擇一個(gè)選項(xiàng)或輸入自己的值。
分割線(Separator)
分隔小部件顯示其他元素之間的分界線。
滑塊(Slider)
Slider小部件可以在兩個(gè)固定值之間滑動(dòng)切換。
文本網(wǎng)格(TextGrid )
TextGrid 是一個(gè)等寬的字符網(wǎng)格。這旨在供文本編輯器、代碼預(yù)覽或終端仿真器使用。
工具欄(Toolbar)
工具欄小部件創(chuàng)建工具按鈕的水平列表。
2.3.2 集成小部件(widget
包)
集成小部件提供高級(jí)緩存功能,以提供海量數(shù)據(jù)的高性能呈現(xiàn)。這確實(shí)導(dǎo)致了一個(gè)更復(fù)雜的構(gòu)造函數(shù),但是對(duì)于它實(shí)現(xiàn)的結(jié)果來說是一個(gè)很好的平衡。這些小部件中的每一個(gè)都使用一系列回調(diào),最小集合由它們的構(gòu)造函數(shù)定義,其中包括數(shù)據(jù)大小、可重復(fù)使用的模板的創(chuàng)建、數(shù)據(jù)應(yīng)用于小部件的函數(shù)。
列表(List)
List 提供了許多子項(xiàng)的高性能垂直滾動(dòng)。
表格(Table)
表格提供了許多子項(xiàng)的高性能滾動(dòng)二維顯示。
樹(Tree)
樹提供了一個(gè)高性能的垂直滾動(dòng)項(xiàng)目,可以展開以顯示子元素。
2.3.3 容器小部件(container
包)
容器小部件類似于常規(guī)容器,但它們提供了一些額外的功能。
應(yīng)用選項(xiàng)卡(AppTabs)
AppTabs 小部件允許從 TabItems 列表切換可見內(nèi)容。每個(gè)項(xiàng)目都由小部件頂部的按鈕表示。
滾動(dòng)容器 (ScrollContainer)
ScrollContainer 定義了一個(gè)小于 Content 的容器。
分裂容器(SplitContainer)
SplitContainer 定義了一個(gè)容器,其大小在兩個(gè)子項(xiàng)之間拆分。
2.4 布局(layout)列表
水平框(HBox)
水平框?qū)㈨?xiàng)目排列在水平行中。每個(gè)元素都將具有相同的高度(容器中最高項(xiàng)目的高度),并且對(duì)象將在其最小寬度處左對(duì)齊。
垂直框 (VBox)
垂直框?qū)㈨?xiàng)目排列在垂直列中。每個(gè)元素將具有相同的寬度(容器中最寬項(xiàng)的寬度),并且對(duì)象將在其最小高度處頂部對(duì)齊。
居中(Center )
居中布局將所有容器元素放置在容器的中心。每個(gè)對(duì)象都將設(shè)置為其最小尺寸。
表單布局(Form)
表單布局將項(xiàng)目成對(duì)排列,其中第一列的寬度最小。這對(duì)于在表單中標(biāo)記元素通常很有用,其中標(biāo)簽位于第一列,而它描述的項(xiàng)目位于第二列。您應(yīng)該始終向表單布局添加偶數(shù)個(gè)元素。
網(wǎng)格(Grid)
網(wǎng)格布局在可用空間中平均排列項(xiàng)目。指定了列數(shù),對(duì)象水平放置,直到達(dá)到列數(shù),此時(shí)新行開始。所有對(duì)象具有相同的大小,即寬度除以總列,高度將是總高度除以所需的行數(shù)。減去填充。
網(wǎng)格環(huán)繞(GridWrap)
GridWrap 布局將所有項(xiàng)目排列成一行,如果空間不足,則換行到新行。所有對(duì)象都將設(shè)置為相同的大小,即傳遞給布局的大小。此布局可能不尊重項(xiàng)目 MinSize 來管理此統(tǒng)一布局。通常用于文件管理器或圖像縮略圖列表。
邊框(Border)
邊框布局支持將項(xiàng)目定位在可用空間之外。邊框被傳遞給(上、左、下、右)對(duì)象的指針。容器中未定位在邊框上的所有項(xiàng)目將填充剩余空間。
最大(max)
最大布局定位所有容器元素以填充可用空間。這些對(duì)象都將是全尺寸的,并按照它們添加到容器中的順序繪制(最后一個(gè)在頂部)。
填充(Padded)
填充布局定位所有容器元素以填充可用空間,但在外部有一個(gè)小填充。填充的大小是特定于主題的。所有對(duì)象都將按照它們添加到容器中的順序繪制(最后一個(gè)在頂部)。
組合布局
可以嵌套多個(gè)容器,每個(gè)容器都有自己的布局,以僅使用上面列出的標(biāo)準(zhǔn)布局創(chuàng)建完整的用戶界面排列。例如標(biāo)題的水平框,左側(cè)文件面板的垂直框和內(nèi)容區(qū)域中的網(wǎng)格環(huán)繞布局 - 使用邊框布局的所有容器內(nèi)都可以構(gòu)建如下所示的結(jié)果。
2.5 對(duì)話框(Dialog)列表
顏色
允許用戶從標(biāo)準(zhǔn)集(或高級(jí)模式下的任何顏色)中選擇一種顏色。
確認(rèn)
詢問動(dòng)作的構(gòu)象
文件打開
展示此內(nèi)容以要求用戶選擇要在應(yīng)用內(nèi)使用的文件。實(shí)際顯示的對(duì)話框取決于當(dāng)前的操作系統(tǒng)。
表單
在對(duì)話框中獲取各種輸入元素,并進(jìn)行驗(yàn)證。
信息
一種向應(yīng)用程序用戶呈現(xiàn)一些信息的簡單方法。
通用
在對(duì)話框容器中呈現(xiàn)任何內(nèi)容。
2.6 快捷方式
快捷方式是可以通過鍵盤組合或上下文菜單觸發(fā)的常見任務(wù)??旖莘绞?#xff0c;很像鍵盤事件,可以附加到焦點(diǎn)元素或注冊(cè)Window.Canvas
上
畫布注冊(cè)
定義了許多標(biāo)準(zhǔn)快捷鍵(例如fyne.ShortcutCopy
),它們連接到標(biāo)準(zhǔn)鍵盤快捷鍵和右鍵菜單。第一步添加Shortcut
是定義快捷方式。對(duì)于大多數(shù)用途,這將是一個(gè)鍵盤觸發(fā)的快捷方式,它是一個(gè)桌面擴(kuò)展。為此,我們使用desktop.CustomShortcut
,例如使用?Tab
?鍵和Control
?修飾符,您可以執(zhí)行以下操作:
ctrlTab := desktop.CustomShortcut{KeyName: fyne.KeyTab, Modifier: desktop.ControlModifier}
請(qǐng)注意,此快捷方式可以重復(fù)使用,因此您也可以將其附加到菜單或其他項(xiàng)目。對(duì)于此示例,我們希望它始終可用,因此我們將其注冊(cè)到我們的窗口Canvas中,如下所示:
ctrlTab := desktop.CustomShortcut{KeyName: fyne.KeyTab, Modifier: desktop.ControlModifier}w.Canvas().AddShortcut(&ctrlTab, func(shortcut fyne.Shortcut) {log.Println("We tapped Ctrl+Tab")})
如您所見,以這種方式注冊(cè)快捷方式有兩個(gè)部分 - 傳遞快捷方式定義和回調(diào)函數(shù)。如果用戶鍵入鍵盤快捷鍵,則將調(diào)用該函數(shù)并打印輸出。
輸入框(Entry)
添加快捷方式
僅在當(dāng)前項(xiàng)目獲得焦點(diǎn)時(shí)應(yīng)用快捷方式也很有幫助。這種方法可用于任何可聚焦的小部件,并通過擴(kuò)展該小部件并添加TypedShortcut
處理程序來管理。這很像添加鍵處理程序,除了傳入的值將是fyne.Shortcut
.
type myEntry struct {widget.Entry
}func (m *myEntry) TypedShortcut(s fyne.Shortcut) {if _, ok := s.(*desktop.CustomShortcut); !ok {m.Entry.TypedShortcut(s)return}log.Println("Shortcut typed:", s)
}
您可以看到如何實(shí)現(xiàn)TypedShortcut
處理程序。在此函數(shù)中,您應(yīng)該檢查快捷方式是否屬于之前使用的自定義類型。如果快捷方式是標(biāo)準(zhǔn)快捷方式,最好調(diào)用原始快捷方式處理程序(如果小部件有一個(gè))。完成這些檢查后,您可以將快捷方式與您正在處理的各種類型(如果有多個(gè))進(jìn)行比較。
2.7 使用[Preferences] API
存儲(chǔ)用戶配置和值是應(yīng)用程序開發(fā)人員的一項(xiàng)常見任務(wù),但跨多個(gè)平臺(tái)實(shí)現(xiàn)它可能是乏味且耗時(shí)的。為了使它更容易,Fyne 有一個(gè) API 用于在文件系統(tǒng)上以一種清晰易懂的方式存儲(chǔ)值,同時(shí)為您處理復(fù)雜的部分。
讓我們從 API 的設(shè)置開始。它是Preferences接口的一部分,其中存在 Bool、Float、Int 和 String 值的存儲(chǔ)和加載函數(shù)。它們每個(gè)都包含三個(gè)不同的功能,一個(gè)用于加載,一個(gè)用于加載備用值,最后一個(gè)用于存儲(chǔ)值。下面是 String 類型的三個(gè)函數(shù)及其行為的示例:
// String looks up a string value for the key
String(key string) string
// StringWithFallback looks up a string value and returns the given fallback if not found
StringWithFallback(key, fallback string) string
// SetString saves a string value for the given key
SetString(key string, value string)
這些函數(shù)可以通過創(chuàng)建的應(yīng)用程序變量和調(diào)用Preferences()
方法來訪問。請(qǐng)注意,必須創(chuàng)建具有唯一 ID 的應(yīng)用程序(通常像反向 url)。這意味著需要使用創(chuàng)建應(yīng)用程序app.NewWithID()
來擁有自己的位置來存儲(chǔ)值。它大致可以像下面的例子一樣使用:
a := app.NewWithID("com.example.tutorial.preferences")
[...]
a.Preferences().SetBool("Boolean", true)
number := a.Preferences().IntWithFallback("ApplicationLuckyNumber", 21)
expression := a.Preferences().String("RegularExpression")
[...]
為了展示這一點(diǎn),我們將構(gòu)建一個(gè)簡單的小應(yīng)用程序,它總是在設(shè)定的時(shí)間后關(guān)閉。此超時(shí)應(yīng)該是用戶可更改的,并在應(yīng)用程序的下一次啟動(dòng)時(shí)應(yīng)用。
讓我們首先創(chuàng)建一個(gè)名為的變量,該變量timeout
將用于以 的形式存儲(chǔ)時(shí)間time.Duration
。
var timeout time.Duration
然后我們可以創(chuàng)建一個(gè)選擇小部件,讓用戶從幾個(gè)預(yù)定義的字符串中選擇超時(shí),然后將超時(shí)乘以字符串相關(guān)的秒數(shù)。最后,該"AppTimeout"
鍵用于將字符串值設(shè)置為選定的值。
timeoutSelector := widget.NewSelect([]string{"10 seconds", "30 seconds", "1 minute"}, func(selected string) {switch selected {case "10 seconds":timeout = 10 * time.Secondcase "30 seconds":timeout = 30 * time.Secondcase "1 minute":timeout = time.Minute}a.Preferences().SetString("AppTimeout", selected)
})
現(xiàn)在我們想要獲取設(shè)置的值,如果不存在,我們想要一個(gè)后備,將超時(shí)設(shè)置為盡可能短的時(shí)間,以節(jié)省用戶等待時(shí)的時(shí)間。這可以通過將 的選定值設(shè)置timeoutSelector
為加載的值或在這種情況下的回退來完成。通過這樣做,選擇小部件內(nèi)的代碼將為該特定值運(yùn)行。
timeoutSelector.SetSelected(a.Preferences().StringWithFallback("AppTimeout", "10 seconds"))
最后一部分將只是擁有一個(gè)在單獨(dú)的?goroutine
?中啟動(dòng)的函數(shù),并告訴應(yīng)用程序在選定的超時(shí)后退出。
go func() {time.Sleep(timeout)a.Quit()
}()
最后,生成的代碼應(yīng)如下所示:
package mainimport ("time""fyne.io/fyne/v2/app""fyne.io/fyne/v2/widget"
)func main() {a := app.NewWithID("com.example.tutorial.preferences")w := a.NewWindow("Timeout")var timeout time.DurationtimeoutSelector := widget.NewSelect([]string{"10 seconds", "30 seconds", "1 minute"}, func(selected string) {switch selected {case "10 seconds":timeout = 10 * time.Secondcase "30 seconds":timeout = 30 * time.Secondcase "1 minute":timeout = time.Minute}a.Preferences().SetString("AppTimeout", selected)})timeoutSelector.SetSelected(a.Preferences().StringWithFallback("AppTimeout", "10 seconds"))go func() {time.Sleep(timeout)a.Quit()}()w.SetContent(timeoutSelector)w.ShowAndRun()
}
2.8 數(shù)據(jù)綁定
Fyne v2.0.0
中引入了數(shù)據(jù)綁定,使將許多小部件連接到將隨時(shí)間更新的數(shù)據(jù)源變得更加容易。該data/binding
包有許多有用的綁定,可以管理將在應(yīng)用程序中使用的大多數(shù)標(biāo)準(zhǔn)類型??梢允褂媒壎?API
(例如NewString
)來管理數(shù)據(jù)綁定,也可以將其連接到外部數(shù)據(jù)項(xiàng),例如 (BindInt(*int)
)。
支持綁定的小部件通常有一個(gè)…WithData
構(gòu)造函數(shù)來在創(chuàng)建小部件時(shí)設(shè)置綁定。您還可以調(diào)用Bind()
和Unbind()
管理現(xiàn)有小部件的數(shù)據(jù)。以下示例顯示了如何管理String
綁定到簡單Label
小部件的數(shù)據(jù)項(xiàng)。
package mainimport ("time""fyne.io/fyne/v2/app""fyne.io/fyne/v2/data/binding""fyne.io/fyne/v2/widget"
)func main() {a := app.New()w := a.NewWindow("Hello")str := binding.NewString()go func() {dots := "....."for i := 5; i >= 0; i-- {str.Set("Count down" + dots[:i])time.Sleep(time.Second)}str.Set("Blast off!")}()w.SetContent(widget.NewLabelWithData(str))w.ShowAndRun()
}
2.9 編譯選項(xiàng)
Fyne
?通常會(huì)通過選擇驅(qū)動(dòng)程序和配置來為目標(biāo)平臺(tái)適當(dāng)?shù)嘏渲媚膽?yīng)用程序。支持以下構(gòu)建標(biāo)簽,它們可以幫助您的開發(fā)。例如,如果您希望在臺(tái)式計(jì)算機(jī)上運(yùn)行時(shí)模擬移動(dòng)應(yīng)用程序,您可以使用以下命令:
go run -tags mobile main.go
標(biāo)簽 | 描述 |
---|---|
gles | 強(qiáng)制使用嵌入式 OpenGL (GLES) 而不是完整的 OpenGL。這通常由目標(biāo)設(shè)備控制,通常不需要。 |
hints | 顯示改進(jìn)或優(yōu)化的開發(fā)人員提示。當(dāng)您的應(yīng)用程序不遵循材料設(shè)計(jì)或其他建議時(shí),運(yùn)行hints 將記錄下來。 |
mobile | 此標(biāo)簽在模擬的移動(dòng)窗口中運(yùn)行應(yīng)用程序。當(dāng)您想在移動(dòng)平臺(tái)上預(yù)覽您的應(yīng)用程序而不編譯和安裝到設(shè)備時(shí)很有用。 |
no_native_menus | 此標(biāo)志專門用于 macOS,表示應(yīng)用程序不應(yīng)使用 macOS 原生菜單。相反,菜單將顯示在應(yīng)用程序窗口內(nèi)。對(duì)于在 macOS 上測(cè)試應(yīng)用程序以模擬 Windows 或 Linux 上的行為最有用。 |