本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法

go代码展示为Go 1.16 及更高版本, idegoland2021.2

3. 绘图和动画

3.1 长方形(Rectangle)

canvas.RectangleFyne 中最简单的画布对象。它显示指定颜色的块。您还可以使用该FillColor字段设置颜色。
在此示例中,矩形填充了窗口,因为它是唯一的内容元素。

package main

import (
    "image/color"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Rectangle")

    rect := canvas.NewRectangle(color.White)
    w.SetContent(rect)

    w.Resize(fyne.NewSize(150, 100))
    w.ShowAndRun()
}

其他fyne.CanvaObject类型有更多配置,我们 接下来看看canvas.Text

3.2 文本(Text)

canvas.Text用于 Fyne 中的所有文本渲染。它是通过指定文本的文本和颜色来创建的。使用当前主题指定的默认字体呈现文本。
文本对象允许某些配置,例如Alignment andTextStyle字段。如这里的示例所示。要改用等宽字体,您可以指定fyne.TextStyle{Monospace: true}.

package main

import (
    "image/color"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Text")

    text := canvas.NewText("Text Object", color.White)
    text.Alignment = fyne.TextAlignTrailing
    text.TextStyle = fyne.TextStyle{Italic: true}
    w.SetContent(text)

    w.ShowAndRun()
}

FYNE_FONT可以通过指定环境变量来使用替代字体。使用它来设置.ttf要使用的文件,而不是 Fyne 工具包或当前主题中提供的文件。

3.3 线(Line)

canvas.Line对象从Position1(默认为顶部,左侧)到Position2(默认为底部,右侧)绘制一条线。您指定它的颜色,并可以改变笔划宽度,否则默认为1.
可以使用Position1orPosition2 字段或使用Move()and Resize()函数来操作行位置。例如,宽度为 0 的区域将显示一条垂直线,而高度为 0 的区域将是水平的。

package main

import (
    "image/color"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Line")

    line := canvas.NewLine(color.White)
    line.StrokeWidth = 5
    w.SetContent(line)

    w.Resize(fyne.NewSize(100, 100))
    w.ShowAndRun()
}

线条通常用于自定义布局或手动控制。与文本不同,它们没有自然(最小)的大小,但可以在复杂的布局中产生很好的效果。

3.4 圆(Circle)

canvas.Circle定义由指定颜色填充的圆形。您也可以设置a StrokeWidth,因此设置 a 不同StrokeColor,如本例所示。
圆圈将填充由调用Resize()或由它控制的布局指定的空间。由于示例将圆圈设置为窗口内容,它将在基本填充(由主题控制)内调整大小以填充窗口。

package main

import (
    "image/color"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Circle")

    circle := canvas.NewCircle(color.White)
    circle.StrokeColor = color.Gray{0x99}
    circle.StrokeWidth = 5
    w.SetContent(circle)

    w.Resize(fyne.NewSize(100, 100))
    w.ShowAndRun()
}

所有这些都是我们的驱动程序可以呈现的基本类型,无需额外信息。接下来我们将看看更复杂的类型,以[Image].

3.5 图片(Image)

canvas.Image代表 Fyne 中的可扩展图像资源。它可以从资源(如示例中所示)、图像文件、包含图像的 URI 链接、io.Reader获取 或 内存中Goimage.Image加载。
默认的图像填充模式canvas.ImageFillStretch将导致它填充指定的空间(通过Resize()或布局)。或者您可以使用canvas.ImageFillContain来确保保持纵横比并且图像在范围内。除此之外,您可以使用canvas.ImageFillOriginal(如此处示例中使用的那样)确保它的最小尺寸也等于原始图像尺寸。

package main

import (
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
    "fyne.io/fyne/v2/theme"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Image")

    image := canvas.NewImageFromResource(theme.FyneLogo())
    // image := canvas.NewImageFromURI(uri)
    // image := canvas.NewImageFromImage(src)
    // image := canvas.NewImageFromReader(reader, name)
    // image := canvas.NewImageFromFile(fileName)
    image.FillMode = canvas.ImageFillOriginal
    w.SetContent(image)

    w.ShowAndRun()
}

图像可以基于位图(如 PNG 和 JPEG)或基于矢量(如 SVG)。使用原始图像尺寸时要小心,因为它们在不同的用户界面比例下可能不会完全符合预期。由于 Fyne 允许整个用户界面缩放 25px 的图像文件,因此可能与 25 高度的 fyne 对象的高度不同。

3.6 栅格(Raster)

canvas.Raster就像一个图像,但为屏幕上的每个像素绘制了一个点。这意味着随着用户界面的缩放或图像大小的调整,将需要更多的像素来填充空间。为此,我们使用Generator本示例中所示的函数 - 它将用于返回每个像素的颜色。
生成器函数可以是基于像素的(如本例中我们为每个像素生成新的随机颜色)或基于完整图像。生成完整的图像(使用canvas.NewRaster())更有效,但有时直接控制像素更方便。

package main

import (
    "image/color"
    "math/rand"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Raster")

    raster := canvas.NewRasterWithPixels(
        func(_, _, w, h int) color.Color {
            return color.RGBA{uint8(rand.Intn(255)),
                uint8(rand.Intn(255)),
                uint8(rand.Intn(255)), 0xff}
        })
    // raster := canvas.NewRasterFromImage()
    w.SetContent(raster)
    w.Resize(fyne.NewSize(200, 200))
    w.ShowAndRun()
}

如果您的像素数据存储在图像中,您可以通过NewRasterFromImage()加载图像以在屏幕上完美显示像素的功能加载它。

3.7 渐变(动画)

最后一个画布原始类型是渐变,可用作 canvas.LinearGradient并且canvas.RadialGradient用于以各种图案从一种颜色绘制到另一种颜色的渐变。您可以使用NewHorizontalGradient()NewVerticalGradient()NewRadialGradient()创建渐变。
要创建渐变,您需要开始和结束颜色 - 中间的每种颜色都由画布计算。在这个例子中,我们color.Transparent用来展示渐变(或任何其他类型)如何使用 alpha值对后面的内容保持半透明。

package main

import (
    "image/color"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
)

func main() {
    myApp := app.New()
    w := myApp.NewWindow("Gradient")

    gradient := canvas.NewHorizontalGradient(color.White, color.Transparent)
    //gradient := canvas.NewRadialGradient(color.White, color.Transparent)
    w.SetContent(gradient)

    w.Resize(fyne.NewSize(100, 100))
    w.ShowAndRun()
}

3.8 动画(Animation)

Fyne 包含一个动画框架,可让您随着时间的推移将画布属性从一个值平滑过渡到另一个值。动画可以包含任何代码,这意味着可以管理任何类型的对象属性,但是有大小、位置和颜色的内置动画。
动画通常是使用 canvas包的内置助手创建的,例如NewSizeAnimation, 并调用Start()创建的动画。您可以将动画设置为重复或自动反转,如下所示。
让我们首先看一个逐渐改变Rectangle 的填充颜色的彩色动画。在下面的代码示例中,我们将一个矩形设置为窗口的内容,就像我们在前面的代码示例中所做的那样。最大的不同是我们在显示窗口之前开始的动画。动画是使用NewColorRGBAAnimation它将颜色通道从定义的 red状态转换到 的blue,它需要 2 秒(指定的持续时间)来完成。

package main

import (
    "image/color"
    "time"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/canvas"
    "fyne.io/fyne/v2/container"
)

func main() {
    a := app.New()
    w := a.NewWindow("Hello")

    obj := canvas.NewRectangle(color.Black)
    obj.Resize(fyne.NewSize(50, 50))
    w.SetContent(container.NewWithoutLayout(obj))

    red := color.NRGBA{R:0xff, A:0xff}
    blue := color.NRGBA{B:0xff, A:0xff}
    canvas.NewColorRGBAAnimation(red, blue, time.Second*2, func(c color.Color) {
        obj.FillColor = c
        canvas.Refresh(obj)
    }).Start()

    w.Resize(fyne.NewSize(200, 200))
    w.SetPadded(false)
    w.ShowAndRun()
}

也可以同时为多个属性设置动画。如果您仔细观察,您会发现我们将矩形添加到没有布局的容器中——这意味着我们可以手动移动或调整对象的大小。让我们添加一个新的位置动画,它将在Rectangle整个窗口中移动,并自动反转。

move := canvas.NewPositionAnimation(fyne.NewPos(0, 0), fyne.NewPos(200, 0), time.Second, obj.Move)
move.AutoReverse = true
move.Start()

因为CanvasObjectMove()函数需要一个fyne.Position参数,位置动画回调也是如此,我们可以简单地传递方法名称而不是创建一个新函数如果你在第一个动画下面添加上面的代码,你会看到对象在窗口中移动在变色的同时!