Dieser Artikel handelt vom Qiita Summer Festival 2020 "Wenn Sie △△ (App) jetzt nur mit 〇〇 (Sprache) erstellen möchten" Es wird die als Thema erstellte ** TODO-Anwendung (verteilt) ** vorgestellt und deren Implementierung erläutert.
Ich verwende ** Python3 (Version 3.7) ** und habe den Vorgang unter Windows 10 bestätigt.
Der Code befindet sich auf dem GitHub unten. Fühlen Sie sich frei, es zu benutzen.
[Code] 1
Die Anwendung ist wie folgt.
Unten können Sie die TODO-Liste anzeigen.
Sie können eine Zeichenfolge aus dem Pulldown auswählen, um ein bestimmtes TODO anzuzeigen. Diese wird durch Drücken der Aktualisierungstaste angezeigt.
Wählen Sie eine TODO-Liste aus, um weitere Details in der Liste anzuzeigen.
Es implementiert drei Hauptfunktionen.
Diese Funktion sucht nach TODO-Dateien, die in mehreren angegebenen Ordnern gespeichert sind, und zeigt sie in einer Liste auf dem Bildschirm an.
Angenommen, Sie speichern eine ** TODO-Datei ** mit dem Namen .txt ** in einem Ordner mit dem Namen ** F: \ Document \ Qiita **, in dem eine nur mit ** Python erstellte Aufgaben-App veröffentlicht wird. In dieser Datei sind die Details von TODO, die Frist für die Veröffentlichung des aktuell verfassten Artikels und die Frist für die Veröffentlichung usw. angegeben.
Angenommen, im Ordner ** F: \ Document \ python \ django ** befindet sich eine weitere ** TODO-Datei **.
Das Problem in dieser Situation ist, dass die ** TODO-Dateien ** verteilt ** sind.
Natürlich können Sie einen ** TODO-Ordner ** erstellen und die ** TODO-Datei ** darin ablegen, aber da Sie die Ordnerhierarchie auf Ihre eigene Weise erstellt und organisiert haben, sind die zugehörigen Dateien beispielsweise ** TODO. Ich möchte die Datei ** in den gleichen Ordner legen. Darüber hinaus können wichtige Informationen hinzugefügt werden, z. B. das Hinzufügen der gesuchten Inhalte zur ** TODO-Datei **.
Um das obige Problem zu lösen, können ** TODO-Dateien ** verteilt werden.
Diese Funktion listet nur ** TODO-Dateien ** in einem bestimmten Ordner auf.
Wenn die Anzahl der ** TODO-Dateien ** zunimmt, ist es schwierig, die gewünschte ** TODO-Datei ** aus allen ** TODO-Dateien ** zu finden.
Aus diesem Grund haben wir es möglich gemacht, einen Ordner aus dem Pulldown-Menü auszuwählen, sodass nur ** TODO-Dateien ** angezeigt werden können, die in einem bestimmten Ordner gespeichert sind.
Diese Funktion zeigt die Details am unteren Bildschirmrand an, wenn Sie auf die angezeigte Liste der ** TODO-Dateien ** klicken.
Die Details sind in der ** TODO-Datei ** beschrieben.
Grundsätzlich kann es ausreichen, ein bestimmtes ** TODO ** (was zu tun ist) mit dem Dateinamen zu schreiben. Ich dachte jedoch, es wäre besser, den Fortschritt und den Inhalt der Umfrage zu sehen, also habe ich sie umgesetzt.
Laden Sie den Code von [GitHub] 1 am Anfang dieses Artikels herunter und legen Sie ihn in einem Ordner ab.
Führen Sie ** display.py ** aus, um die GUI zu starten.
python display.py
Die Konfigurationsdatei ist eine Datei mit dem Namen ** config.ini ** und wird im folgenden Format beschrieben.
[Dir_names]
#Der im Pulldown angezeigte Name=Absoluter Pfad des Ordners, der die TODO-Datei enthält
#Beispiel
qiita=F:\Document\800_IT selbstlernend\09_python\51_Qiita
[File_names]
#Der Name der Datei, die Sie in der TODO-Liste anzeigen möchten. Platzhalter(*)Sie können verwenden.
#Beispiel
#Dateien mit der Zeichenfolge todo am Anfang
todo=todo*
#Dateien mit py-Erweiterung
python=*.py
** * Bitte beachten Sie, dass die Suche einige Zeit dauern kann, wenn sich unter dem aufgelisteten Ordnernamen eine große Anzahl von Ordnern und Dateien befindet. ** ** ** ** Es ist eine extreme Geschichte, aber wenn Sie C: \ in den Ordnernamen schreiben, wird es eine beträchtliche Zeit dauern, bis die TODO-Liste angezeigt wird. ** ** **
** Der Zeichencode der TODO-Datei sollte UTF-8 sein. Der Detailbildschirm wird nicht angezeigt. ** ** **
operate_file_1.py
import os
import fnmatch
#root:Verzeichnisname
#patterns:Unterstützt Platzhalter im Unix-Shell-Stil. Dateinamenmuster
#yeild_folders:Gibt an, ob Dateien in Unterverzeichnissen gelesen werden sollen.
def all_files(root, patterns = "*", single_level=False, yeild_folders=False):
#split:";"Sie können mehrere Muster mit angeben.;Kann nicht in das Muster aufgenommen werden.
patterns = patterns.split(";")
#os.Übergeben Sie den Verzeichnispfadnamen, den Verzeichnisnamen und den Dateinamen unter dem durch walk angegebenen Verzeichnis.
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 gibt True zurück, wenn der Name mit dem Muster übereinstimmt.
if fnmatch.fnmatch(name, pattern):
yield os.path.join(path, name)
break
if single_level:
break
Dies ist der im Python-Kochbuch beschriebene Code.
Python Cookbook 2nd Edition (Seite 89, 2.16 Verzeichnisbaumsuche) von Alex Martelli, Anna Martelli Ravenscroft, David Ascher, Masao Kamozawa, Hitoshi Toyama, Satoshi Yoshida, Sadaki Yoshimune usw. Übersetzt von O'Reilly Japan ISBN978- 4-87311-276-3
Wir suchen nach einer Übereinstimmung aus dem empfangenen Verzeichnisnamen und dem Dateinamen und geben das Ergebnis zurück.
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
Dies ist eine Klasse, die die Einstellungen aus ** config.ini ** liest und die Datei mit der in ** operator_file_1.py ** beschriebenen Funktion durchsucht.
Verwenden Sie das in Python integrierte Modul ** [configparser] 2 **, um den Wert aus der Konfigurationsdatei zu lesen.
** search \ _file ** durchsucht die gesamte Suche, ** limit \ _ search \ _file ** durchsucht nur den angegebenen Ordner.
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"] = "aktualisieren"
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(["Erstellen", create_time, "aktualisieren", 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()
Mit dem Objekt ** Tkinter ** zeigen wir eine Liste von ** TODO-Dateien ** an, die in ** todo.py ** gesucht wurden.
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()
Einstellungen werden für verschiedene ** Tkinter ** -Objekte vorgenommen, die in ** display.py ** verwendet werden.
Ich passe hauptsächlich das Aussehen an.
Es war eine lustige und glückliche Zeit, eine Anwendung mit einem festen Thema zu erstellen.
Ich hoffe, dass diese TODO-App in Zukunft nützlich sein wird.