Search code examples
gofyne

How to display text that can be copied on a fyne GUI?


On my fyne GUI, I want to display text that can be copied by the user. So far, I'm using a (multi-line) widget.Entry, see example below. Although that works, it seems inappropriate since "entry" implies user-input - which is not the case here.

If I use a widget.Label or canvas.Text, the characters can't be copied. So what's the best approach here?


Example:

package main

import (
    "time"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/data/binding"
    "fyne.io/fyne/v2/widget"
)

func main() {
    myApp := app.New()
    myWindow := myApp.NewWindow("demo")

    txtBound := binding.NewString()
    txtWid := widget.NewEntryWithData(txtBound)
    txtWid.MultiLine = true

    // we can disable the Entry field so the user can't modify the text:
    txtWid.Disabled()

    go func() {
        for {
            txtBound.Set(time.Now().Format("2006-01-02\n15:04:05\nMST -0700"))
            time.Sleep(time.Second)
        }
    }()

    content := container.NewBorder(nil, nil, nil, nil, txtWid)

    myWindow.SetContent(content)
    myWindow.Resize(fyne.NewSize(500, 300))

    myWindow.ShowAndRun()
}

The text in the Entry field can be selected and then copied using either mouse/right-click context menu or ctrl-c. On Windows 10, that would look like enter image description here


Solution

  • Labels are for display only, they afford no user interaction - this is something that web based apps have confused us about :). In Fyne apps we aim to have all user interaction hinted at, buttons and links are interactive, text is not. There are two possible approaches:

    1. put a “copy” button next to your label as has become common practice in many apps (for example password managers or YouTube)
    2. use a disabled Entry so the text can be interacted with but not edited.