编辑
2025-09-17
C#
00

目录

Terminal.Gui简介
主要特性:
应用场景
3. 入门指南
安装
基本结构
实际应用示例
示例1:任务管理器
示例2:简单的文本编辑器
高级特性
响应式布局
自定义控件
异步操作
最佳实践
结论

Terminal.Gui这个强大的工具包。Terminal.Gui是一个用于.NET平台的跨平台终端UI工具包,它使开发者能够创建功能丰富、交互性强的控制台应用程序。

Terminal.Gui简介

Terminal.Gui是一个开源项目,它为.NET开发者提供了一套全面的工具,用于构建复杂的终端用户界面。它支持Windows、macOS和Linux等多个平台,使得开发跨平台控制台应用变得简单而高效。

主要特性:

  • 跨平台兼容性
  • 丰富的UI控件
  • 事件驱动编程模型
  • 灵活的布局系统
  • 键盘和鼠标输入支持
  • 自定义控件能力

应用场景

Terminal.Gui适用于多种应用场景,特别是那些需要在终端环境中提供丰富用户界面的场合:

  1. 系统管理工具:如服务器监控、日志分析器等。
  2. 开发者工具:CLI版本的IDE、代码生成器、构建工具等。
  3. 数据可视化应用:在终端中展示图表、统计信息等。
  4. 文本编辑器:类似于Vim或Nano的终端编辑器。
  5. 数据库管理工具:命令行数据库客户端。
  6. 网络工具:FTP客户端、SSH客户端等。
  7. 游戏:文字冒险游戏或其他基于文本的游戏。
  8. 配置工具:用于复杂系统的交互式配置工具。

3. 入门指南

安装

首先,在你的.NET项目中安装Terminal.Gui NuGet包:

C#
dotnet add package Terminal.Gui

image.png

基本结构

一个典型的Terminal.Gui应用程序结构如下:

C#
using Terminal.Gui; class Program { static void Main(string[] args) { Application.Init(); // 创建主窗口 var win = new Window("My App") { X = 0, Y = 1, // 留出空间给顶部菜单 Width = Dim.Fill(), Height = Dim.Fill() }; // 添加控件到窗口 Application.Top.Add(win); Application.Run(); } }

image.png

实际应用示例

示例1:任务管理器

这个例子展示了如何创建一个简单的任务管理器应用:

C#
using Terminal.Gui; using System.Collections.Generic; namespace ConsoleApp2 { internal class Program { static void Main(string[] args) { Application.Run<TaskManagerApp>(); } } class Task { public string Name { get; set; } public bool IsCompleted { get; set; } public override string ToString() => IsCompleted ? "[X] " + Name : "[ ] " + Name; } class TaskManagerApp : Window { private readonly List<Task> tasks = new List<Task>(); private readonly ListView taskListView; private readonly TextField newTaskField; public TaskManagerApp() { Title = "Task Manager"; // Create task list view taskListView = new ListView() { X = 0, Y = 0, Width = Dim.Fill(), Height = Dim.Fill() - 3 }; // Create a label for the new task input var taskLabel = new Label("Enter New Task:") { X = 0, Y = Pos.Bottom(taskListView), AutoSize = true }; // Create new task input field newTaskField = new TextField("") { X = Pos.Right(taskLabel) + 1, Y = Pos.Bottom(taskListView), Width = Dim.Fill() - 20 // Simple fixed adjustment for demonstration }; // Create add button var addButton = new Button("Add") { X = Pos.Right(newTaskField) + 1, Y = Pos.Top(newTaskField), Width = 9 }; addButton.Clicked += () => { if (!string.IsNullOrWhiteSpace(newTaskField.Text.ToString())) { tasks.Add(new Task { Name = newTaskField.Text.ToString() }); taskListView.SetSource(tasks); newTaskField.Text = string.Empty; } newTaskField.SetFocus(); // Return focus to the input field }; // Create complete button var completeButton = new Button("Complete") { X = Pos.Center(), Y = Pos.Bottom(newTaskField) + 1, Width = 12 }; completeButton.Clicked += () => { if (taskListView.SelectedItem >= 0 && taskListView.SelectedItem < tasks.Count) { tasks[taskListView.SelectedItem].IsCompleted = true; taskListView.SetSource(tasks); } }; Add(taskListView, taskLabel, newTaskField, addButton, completeButton); taskListView.SetSource(tasks); newTaskField.SetFocus(); // Set initial focus } } }

image.png

示例2:简单的文本编辑器

这个例子展示了如何创建一个基本的文本编辑器:

C#
using Terminal.Gui; using System; using System.IO; using System.Collections.Generic; namespace ConsoleApp2 { internal class Program { static void Main(string[] args) { Application.Init(); var top = Application.Top; var win = new TextEditorApp(); top.Add(win); Application.Run(); } } class TextEditorApp : Window { private TextView textView; private StatusBar statusBar; private string currentFilePath; public TextEditorApp() { Title = "Simple Text Editor"; // Create menu var menu = new MenuBar(new MenuBarItem[] { new MenuBarItem ("_File", new MenuItem [] { new MenuItem ("_New", "", () => NewFile()), new MenuItem ("_Open", "", () => OpenFile()), new MenuItem ("_Save", "", () => SaveFile()), new MenuItem ("_Quit", "", () => Application.RequestStop()) }), }); // Create text view textView = new TextView() { X = 0, Y = 1, Width = Dim.Fill(), Height = Dim.Fill() - 1 }; // Create status bar statusBar = new StatusBar(new StatusItem[] { new StatusItem(Key.F2, "~F2~ Open", () => OpenFile()), new StatusItem(Key.F3, "~F3~ Save", () => SaveFile()), new StatusItem(Key.F9, "~F9~ Quit", () => Application.RequestStop()) }); Add(menu, textView, statusBar); } private void NewFile() { textView.Text = ""; currentFilePath = null; } private void OpenFile() { var dialog = new OpenDialog("Open File", "Open a text file"); Application.Run(dialog); if (!dialog.Canceled && !string.IsNullOrEmpty(dialog.FilePath.ToString())) { currentFilePath = dialog.FilePath.ToString(); textView.Text = File.ReadAllText(currentFilePath); } } private void SaveFile() { if (string.IsNullOrEmpty(currentFilePath)) { var dialog = new SaveDialog("Save File", "Save your text file"); Application.Run(dialog); if (!dialog.Canceled && !string.IsNullOrEmpty(dialog.FilePath.ToString())) { currentFilePath = dialog.FilePath.ToString(); } else { return; } } File.WriteAllText(currentFilePath, textView.Text.ToString()); MessageBox.Query("Save Successful", "File has been saved", "OK"); } } }

image.png

高级特性

响应式布局

Terminal.Gui提供了强大的布局系统,允许创建响应终端大小变化的界面:

C#
using Terminal.Gui; namespace ConsoleApp2 { class Program { static void Main(string[] args) { // 初始化应用程序 Application.Init(); // 创建主窗口 var win = new Window("My Application") // 窗口标题为“My Application” { X = 0, Y = 1, // 为将来的菜单预留空间 Width = Dim.Fill(), // 窗口宽度填满屏幕 Height = Dim.Fill() // 窗口高度填满屏幕 }; // 创建一个居中的标签 var responsiveLabel = new Label("Hello World!") // 标签内容为“Hello World!” { X = Pos.Center(), // 水平居中 Y = Pos.Center() // 垂直居中 // 不设置 Width,以正确实现居中 }; // 将标签添加到窗口 win.Add(responsiveLabel); // 将窗口添加到顶层容器中 Application.Top.Add(win); // 运行应用程序 Application.Run(); } } }

自定义控件

你可以通过继承View类来创建自定义控件:

C#
using System; using System.Threading; using Terminal.Gui; namespace ConsoleApp2 { class Program { static void Main(string[] args) { // 初始化应用程序 Application.Init(); // 创建主窗口 var win = new Window("Custom Progress Bar") { X = 0, Y = 0, Width = Dim.Fill(), Height = Dim.Fill() }; // 创建自定义进度条 var progressBar = new CustomProgressBar() { X = Pos.Center(), Y = Pos.Center(), Width = 50, Height = 1 }; win.Add(progressBar); Application.Top.Add(win); // 启动一个新线程来更新进度条 new Thread(() => { for (int i = 0; i <= 50; i++) { Thread.Sleep(100); // 每100毫秒更新一次 Application.MainLoop.Invoke(() => { progressBar.Value = i; progressBar.SetNeedsDisplay(); // 标记需要重绘 }); } }).Start(); // 运行应用程序 Application.Run(); } } public class CustomProgressBar : View { public int Value { get; set; } = 0; public CustomProgressBar() { CanFocus = false; } public override void Redraw(Rect bounds) { Driver.SetAttribute(ColorScheme.Focus); for (int i = 0; i < bounds.Width; i++) { Move(i, 0); Driver.AddRune(i < Value ? '█' : '░'); } } } }

image.png

异步操作

Terminal.Gui支持异步操作,这在处理耗时任务时非常有用:

C#
using System; using System.Threading.Tasks; using Terminal.Gui; namespace ConsoleApp2 { class Program { static void Main(string[] args) { // 初始化应用程序 Application.Init(); // 创建主窗口 var win = new Window("Progress Bar") { X = 0, Y = 0, Width = Dim.Fill(), // 窗口填满整个宽度 Height = Dim.Fill() // 窗口填满整个高度 }; // 将窗口添加到应用程序顶层 Application.Top.Add(win); // 在应用程序启动时运行异步任务来更新进度条 UpdateProgressBar(win); // 运行应用程序 Application.Run(); } // 更新进度条的异步方法 static async void UpdateProgressBar(Window win) { // 创建进度条并设定其位置和宽度 var progress = new ProgressBar() { X = Pos.Center(), // 水平居中 Y = Pos.Center(), // 垂直居中 Width = Dim.Percent(75) // 进度条宽度占窗口的75% }; // 将进度条添加到窗口 win.Add(progress); for (int i = 0; i <= 100; i++) { // 确保UI更新在主线程中完成 Application.MainLoop.Invoke(() => { progress.Fraction = i / 100f; // 更新进度条的进度 }); await Task.Delay(50); // 模拟工作通过延迟50毫秒 } // 进度完成后从窗口中移除进度条 Application.MainLoop.Invoke(() => { win.Remove(progress); }); } } }

image.png

最佳实践

  1. 模块化设计:将UI逻辑分离到不同的类中,保持代码整洁。
  2. 使用事件驱动模型:充分利用Terminal.Gui的事件系统。
  3. 注意性能:对于大量数据,考虑使用虚拟化列表。
  4. 错误处理:实现全局异常处理,确保应用程序的稳定性。
  5. 主题定制:使用ColorScheme来创建一致的视觉风格。
  6. 快捷键支持:为常用操作添加快捷键,提高用户效率。

结论

Terminal.Gui为.NET开发者提供了一个强大的工具,用于创建复杂、交互性强的控制台应用程序。它结合了传统命令行界面的轻量级特性和现代GUI应用的交互性,为各种应用场景提供了理想的解决方案。

无论是构建开发工具、系统管理应用还是创建独特的用户界面,Terminal.Gui都能满足各种需求。通过本文介绍的特性和示例,相信您已经对Terminal.Gui有了深入的了解,并能够开始使用它来创建您自己的强大控制台应用程序。

随着.NET生态系统的不断发展,Terminal.Gui无疑将在控制台应用程序开发中扮演越来越重要的角色。希望本文能够激发您的创意,帮助您在下一个项目中充分利用Terminal.Gui的潜力。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!