4 pièce(s) jointe(s)
[Tutoriel] Afficher une progress bar dans une Console
Bonjour à tous,
C'est parfaitement inutile, donc absolument indispensable, et je tenais à le partager avec vous...
J'ai une application console dont je souhaitais connaitre l'avancement.
Grosso modo, je parcours une liste, fais un peu de traitement, et affiche ligne par ligne le résultat. Normal.
Mais comme je n'aime pas lire des choses du genre 164/1927, je me suis dit "mais dis donc! et pourquoi ne pas mettre une ProgressBar, gros ballot?"
Et comme je suis également une bille en matière d’application console, j'ai du fouiller un peu.
Donc voici mon résultat, certainement pas parfait, mais suffisant pour mon utilisation:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| static string ProgressBar(int progress)
{
// Convertit le progress en texte, et on fixe la longueur à 3 caractères avec un petit PadLeft
string textual = progress.ToString().PadLeft(3, ' ');
// Réutilisation de la même string pour afficher un texte représentant le progrès
textual = "Progress " + textual + "% ";
// Calcul de la taille disponible pour la progressbar
// Console.WindowWidth retourne le nombre de colonnes de la console.
// Il faut retrancher 1 car sinon le texte fait exactement la largeur de la console,
// ce qui entraînerait de facto un retour à la ligne (et ce serait moche, et l'effet
// progressbar disparaîtrait...)
int barsize = Console.WindowWidth - 1 - textual.Length;
// Initialisation d'un string builder d'une capacité égale à la taille de la progressbar
StringBuilder p = new StringBuilder(barsize);
// Une petit règle de trois pour caler le progrès sur la taille de la progressbar
progress = progress * barsize / 100;
// Et la fonction retourne une string avec des padding sur la gauche pour afficher le progress
// et un padding sur la droite pour donner une arrière plan à la progressbar
return textual + p.ToString().PadLeft(progress, (char)219).PadRight(barsize, (char)176);
} |
Notez que dans mon cas, les caractères que je souhaite utiliser nécessite d’accéder a la table Ascii étendue.
Il faut donc rajouter, ce que j'ai fait en première ligne de mon application:
Code:
1 2 3
| static void Main(string[] args)
{
Console.OutputEncoding = Encoding.GetEncoding(1252); |
Dans mon cas, je parcours une liste et souhaite toujours afficher le detail du traitement en cours, j'ai donc quelque chose du genre:
Code:
1 2 3 4 5 6 7 8 9
| foreach (var file in filelist)
{
// blabla code blabla
// Notez le \r en debut de ligne, pour replacer le chariot au bon endroit
Console.WriteLine("\rblabla ceci s'est passe sur l'item file");
// Calcul du progres en %
int i = 100 * (filelist.IndexOf(file) + 1) / filelist.Count;
Console.Write(ProgressBar(i));
} |
Ce qui me donne comme affichage une progress bar qui reste bien en bas de la fenêtre de la console:
Pièce jointe 355131
Si vous ne voulez pas afficher de détails, il est possible de faire par exemple:
Code:
1 2 3 4 5 6 7 8
| int MAX = 200;
Console.WriteLine("Please wait...");
for (int i = 1; i <= MAX; i++)
{
Thread.Sleep(100);
int p = 100 * i / MAX;
Console.Write("\r"+ProgressBar(p));
} |
Ce qui produira :
Pièce jointe 355139
Il est également possible de positionner cela tout en haut ou tout en bas en jouant avec Console.SetCursorPosition():
Pièce jointe 355144
Et si vous le voulez, j'ai aussi une progressbar du style Marquee (un bloc qui se déplace en avant/en arrière jusqu’à la fin de la tache):
Pièce jointe 355149
Enfin bref, ça m'a amusé de faire cela, donc je le partage avec vous.
@+