Laut dem offiziellen Dokument
Die curses-Bibliothek bietet terminalunabhängige Bildschirmzeichnung und Tastaturverarbeitung für textbasierte Terminals (Terminals) wie VT100s, Linux-Konsolen und Emulationsterminals, die von verschiedenen Programmen bereitgestellt werden. Das Terminal unterstützt verschiedene Steuercodes zum Ausführen allgemeiner Vorgänge wie Bewegen des Cursors, Scrollen des Bildschirms und Löschen des Bereichs. Verschiedene Arten von Terminals können sehr unterschiedliche Steuercodes verwenden und haben oft eine besondere Angewohnheit.
Dies kann nützlich sein, wenn Sie eine einfache GUI erstellen oder mit Daten auf einem Server arbeiten möchten, auf den nur mit ssh zugegriffen werden kann. Sie können auch den Inhalt von CSV und DB anzeigen.
Angenommen, Sie haben die folgende CSV-Datei.
ID | Prefecture | Capital | Population | Area | Density |
---|---|---|---|---|---|
1 | Aichi | Nagoya | 70,43,235 | 5,153.81 | 1,366 |
2 | Akita | Akita | 11,89,215 | 11,612.11 | 102 |
3 | Aomori | Aomori | 14,75,635 | 9,606.26 | 154 |
... | ... | ... | ... | ... | ... |
45 | Yamagata | Yamagata | 12,44,040 | 9,323.34 | 133 |
46 | Yamaguchi | Yamaguchi | 15,28,107 | 6,110.76 | 250 |
47 | Yamanashi | Kofu | 8,88,170 | 4,465.37 | 199 |
Ich möchte eine GUI erstellen, die den Inhalt des Terminals anzeigen und die zu verarbeitende Präfektur auswählen kann.
main.py
# -*- coding: utf-8 -*-
import curses
import csv
from math import ceil
ROWS_PER_PAGE = 20
ENTER = ord( "\n" )
ESC = 27
DOWN = curses.KEY_DOWN
UP = curses.KEY_UP
class UI():
def __init__(self, header, rows):
super().__init__()
self.header = header
self.rows = rows
#Initialisieren
self.screen = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
self.screen.keypad(1)
#Farbeinstellungen
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_CYAN)
self.highlight_text = curses.color_pair(1) #Verwenden Sie die Paar-ID in der obigen Zeile
self.normal_text = curses.A_NORMAL
self.screen.border(0)
curses.curs_set(0)
self.rows_per_page = ROWS_PER_PAGE
self.total_rows = len(self.rows)
#Notieren Sie die Breite jeder Spalte
self.widths = []
#Randzeichnung
self.tavnit = '|'
self.separator = '+'
for index, title in enumerate(self.header):
#Machen Sie den Spaltentitel und den längsten Wert jeder Zeile zur Breite der Spalte
max_col_length = max([len(row[index]) for row in self.rows])
max_col_length = max(max_col_length, len(title))
self.widths.append(max_col_length)
#Rahmeneinstellungen
for w in self.widths:
#Es sieht aus wie das:
# | %-2s | %-10s | %-10s | %-11s | %-9s | %-7s |
self.tavnit += " %-"+"%ss |" % (w,)
#Es sieht aus wie das:
# +----+------------+------------+-------------+-----------+---------+
self.separator += '-'*w + '--+'
self.total_pages = int(ceil(self.total_rows / self.rows_per_page))
self.position = 1
self.page = 1
#Nachricht angezeigt werden
self.msg = 'Page: {}/{}'.format(self.page, self.total_pages)
def end(self):
curses.endwin()
def draw(self):
self.screen.erase()
#Nachricht oben anzeigen
self.screen.addstr(1, 2, self.msg, self.normal_text)
#Rand auf dem Tisch
self.screen.addstr(2, 2, self.separator, self.normal_text)
#Kopfzeile anzeigen
self.screen.addstr(3, 2, self.tavnit % tuple(self.header), self.normal_text)
#Grenze zwischen Header und Inhalt
self.screen.addstr(4, 2, self.separator, self.normal_text)
#Zeichne jede Linie
row_start = 1 + (self.rows_per_page * (self.page - 1))
row_end = self.rows_per_page + 1 + (self.rows_per_page * (self.page - 1))
for i in range(row_start, row_end):
if i >= self.total_rows + 1:
break
row_number = i + (self.rows_per_page * (self.page - 1))
#Linie markieren
if (row_number == self.position + (self.rows_per_page * (self.page - 1))):
color = self.highlight_text
else:
color = self.normal_text
#Da gibt es 4 Zeilen wie Nachrichten und Rahmen oben+4
draw_number = i - (self.rows_per_page * (self.page - 1)) + 4 #Da gibt es 4 Zeilen wie Nachrichten und Rahmen oben
self.screen.addstr(draw_number , 2, self.tavnit % tuple(self.rows[i - 1]), color)
#Unterer Rand der Tabelle,Da gibt es 4 Zeilen wie Nachrichten und Rahmen oben+4
bottom = min(row_end, self.total_rows + 1) - (self.rows_per_page * (self.page - 1)) + 4
self.screen.addstr(bottom, 2, self.separator, self.normal_text)
self.screen.refresh()
def down(self):
if self.page == self.total_pages:
if self.position < self.total_rows:
self.position += 1
else:
if self.position < self.rows_per_page + (self.rows_per_page * (self.page - 1)):
self.position += 1
else:
self.page += 1
self.position = 1 + (self.rows_per_page * (self.page - 1))
self.msg = 'Page: {}/{}'.format(self.page, self.total_pages)
self.draw()
def up(self):
if self.page == 1:
if self.position > 1:
self.position -= 1
else:
if self.position > (1 + (self.rows_per_page * (self.page - 1))):
self.position -= 1
else:
self.page -= 1
self.position = self.rows_per_page + (self.rows_per_page * (self.page - 1))
self.msg = 'Page: {}/{}'.format(self.page, self.total_pages)
self.draw()
def esc(self):
self.end()
def enter(self):
#Was Sie hier machen wollen
prefecture_id = self.rows[self.position - 1][0]
prefecture = self.rows[self.position - 1][1]
self.msg = 'Page: {}/{} ({} {} was selected.)' \
.format(self.page, self.total_pages, prefecture_id, prefecture)
self.draw()
def loop(self):
#Erkennt den eingegebenen Schlüssel
key = self.screen.getch()
while 1:
if key == ENTER:
self.enter()
elif key == ESC:
self.esc()
break
elif key == DOWN:
self.down()
elif key == UP:
self.up()
key = self.screen.getch()
if __name__ == '__main__':
with open('prefectures.csv') as f:
reader = csv.reader(f)
data = list(reader)
header = data[0]
rows = data[1:]
ui = UI(header, rows)
ui.draw()
ui.loop()
$ python main.py
Die maximale Anzahl von Zeilen auf der Seite beträgt 20.
Sie können mit ↑
und ↓
scrollen.
Wenn Sie die Eingabetaste drücken (Zurück), werden die Informationen der entsprechenden Präfektur in der Nachricht angezeigt.
Beenden Sie die GUI mit "ESC".
Recommended Posts