[GH-ISSUE #909] Windows Non-Stop Flickering when calling function QueueUpdateDraw() inside SetAfterDrawFunc() #661

Closed
opened 2026-03-04 01:06:52 +03:00 by kerem · 2 comments
Owner

Originally created by @Vinrithi on GitHub (Nov 1, 2023).
Original GitHub issue: https://github.com/rivo/tview/issues/909

Hello. I would like to appreciate you for the wonderful work you've done in providing this library. I had started using it in 2022 in a small project and noticed there were new updates. However, there seems to be a bug which causes the application to flicker non-stop in Windows in the latest release v0.0.0-20231031172508-2dfe06011790. I updated from v0.0.0-20220812085834-0e6b21a48e96. I've created a sample code below to showcase this.
screen-capture.webm

The above video shows what is happening in the UI and this is the code:

func main() {

	app := tview.NewApplication()
	form := tview.NewForm().
		AddDropDown("Title", []string{"Mr.", "Ms.", "Mrs.", "Dr.", "Prof."}, 0, nil).
		AddInputField("First name", "", 20, nil, nil).
		AddInputField("Last name", "", 20, nil, nil).
		AddCheckbox("Age 18+", false, nil).
		AddPasswordField("Password", "", 10, '*', nil).
		AddButton("Save", nil).
		AddButton("Quit", func() {
			app.Stop()
		})
	form.SetBorder(true).SetTitle("Enter some data").SetTitleAlign(tview.AlignLeft)

	app.SetAfterDrawFunc(func(screen tcell.Screen) {
		go func() {
			app.QueueUpdateDraw(func() {
			
			})
		}()
	})

	if err := app.SetRoot(form, true).EnableMouse(true).Run(); err != nil {
		panic(err)
	}
}

This only happens when I call

app.SetAfterDrawFunc(func(screen tcell.Screen) {
		go func() {
			app.QueueUpdateDraw(func() {
			
			})
		}()
	})

and it only happens in Windows. I've tried in Command Prompt and Powershell latest 7.3.9 and the output is the same. In Linux there is no issue whatsoever. The application is running as expected. In my actual project, Before the latest updates, the flickering was not happening:

go.mod before

go 1.19

require (
	github.com/briandowns/spinner v1.23.0
	github.com/epiclabs-io/winman v0.0.0-20220901164457-3d8c4b3ae090
	github.com/gdamore/tcell/v2 v2.6.0
	github.com/rivo/tview v0.0.0-20220812085834-0e6b21a48e96
	golang.design/x/clipboard v0.7.0
)

require (
	github.com/fatih/color v1.15.0 // indirect
	github.com/gdamore/encoding v1.0.0 // indirect
	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
	github.com/mattn/go-colorable v0.1.13 // indirect
	github.com/mattn/go-isatty v0.0.17 // indirect
	github.com/mattn/go-runewidth v0.0.14 // indirect
	github.com/rivo/uniseg v0.4.3 // indirect
	golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
	golang.org/x/image v0.6.0 // indirect
	golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c // indirect
	golang.org/x/sys v0.6.0 // indirect
	golang.org/x/term v0.5.0 // indirect
	golang.org/x/text v0.8.0 // indirect
)

go.mod updated

go 1.19

require (
	github.com/briandowns/spinner v1.23.0
	github.com/epiclabs-io/winman v0.0.0-20220901164457-3d8c4b3ae090
	github.com/gdamore/tcell/v2 v2.6.0
	github.com/rivo/tview v0.0.0-20231031172508-2dfe06011790
	golang.design/x/clipboard v0.7.0
)

require (
	github.com/fatih/color v1.15.0 // indirect
	github.com/gdamore/encoding v1.0.0 // indirect
	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
	github.com/mattn/go-colorable v0.1.13 // indirect
	github.com/mattn/go-isatty v0.0.20 // indirect
	github.com/mattn/go-runewidth v0.0.15 // indirect
	github.com/rivo/uniseg v0.4.4 // indirect
	golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
	golang.org/x/exp/shiny v0.0.0-20231006140011-7918f672742d // indirect
	golang.org/x/image v0.13.0 // indirect
	golang.org/x/mobile v0.0.0-20231006135142-2b44d11868fe // indirect
	golang.org/x/sys v0.13.0 // indirect
	golang.org/x/term v0.13.0 // indirect
	golang.org/x/text v0.13.0 // indirect
)

In my actual project, I need to call the function to redraw the UI for smooth operations. Otherwise, I'm forced to move the terminal a bit for it to refresh UI as shown in the videos below (I have used Ubuntu Terminal since it has no flickering):

screen-capture-without-queue-update-draw.webm
screen-capture-with-queue-update-draw.webm

And here's the project on Windows:

windows-flickering.webm

I have no problem running my application in Ubuntu, but I really wanted it to work in Windows as well since that's where it's being used the most.
Kindly have a look and advise.

Originally created by @Vinrithi on GitHub (Nov 1, 2023). Original GitHub issue: https://github.com/rivo/tview/issues/909 Hello. I would like to appreciate you for the wonderful work you've done in providing this library. I had started using it in 2022 in a small project and noticed there were new updates. However, there seems to be a bug which causes the application to flicker non-stop in Windows in the latest release **v0.0.0-20231031172508-2dfe06011790**. I updated from **v0.0.0-20220812085834-0e6b21a48e96**. I've created a sample code below to showcase this. [screen-capture.webm](https://github.com/rivo/tview/assets/22772526/73a1e9b1-b290-4414-8aa2-31b1953536b2) The above video shows what is happening in the UI and this is the code: ```go func main() { app := tview.NewApplication() form := tview.NewForm(). AddDropDown("Title", []string{"Mr.", "Ms.", "Mrs.", "Dr.", "Prof."}, 0, nil). AddInputField("First name", "", 20, nil, nil). AddInputField("Last name", "", 20, nil, nil). AddCheckbox("Age 18+", false, nil). AddPasswordField("Password", "", 10, '*', nil). AddButton("Save", nil). AddButton("Quit", func() { app.Stop() }) form.SetBorder(true).SetTitle("Enter some data").SetTitleAlign(tview.AlignLeft) app.SetAfterDrawFunc(func(screen tcell.Screen) { go func() { app.QueueUpdateDraw(func() { }) }() }) if err := app.SetRoot(form, true).EnableMouse(true).Run(); err != nil { panic(err) } } ``` This only happens when I call ```go app.SetAfterDrawFunc(func(screen tcell.Screen) { go func() { app.QueueUpdateDraw(func() { }) }() }) ``` and it only happens in Windows. I've tried in Command Prompt and Powershell latest 7.3.9 and the output is the same. In Linux there is no issue whatsoever. The application is running as expected. In my actual project, Before the latest updates, the flickering was not happening: **go.mod before** ```go go 1.19 require ( github.com/briandowns/spinner v1.23.0 github.com/epiclabs-io/winman v0.0.0-20220901164457-3d8c4b3ae090 github.com/gdamore/tcell/v2 v2.6.0 github.com/rivo/tview v0.0.0-20220812085834-0e6b21a48e96 golang.design/x/clipboard v0.7.0 ) require ( github.com/fatih/color v1.15.0 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/rivo/uniseg v0.4.3 // indirect golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect golang.org/x/image v0.6.0 // indirect golang.org/x/mobile v0.0.0-20230301163155-e0f57694e12c // indirect golang.org/x/sys v0.6.0 // indirect golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.8.0 // indirect ) ``` **go.mod updated** ```go go 1.19 require ( github.com/briandowns/spinner v1.23.0 github.com/epiclabs-io/winman v0.0.0-20220901164457-3d8c4b3ae090 github.com/gdamore/tcell/v2 v2.6.0 github.com/rivo/tview v0.0.0-20231031172508-2dfe06011790 golang.design/x/clipboard v0.7.0 ) require ( github.com/fatih/color v1.15.0 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/rivo/uniseg v0.4.4 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/exp/shiny v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/image v0.13.0 // indirect golang.org/x/mobile v0.0.0-20231006135142-2b44d11868fe // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect ) ``` In my actual project, I need to call the function to redraw the UI for smooth operations. Otherwise, I'm forced to move the terminal a bit for it to refresh UI as shown in the videos below (I have used Ubuntu Terminal since it has no flickering): [screen-capture-without-queue-update-draw.webm](https://github.com/rivo/tview/assets/22772526/fc38c464-dac7-4959-9ff0-6947f14dba2a) [screen-capture-with-queue-update-draw.webm](https://github.com/rivo/tview/assets/22772526/a9b260bb-cd13-4ed2-91b4-b34d92fae02f) And here's the project on Windows: [windows-flickering.webm](https://github.com/rivo/tview/assets/22772526/69a2bc1d-457a-4ec0-9f1e-a63a916b6611) I have no problem running my application in Ubuntu, but I really wanted it to work in Windows as well since that's where it's being used the most. Kindly have a look and advise.
kerem closed this issue 2026-03-04 01:06:52 +03:00
Author
Owner

@rivo commented on GitHub (Nov 4, 2023):

It is necessary to clear the screen before each call to Draw() (see https://github.com/rivo/tview/issues/899#issuecomment-1777112223). This should generally not be a problem. But in your particular example, you are creating an endless loop of calls to Draw(): In your SetAfterDrawFunc() callback, you're scheduling another Draw() invocation. And then again and again.

I'm not sure why you are doing that, but even if there was no flickering, it would keep the CPU unnecessarily busy. I'm guessing that there is a slight difference in terminals on Windows and on other OSes but it happens on non-Windows OSes too, it's just not visible.

Maybe you want to clarify why you create an endless Draw() cycle?

<!-- gh-comment-id:1793433713 --> @rivo commented on GitHub (Nov 4, 2023): It is necessary to clear the screen before each call to `Draw()` (see https://github.com/rivo/tview/issues/899#issuecomment-1777112223). This should generally not be a problem. But in your particular example, you are creating an endless loop of calls to `Draw()`: In your `SetAfterDrawFunc()` callback, you're scheduling another `Draw()` invocation. And then again and again. I'm not sure why you are doing that, but even if there was no flickering, it would keep the CPU unnecessarily busy. I'm guessing that there is a slight difference in terminals on Windows and on other OSes but it happens on non-Windows OSes too, it's just not visible. Maybe you want to clarify why you create an endless `Draw()` cycle?
Author
Owner

@Vinrithi commented on GitHub (Nov 4, 2023):

Thanks for the clarification on what is happening. I've relooked at my code and I've seen I might have been messing up by calling

app.SetAfterDrawFunc(func(screen tcell.Screen) {
		go func() {
			app.QueueUpdateDraw(func() {
			
			})
		}()
	})

I had some windows like alerts and progress bars made using the winman library, and was having difficulties showing and hiding them, until I encountered the function above. It was solving the issues I had, but didn't know the repercussions in things like CPU usage. I've reimplemented using Draw() and the program is running well on both Windows and Linux with minimal CPU usage.

<!-- gh-comment-id:1793568128 --> @Vinrithi commented on GitHub (Nov 4, 2023): Thanks for the clarification on what is happening. I've relooked at my code and I've seen I might have been messing up by calling ```go app.SetAfterDrawFunc(func(screen tcell.Screen) { go func() { app.QueueUpdateDraw(func() { }) }() }) ``` I had some windows like alerts and progress bars made using the winman library, and was having difficulties showing and hiding them, until I encountered the function above. It was solving the issues I had, but didn't know the repercussions in things like CPU usage. I've reimplemented using Draw() and the program is running well on both Windows and Linux with minimal CPU usage.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#661
No description provided.