-
I'm looking to run the main loop in a cooperative way. That is, the UI runs until certain conditions are met, then it's paused while my application runs other non-UI code, then UI interaction is resumed, ...and so on. I was looking at the docs here but it looks like I tried the following which seems to work but the UI is not updating. For example, I see the cursor blinking in a text input field. But tabbing to buttons, they are not highlighted (don't appear as focused).
How can I retain full functionality of Terminal.Gui while being able to control the main loop execution? I'm using version 1.17.1 on Linux Mint. |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 5 replies
-
Can you describe a bit more the use case please. If you just want to show tui until asynchronous condition is met e.g. as a loading screen then the easiest way would be to have your worker thread invoke Application.RequestStop. This way you would Init, Run then Shutdown. Then later repeat (by re Init). You would need to handle the UI state though e.g. if you wanted to restore what was in TextFields etc Manually running the MainLoop would be quite difficult in v1 and is quite low level - so may not actually be required for your use case |
Beta Was this translation helpful? Give feedback.
-
My use case is a partially automated workflow where periodically user input is needed to make certain choices. Currently there is no worker thread, just one thread that does all the work. I guess the most straightforward approach is to Init, Run, Shutdown every time a user interaction is needed. I was hoping to avoid the performance cost of doing that and instead essentially keep the UI in an idle state until each time it's needed. |
Beta Was this translation helpful? Give feedback.
-
Here is example of running Terminal.Gui multiple times to illicit values from a user: using delme;
using Terminal.Gui;
Console.Write("Do some Work");
Task.Delay(TimeSpan.FromSeconds(3)).Wait();
Application.Init();
var w = new MyWin();
try
{
Application.Run(w);
}
finally
{
Application.Shutdown();
}
Console.Write("Do some more work on " + w.Result);
Task.Delay(TimeSpan.FromSeconds(3)).Wait();
Application.Init();
w = new MyWin();
try
{
Application.Run(w);
}
finally
{
Application.Shutdown();
}
Console.Write("Now do work on " + w.Result);
Task.Delay(TimeSpan.FromSeconds(3)).Wait();
class MyWin : Window
{
private readonly TextField _tf;
private readonly Button _btn;
public string? Result { get; set; }
public MyWin()
{
Width = Dim.Fill();
Height = Dim.Fill();
Add(_tf =new TextField()
{
Width = 5,
});
Add(_btn = new Button()
{
Y = 1,
Text = "ok",
IsDefault = true
});
_btn.Clicked += _btn_Clicked;
}
private void _btn_Clicked()
{
Result = _tf.Text.ToString();
Application.RequestStop();
}
} |
Beta Was this translation helpful? Give feedback.
-
If you want to use Terminal.Gui in a seperate thread from your main task e.g. to provide the user updates then it could look something like this (see below). Just make sure to use invoke so that any UI operation happens on the same thread you are running Terminal.Gui. Also don't have your main thread running Console writeline while terminal gui is running in another thread! using delme;
using Terminal.Gui;
// This task simulates your main script
var loadingTask = Task.Delay(TimeSpan.FromSeconds(3));
var semaphore = new SemaphoreSlim(0, 1); // Initialize a semaphore with 0 count.
// Run Terminal.Gui in a seperate thread
Task.Run(() =>
{
Application.Init();
var w = new MyWin();
try
{
Application.Run(w);
}
finally
{
Application.Shutdown();
semaphore.Release(); // Release the semaphore to signal shutdown completion.
}
});
// Finish your script - during this time Terminal.Gui will be showing the loading screen
loadingTask.Wait();
// Your work finished so you request to close the Terminal.Gui app
Application.MainLoop.Invoke(()=>Application.RequestStop());
// Wait for the semaphore to be released - that way we know shutdown finished.
semaphore.Wait();
// Now it is safe to use console again
Console.WriteLine("Loading complete, press enter key to exit");
Console.ReadLine();
class MyWin : Window
{
public MyWin()
{
Width = Dim.Fill();
Height = Dim.Fill();
Add(new Label("Loading..."));
}
} |
Beta Was this translation helpful? Give feedback.
-
I don’t know what the status of gui is nowadays, but this is a common feature to integrate apps that have different main loops. Older versions might have had it |
Beta Was this translation helpful? Give feedback.
If you want to use Terminal.Gui in a seperate thread from your main task e.g. to provide the user updates then it could look something like this (see below).
Just make sure to use invoke so that any UI operation happens on the same thread you are running Terminal.Gui.
Also don't have your main thread running Console writeline while terminal gui is running in another thread!