Cet article concerne le festival d'été Qiita 2020 "Si vous voulez créer △△ (application) en utilisant uniquement 〇〇 (langue)" Il présente l'application ** TODO (distribuée) ** créée sous forme de thème et explique comment l'implémenter.
J'utilise ** Python3 (ver 3.7) ** et j'ai confirmé l'opération sous Windows 10.
Le code se trouve sur le GitHub ci-dessous. Sentez-vous libre de l'utiliser.
[Code] 1
L'application est la suivante.
Il y a un endroit pour afficher la liste TODO en bas.
Vous pouvez sélectionner une chaîne dans le menu déroulant pour afficher un TODO spécifique, et elle sera affichée en appuyant sur le bouton de mise à jour.
Sélectionnez une liste TODO pour voir plus de détails dans la liste.
Il met en œuvre trois fonctions principales.
Cette fonction recherche les fichiers TODO enregistrés dans plusieurs dossiers spécifiés et les affiche dans une liste à l'écran.
Par exemple, supposons que vous stockiez un ** fichier TODO ** appelé .txt ** dans un dossier appelé ** F: \ Document \ Qiita ** qui publie une application todo faite uniquement avec ** python. Dans ce fichier, les détails de TODO, la date limite de publication de l'article en cours de rédaction, la date limite de publication, etc. sont inscrits.
D'autre part, supposons qu'il y ait un autre ** fichier TODO ** dans le dossier ** F: \ Document \ python \ django **.
Le problème avec cette situation est que les ** fichiers TODO ** sont ** distribués **.
Bien sûr, vous pouvez créer un ** dossier TODO ** et y placer le ** fichier TODO **, mais puisque vous avez créé et organisé la hiérarchie des dossiers à votre manière, les fichiers associés sont, par exemple, ** TODO. Je veux mettre le fichier ** dans le même dossier. De plus, des informations importantes peuvent être ajoutées, telles que l'ajout du contenu recherché au ** fichier TODO **.
Afin de résoudre le problème ci-dessus, des ** fichiers TODO ** peuvent être distribués.
Cette fonction répertorie uniquement les ** fichiers TODO ** dans un dossier particulier.
Lorsque le nombre de ** fichiers TODO ** augmente, il est difficile de trouver le ** fichier TODO ** souhaité dans tous les ** fichiers TODO **.
Par conséquent, nous avons rendu possible la sélection d'un dossier dans le menu déroulant afin que seuls les ** fichiers TODO ** stockés dans un dossier spécifique puissent être affichés.
Cette fonction affiche les détails en bas de l'écran lorsque vous cliquez sur la liste affichée des ** fichiers TODO **.
Les détails sont décrits dans le ** fichier TODO **.
En gros, il peut suffire d'écrire un ** TODO ** spécifique (que faire) avec le nom du fichier. Cependant, j'ai pensé qu'il serait préférable de voir les progrès et le contenu de l'enquête, alors je l'ai mise en œuvre.
Téléchargez le code depuis [GitHub] 1 au début de cet article et placez-le dans un dossier.
Exécutez ** display.py ** pour lancer l'interface graphique.
python display.py
Le fichier de configuration est un fichier nommé ** config.ini ** et est décrit dans le format suivant.
[Dir_names]
#Le nom affiché dans le menu déroulant=Chemin absolu du dossier contenant le fichier TODO
#Exemple
qiita=F:\Document\800_Auto-apprentissage informatique\09_python\51_Qiita
[File_names]
#Le nom du fichier que vous souhaitez afficher dans la liste TODO. Caractère générique(*)Vous pouvez utiliser.
#Exemple
#Fichiers avec la chaîne todo au début
todo=todo*
#Fichiers avec l'extension py
python=*.py
** * Veuillez noter que la recherche peut prendre un certain temps s'il y a un grand nombre de dossiers et de fichiers sous le nom de dossier répertorié. ** ** ** C'est une histoire extrême, mais si vous écrivez C: \ dans le nom du dossier, cela prendra un temps considérable pour afficher la liste TODO. ** **
** Le code de caractère du fichier TODO doit être UTF-8. L'écran de détails ne s'affiche pas. ** **
operate_file_1.py
import os
import fnmatch
#root:Nom du répertoire
#patterns:Prend en charge les caractères génériques de type shell Unix. Modèle de nom de fichier
#yeild_folders:S'il faut lire les fichiers dans le sous-répertoire.
def all_files(root, patterns = "*", single_level=False, yeild_folders=False):
#split:";"Vous pouvez spécifier plusieurs modèles avec.;Ne peut pas être inclus dans le modèle.
patterns = patterns.split(";")
#os.Passez le nom du chemin du répertoire, le nom du répertoire et le nom du fichier sous le répertoire spécifié par walk.
for path, subdirs, files in os.walk(root):
if yeild_folders:
files.extend(subdirs)
files.sort()
for name in files:
for pattern in patterns:
#fnmatch renvoie True si le nom correspond au modèle.
if fnmatch.fnmatch(name, pattern):
yield os.path.join(path, name)
break
if single_level:
break
Ce sera le code décrit dans le livre de recettes Python.
Python Cookbook 2nd Edition (Page 89, 2.16 Directory Tree Search) par Alex Martelli, Anna Martelli Ravenscroft, David Ascher, Masao Kamozawa, Hitoshi Toyama, Satoshi Yoshida, Sadaki Yoshimune, etc. Traduit par O'Reilly Japan ISBN978- 4-87311-276-3
Ce que nous faisons est de rechercher une correspondance à partir du nom de répertoire et de nom de fichier reçus et de renvoyer le résultat.
todo.py
from operate_file_1 import all_files
import configparser
class Todo:
def __init__(self):
self.rule_file = configparser.ConfigParser()
self.rule_file.read("./config.ini", "UTF-8")
self.dir_name_keys = list(self.rule_file["Dir_names"].keys())
self.dir_names = [self.rule_file["Dir_names"][key] for key in self.rule_file["Dir_names"].keys()]
self.patterns = [self.rule_file["File_names"][key] for key in self.rule_file["File_names"].keys()]
def search_file(self):
paths = {}
for index, dir_name in enumerate(self.dir_names):
paths[self.dir_name_keys[index]] = list(all_files(dir_name, ";".join(self.patterns)))
return paths
def limit_search_file(self, dir_name_key):
paths = {}
paths[dir_name_key] = list(all_files(self.rule_file["Dir_names"][dir_name_key], ";".join(self.patterns)))
return paths
def get_dir_name_keys(self):
return self.dir_name_keys
Il s'agit d'une classe qui lit les paramètres de ** config.ini ** et recherche le fichier à l'aide de la fonction décrite dans ** operator_file_1.py **.
Utilisez le module intégré à python appelé ** [configparser] 2 ** pour lire la valeur du fichier de configuration.
** search \ _file ** recherche toute la recherche, ** limit \ _ search \ _file ** recherche uniquement le dossier spécifié.
display.py
import tkinter as tk
import os
import datetime
from todo import Todo
from gui_object import Frame, Label, Listbox, Text, Button, Combobox
class TodoDisplay:
def __init__(self):
self.root = tk.Tk()
self.root.title("todo")
self.todo = Todo()
self.todo_list_box_dict = {}
self.todo_list_frame = Frame(self.root)
self.todo_list_frame.grid(column=0, row=1)
self.todo_detail_frame = Frame(self.root)
self.todo_detail_frame.grid(column=0, row=2)
self.function_frame = Frame(self.root)
self.function_frame.grid(column=0, row=0)
self.listbox = Listbox(master=self.todo_list_frame, master_of_detail_text=self.todo_detail_frame)
self.refresh_button = Button(master=self.function_frame)
self.refresh_button.grid(column=1, row=0)
self.refresh_button["text"] = "mise à jour"
self.refresh_button["command"] = self.refresh
self.combbox = Combobox(master=self.function_frame)
self.combbox.grid(column=0, row=0)
self.set_value_for_combbox()
def display_todo(self):
todo_list_box_id = 0
self.todo_list_box_dict = {}
if (self.combbox.get() == "all") or (self.combbox.get() == ""):
paths = self.todo.search_file()
else:
paths = self.todo.limit_search_file(self.combbox.get())
for key in paths.keys():
for path in paths[key]:
create_time, update_time = self.get_timestamp_of_path(path)
insert_statement = " ".join(["Créer", create_time, "mise à jour", update_time, path.split("\\")[-1].split(".")[0]])
self.listbox.insert(todo_list_box_id, insert_statement)
self.todo_list_box_dict[todo_list_box_id] = path
todo_list_box_id = todo_list_box_id + 1
self.listbox.set_todo_list(self.todo_list_box_dict)
def get_timestamp_of_path(self, path):
stat_result = os.stat(path)
create_time = datetime.datetime.fromtimestamp(stat_result.st_ctime).strftime("%Y/%m/%d %H:%M:%S")
update_time = datetime.datetime.fromtimestamp(stat_result.st_mtime).strftime("%Y/%m/%d %H:%M:%S")
return create_time, update_time
def refresh(self, event=None):
self.listbox.delete(0, "end")
self.display_todo()
def set_value_for_combbox(self):
self.combbox["value"] = ["all"] + [dir_name.split("\\")[-1] for dir_name in self.todo.get_dir_name_keys()]
def mainloop(self):
self.root.mainloop()
if __name__ == "__main__":
todo_display = TodoDisplay()
todo_display.display_todo()
todo_display.mainloop()
En utilisant l'objet ** Tkinter **, nous affichons une liste de ** fichiers TODO ** recherchés dans ** todo.py **.
gui_object.py
from tkinter import *
import tkinter as tk
import tkinter.ttk as ttk
class Frame(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid(column=0, row=0)
self["width"] = 100
self["height"] = 100
self["padx"] = 20
self["pady"] = 20
class Button(tk.Button):
def __init__(self, master=None):
tk.Button.__init__(self, master)
self["height"] = 2
self["width"] = 20
self["font"] = ("Helvetica", 15)
class RefreshButton(Button):
def __init__(self, master=None,):
Button.__init__(self, master)
class Combobox(ttk.Combobox):
def __init__(self, master=None):
ttk.Combobox.__init__(self, master)
self["font"] = ("Helvetica", 20)
class Text(tk.Text):
def __init__(self, master=None):
tk.Text.__init__(self, master)
self["width"] = 100
self["height"] = 10
class Listbox(tk.Listbox):
def __init__(self, master=None, master_of_detail_text=None):
scrollbar = Scrollbar(master)
scrollbar.pack(side=RIGHT, fill=Y)
tk.Listbox.__init__(self, master, yscrollcommand=scrollbar.set, selectmode=EXTENDED)
self.pack(side=LEFT, fill=BOTH)
self["width"] = 100
self["height"] = 10
self["font"] = ("Helvetica", 12)
self.master = master
self.master_of_detail_text = master_of_detail_text
self.text = Text(self.master_of_detail_text)
scrollbar["command"] = self.yview
self.bind("<Double-Button-1>", self.show_detail)
self.bind("<Return>", self.show_detail)
self.todo_list = {}
def show_detail(self, event=None):
self.text.destroy()
self.text = Text(self.master_of_detail_text)
self.text.insert(END, self.read_detail_of_todo(self.index(ACTIVE)))
self.text.pack()
def set_todo_list(self, todo_list_dict):
self.todo_list = todo_list_dict
def read_detail_of_todo(self, index):
path = self.todo_list[index]
with open(path, encoding="utf_8") as f:
return f.read()
Les paramètres sont définis pour divers objets ** Tkinter ** utilisés dans ** display.py **.
J'ajuste principalement l'apparence.
C'était un moment amusant et heureux pour créer une application avec un thème fixe.
J'espère que cette application TODO sera utile à l'avenir.