rivo / tview

Terminal UI library with rich, interactive widgets — written in Golang
MIT License
11.17k stars 574 forks source link

How to use textview as terminal print #811

Closed zenithbb closed 1 year ago

zenithbb commented 1 year ago

I have a function runs by some steps, I want each step print something in the terminal use textview, but problem is: before the func return, the text not show as expect. below is the code, only third info is printed in the terminal how can I print all info



import (
    "fmt"
    "time"

    "github.com/rivo/tview"
)

var ttext = tview.NewTextView()
var tinput = tview.NewForm()

var app = tview.NewApplication()

func InitInput() *tview.Form {
    tinput.AddButton("Change Text", func() { DoSomething() })
    tinput.SetBorder(true)
    return tinput
}

func DoSomething() error {
    ttext.SetText(fmt.Sprintf("first %v", time.Now().String()))
    time.Sleep(5 * time.Second)
    ttext.SetText(fmt.Sprintf("second %v", time.Now().String()))
    time.Sleep(time.Second)
    ttext.SetText(fmt.Sprintf("third %v", time.Now().String()))
    return nil
}

func main() {
    InitInput()
    ttext.SetRegions(true).SetDynamicColors(true).SetWordWrap(true).SetBorder(true).SetTitle("Changed Text")
    flex := tview.NewFlex().AddItem(tinput, 0, 1, true).AddItem(ttext, 0, 1, false)
    if err := app.SetRoot(flex, true).EnableMouse(true).SetFocus(flex).Run(); err != nil {
        panic(err)
    }
}
rivo commented 1 year ago

SetText() doesn't cause the text view to be redrawn. It is only redrawn after DoSomething() returns, which happens after 6 seconds.

It's generally not a good idea to block everything. So here's an non-blocking example which queues the update to the text view in the intervals used in your code:

package main

import (
    "fmt"
    "time"

    "github.com/rivo/tview"
)

var ttext = tview.NewTextView()
var tinput = tview.NewForm()

var app = tview.NewApplication()

func InitInput() *tview.Form {
    tinput.AddButton("Change Text", func() { go DoSomething() })
    tinput.SetBorder(true)
    return tinput
}

func DoSomething() error {
    app.QueueUpdateDraw(func() { ttext.SetText(fmt.Sprintf("first %v", time.Now().String())) })
    time.Sleep(5 * time.Second)
    app.QueueUpdateDraw(func() { ttext.SetText(fmt.Sprintf("second %v", time.Now().String())) })
    time.Sleep(time.Second)
    app.QueueUpdateDraw(func() { ttext.SetText(fmt.Sprintf("third %v", time.Now().String())) })
    return nil
}

func main() {
    InitInput()
    ttext.SetRegions(true).SetDynamicColors(true).SetWordWrap(true).SetBorder(true).SetTitle("Changed Text")
    flex := tview.NewFlex().AddItem(tinput, 0, 1, true).AddItem(ttext, 0, 1, false)
    if err := app.SetRoot(flex, true).EnableMouse(true).SetFocus(flex).Run(); err != nil {
        panic(err)
    }
}