Selon le Document officiel,
La bibliothèque curses fournit le dessin d'écran indépendant du terminal et le traitement du clavier pour les terminaux basés sur du texte (terminaux) tels que les VT100, les consoles Linux et les terminaux d'émulation fournis par divers programmes. Le terminal prend en charge divers codes de commande pour effectuer des opérations courantes telles que déplacer le curseur, faire défiler l'écran et effacer la zone. Différents types de terminaux peuvent utiliser des codes de contrôle très différents, souvent avec des bizarreries uniques.
Cela peut être utile lorsque vous souhaitez créer une interface graphique simple ou lorsque vous souhaitez travailler avec des données sur un serveur accessible uniquement avec ssh. Vous pouvez également afficher le contenu de CSV et DB.
Par exemple, supposons que vous ayez le [fichier csv] suivant (https://raw.githubusercontent.com/hrdrq/curses_sample/master/prefectures.csv).
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 |
Je souhaite créer une interface graphique pouvant afficher le contenu sur le terminal et sélectionner la préfecture à traiter.
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
#Initialisation
self.screen = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
self.screen.keypad(1)
#Paramètres de couleur
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_CYAN)
self.highlight_text = curses.color_pair(1) #Utilisez l'identifiant de paire dans la ligne ci-dessus
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)
#Enregistrez la largeur de chaque colonne
self.widths = []
#Dessin de bordure
self.tavnit = '|'
self.separator = '+'
for index, title in enumerate(self.header):
#Faire du titre de la colonne et de la valeur la plus longue de chaque ligne la largeur de la colonne
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)
#Paramètres de bordure
for w in self.widths:
#Cela ressemble à ceci:
# | %-2s | %-10s | %-10s | %-11s | %-9s | %-7s |
self.tavnit += " %-"+"%ss |" % (w,)
#Cela ressemble à ceci:
# +----+------------+------------+-------------+-----------+---------+
self.separator += '-'*w + '--+'
self.total_pages = int(ceil(self.total_rows / self.rows_per_page))
self.position = 1
self.page = 1
#Message à afficher
self.msg = 'Page: {}/{}'.format(self.page, self.total_pages)
def end(self):
curses.endwin()
def draw(self):
self.screen.erase()
#Afficher le message en haut
self.screen.addstr(1, 2, self.msg, self.normal_text)
#Bordure sur la table
self.screen.addstr(2, 2, self.separator, self.normal_text)
#Afficher en-tête
self.screen.addstr(3, 2, self.tavnit % tuple(self.header), self.normal_text)
#Frontière entre l'en-tête et le contenu
self.screen.addstr(4, 2, self.separator, self.normal_text)
#Tracez chaque ligne
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))
#Mettre en évidence la ligne
if (row_number == self.position + (self.rows_per_page * (self.page - 1))):
color = self.highlight_text
else:
color = self.normal_text
#Puisqu'il y a 4 lignes telles que des messages et des bordures au-dessus+4
draw_number = i - (self.rows_per_page * (self.page - 1)) + 4 #Puisqu'il y a 4 lignes telles que des messages et des bordures au-dessus
self.screen.addstr(draw_number , 2, self.tavnit % tuple(self.rows[i - 1]), color)
#Bordure inférieure du tableau,Puisqu'il y a 4 lignes telles que des messages et des bordures au-dessus+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):
#Ce que tu veux faire ici
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):
#Détecte la clé saisie
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
Le nombre maximum de lignes sur la page est de 20.
Vous pouvez faire défiler avec ↑
et ↓
.
ʻEnter (return) affichera les informations de la préfecture correspondante dans le message. Quittez l'interface graphique avec ʻESC
.
Recommended Posts