tview icon indicating copy to clipboard operation
tview copied to clipboard

Instability/Inconsistency of grid, Newbutton Output

Open WhipMeHarder opened this issue 1 year ago • 3 comments

The following experimental code is being reported - as seen below, which seems to produce component output instability and inconsistency. When used, there is no reliability that the movement or appearance of the selected button's blue background will follow the up and down input of the arrow keys from the keyboard. The top and first button is supposed to be selected. This happens intermittently, as does the selection of buttons when using the keyboard.

package main

import (
	"github.com/gdamore/tcell/v2"
	"github.com/rivo/tview"
	"fmt"
)

func main() {
    app := tview.NewApplication()

	// Create the buttons
	buttons := []string {"test 1", "test 2", "test 3", "test 4", "test 5"}
	grid := tview.NewGrid().SetColumns(45, 65, 45).SetRows(3, 3, 3, 3, 3, 3, 3, 3, 3, 3)

	// Add buttons to the grid
	for i, label := range buttons {
		grid.AddItem(tview.NewButton(label).SetBorder(true).SetTitle("[ "+label+" ]"), i, 0, 1, 1, 0, 0, false)
		
	}
	
	f := tview.NewInputField()
	f.SetBorder(true)
	f.SetTitle("Enter")

	g := tview.NewButton("Some text")	//.SetBorder(true)

	grid.AddItem(g, 5, 0, 1, 1, 0, 0, true)
	grid.AddItem(f, 6, 0, 1, 1, 0, 0, true)
	grid.AddItem(tview.NewTextView().SetText("Some small text").SetTextAlign(tview.AlignCenter), 7, 0, 1, 1, 0, 0, true)
	
	
	// Blue area button
	supr := tview.NewButton("test 1")
	supr.SetBackgroundColor(tcell.ColorBlue)
	supr.SetBorder(false)
	grid.AddItem(supr, 0, 0, 1, 1, 0, 0, true)

	currentRow := 0 // Track the current row of the blue area

	// Function to update the blue area position
	moveBlueArea := func(delta int) {
		newRow := currentRow + delta
		if newRow < 0 { newRow = 0 }
		if newRow >= len(buttons) { newRow = len(buttons) - 1}

		//if newRow >= 0 && newRow < len(buttons) {
			
			grid.RemoveItem(supr) // Remove from current position
			supr := tview.NewButton(buttons[newRow])
			grid.AddItem(supr, newRow, 0, 1, 1, 0, 0, true) // Add to new position
			
			currentRow = newRow
		//}
	}

	// Add the blue area initially
	grid.AddItem(supr, currentRow, 0, 1, 1, 0, 0, true)

	// Set up key handlers
	app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
		switch event.Key() {
			case tcell.KeyUp:
				moveBlueArea(-1) // Move up
			case tcell.KeyDown:
				moveBlueArea(1) // Move down
			case tcell.KeyTAB:
				f.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey { fmt.Println("Key pressed:", e); return e })
			case tcell.KeyEnter:
				app.Stop() // Exit on Enter key
		}
		return event
	})

	// Set up the layout and run the application
	if err := app.SetRoot(grid, true).SetFocus(grid).Run(); err != nil {
		panic(err)
	}
}

Various experiments have been done to:

  1. Rewrite or rebuild the entire display - even with or without the exception of the selected button.
  2. To add or change the background colour properties, of each selected button, including those which are not; and then back to point number one.

However, regardless of what methods are used, the output results always remain the same and haphazard. Is there a way to make the interactive output stable?

WhipMeHarder avatar Jan 13 '25 13:01 WhipMeHarder

The following line in your code

supr := tview.NewButton(buttons[newRow])

creates a new variable with the new button. But the scope of this variable extends only until the end of the function. So you're actually not updating your global supr variable with this. Thus, you end up always removing the same button that does not exist anymore after the first deletion. It has no effect.

There are Golang linters who can catch this mistake. You might want to look into them.

Other than that, I would also say, maybe try to avoid deleting and creating elements on the fly like that. Maybe what you really want is to call SetDisabled(). Or maybe just switch the focus using SetFocus(). Have a look at the Form implementation. It switches between different elements, similarly to what you're doing. Or maybe just use Form directly, then you don't have to worry about it.

rivo avatar Mar 29 '25 15:03 rivo

Ok. Thank you for giving such an insightful understanding. I will definitely look into this.

WhipMeHarder avatar May 08 '25 15:05 WhipMeHarder

Will close this for now. Feel to open a new issue if needed.

rivo avatar Aug 27 '25 19:08 rivo