Czy budując aplikację Windows Console w języku C #, można pisać na konsoli bez konieczności przedłużania bieżącej linii lub przejścia do nowej? Na przykład, jeśli chcę pokazać procent reprezentujący, jak blisko procesu jest zakończenie, chciałbym po prostu zaktualizować wartość w tym samym wierszu co kursor i nie musiałem umieszczać każdego procentu w nowym wierszu.
Czy można to zrobić za pomocą „standardowej” aplikacji na konsolę C #?
Odpowiedzi:
Jeśli drukujesz tylko
"\r"
na konsoli, kursor wraca na początek bieżącego wiersza, a następnie możesz go przepisać. To powinno załatwić sprawę:Zwróć uwagę na kilka spacji po numerze, aby upewnić się, że wszystko, co było wcześniej, zostało usunięte.
Zwróć też uwagę na użycie
Write()
zamiast,WriteLine()
ponieważ nie chcesz dodawać „\ n” na końcu wiersza.źródło
PadRight
(zapisywanie niepakowanego łańcucha lub długości, oczywiście, oczywiście).Możesz użyć,
Console.SetCursorPosition
aby ustawić pozycję kursora, a następnie zapisać w bieżącej pozycji.Oto przykład pokazujący prosty „spinner”:
Pamiętaj, że będziesz musiał nadpisać wszelkie istniejące dane wyjściowe nowymi danymi wyjściowymi lub spacjami.
Aktualizacja: Ponieważ krytykowano, że przykład przesuwa kursor tylko o jeden znak wstecz, dodam to dla wyjaśnienia: Używając
SetCursorPosition
możesz ustawić kursor w dowolnej pozycji w oknie konsoli.ustawi kursor na początku bieżącej linii (lub możesz użyć
Console.CursorLeft = 0
bezpośrednio).źródło
SetCursorPosition
(lubCursorLeft
) pozwala na większą elastyczność, np. Brak pisania na początku wiersza, poruszanie się w oknie itp., Więc jest to bardziej ogólne podejście, które można zastosować np. Do wyjścia niestandardowe paski postępu lub grafika ASCII.Do tej pory mamy trzy konkurujące ze sobą alternatywy:
Zawsze używałem
Console.CursorLeft = 0
, wariant trzeciej opcji, więc postanowiłem zrobić kilka testów. Oto kod, którego użyłem:Na moim komputerze otrzymuję następujące wyniki:
Dodatkowo
SetCursorPosition
spowodowało zauważalne migotanie, którego nie zaobserwowałem dla żadnej z alternatyw. Morał polega na tym, aby w miarę możliwości korzystać z odstępów lub zwrotów karetki , a dzięki za nauczenie mnie szybszego sposobu na to, SO!Aktualizacja : W komentarzach Joel sugeruje, że SetCursorPosition jest stały w odniesieniu do odległości przesuniętej, podczas gdy inne metody są liniowe. Dalsze testy potwierdzają, że tak jest, jednak stały czas i powolność są wciąż powolne. W moich testach pisanie długiego ciągu odstępów w konsoli jest szybsze niż SetCursorPosition, aż osiągnie około 60 znaków. Tak więc backspace jest szybszy do zastępowania części linii krótszych niż 60 znaków (lub mniej więcej) i nie miga, więc zamierzam podtrzymać moje wstępne poparcie \ b nad \ r i
SetCursorPosition
.źródło
Możesz użyć sekwencji ucieczki \ b (backspace), aby wykonać kopię zapasową określonej liczby znaków w bieżącym wierszu. To po prostu przesuwa bieżącą lokalizację, nie usuwa postaci.
Na przykład:
Tutaj linia jest linią procentową do zapisu w konsoli. Sztuką jest wygenerowanie poprawnej liczby znaków \ b dla poprzedniego wyniku.
Ma to tę zaletę nad \ r podejścia jest to, że jeśli działa, nawet jeśli nie jest wyjście procent na początku wiersza.
źródło
\r
jest używany w tych scenariuszach.\r
reprezentuje powrót karetki, co oznacza, że kursor wraca na początek linii.Dlatego Windows używa
\n\r
jako nowego znacznika linii.\n
przesuwa cię w dół linii i\r
wraca na początek linii.źródło
Po prostu musiałem grać z klasą divo
ConsoleSpinner
. Mój nie jest tak zwięzły, ale po prostu nie spodobało mi się, że użytkownicy tej klasy muszą napisać własnąwhile(true)
pętlę. Kręcę dla bardziej podobnych wrażeń:I zrozumiałem to za pomocą poniższego kodu. Ponieważ nie chcę, aby moja
Start()
metoda blokowała się, nie chcę, aby użytkownik musiał się martwić o napisaniewhile(spinFlag)
pętli podobnej do tej, i chcę pozwolić na wiele spinnerów w tym samym czasie, musiałem stworzyć osobny wątek do obsługi spinning. A to oznacza, że kod musi być o wiele bardziej skomplikowany.Nie zrobiłem też zbyt wielu wątków, więc możliwe jest (prawdopodobnie nawet), że zostawiłem tam subtelny błąd lub trzy. Ale wydaje się, że do tej pory działa całkiem dobrze:
źródło
Jawne użycie powrotu karetki (\ r) na początku wiersza zamiast (niejawnie lub jawnie) za pomocą nowej linii (\ n) na końcu powinno dać ci to, czego chcesz. Na przykład:
źródło
źródło
Z dokumentów konsoli w MSDN:
Więc - zrobiłem to:
Wtedy jestem w stanie sam kontrolować wyjście;
Kolejny sposób na dotarcie tam.
źródło
Działa to, jeśli chcesz, aby generowanie plików wyglądało fajnie.
I to jest metoda, którą otrzymałem z odpowiedzi poniżej i zmodyfikowałem
źródło
Oto kolejny: D
źródło
Jeśli chcesz zaktualizować jedną linię, ale informacja jest zbyt długa, aby wyświetlać się w jednej linii, może potrzebować kilku nowych linii. Napotkałem ten problem, a poniżej jest jeden ze sposobów rozwiązania tego problemu.
źródło
szukałem tego samego rozwiązania w vb.net i znalazłem to i jest świetne.
jednak jak @JohnOdom sugeruje lepszy sposób obsługi pustych miejsc, jeśli poprzedni jest większy niż bieżący.
Zrobiłem funkcję w vb.net i pomyślałem, że ktoś może uzyskać pomoc ..
oto mój kod:
źródło
Static intLastLength As Integer
.Szukałem tego, aby sprawdzić, czy napisane przeze mnie rozwiązanie można zoptymalizować pod kątem szybkości. Chciałem odliczać czas, a nie tylko aktualizować bieżącą linię. Oto, co wymyśliłem. Może być komuś przydatny
źródło
Zainspirowany @ E.Lahu Solution, realizacja postępu paska z procentem.
źródło
Oto moje zdanie na temat odpowiedzi Sosh i 0xA3. Może aktualizować konsolę za pomocą komunikatów użytkownika podczas aktualizacji tarczy i ma również wskaźnik upływu czasu.
użycie jest mniej więcej takie:
źródło
SetCursorPosition
Metoda działa w scenariuszu wielowątkowości, gdzie dwie inne metody nieźródło