[Python] ファイル削除ツール アップデートv0.0.3 スクロールバー他

[macOS Catalina 10.15.7]

アップデート内容はXY方向のスクロールバー配置、自動スクロール、無限ループ、処理完了時刻表示です。

スクロールバーを付けるだけでしんどい思いをしました。FrameBクラスの記述ではいいサンプルコードを見つけるまでは七転八倒状態でした。

JavaでのGUI作成の快適さを知ってしまうと、tkinterで作るモチベーションがかなり低下します。

JavaからPythonによるスクレイピング のモジュールを呼び出せるのであればGUIについては全てJavaで作成するのですが、Python3は一切融通できないところがツラいです。

今後ツール類はJavaで書くかもしれません。ただJavaはJavaでコード量が増えるデメリットがあるので、後継言語とされているScalaでどうなるか試してみる可能性もあります。

このツールだけはtkinterでとことんやってみようかとも思っています。

※ 21/07/06追記 あとでわかったことですがTextウィジェットはスクロールバーがなくてもスクロールできます。ただ表示されている部分の全体における位置が分からないのでスクロールバーがある方が見やすいです。

import glob,os,shutil,sys,datetime
import tkinter as tk
import tkinter.font as font
from tkinter import ttk

# 色
# '#98fb98','#8b0000','#808000','#FF7F50','#00FA9A','#9370DB','#40E0D0','#FFFACD'

def list_text():
    # frameB全ウィジェットのinfoを取得
    children = frameB.winfo_children()
    text_list = [entry for entry in children if type(entry)==tk.Text]

    return text_list

class FrameA(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.configure(background = '#FFFACD')
        self.grid(row=1,column=1, sticky=tk.NSEW, padx=5, pady=5)

class FrameB(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.configure(background = '#FFFACD')
        # テキストウィジェットの設定
        self.msg_box = tk.Text(self,width=30,height=5,background = '#98fb98',foreground = '#8b0000',font=my_font2,wrap=tk.NONE)
        # スクロールするフレームをテキストウィジェットに設定
        self.scrollable_frame = ttk.Frame(self.msg_box)
        # FrameBのグリッド位置を設定
        self.grid(row=2,column=1, sticky=tk.NSEW, padx=5, pady=5)

        # Y方向スクロールバーの設定
        self.scrollbar_y = ttk.Scrollbar(self, orient="vertical", command=self.msg_box.yview)
        self.scrollbar_y.pack(side=tk.RIGHT, fill="y")
        self.msg_box.configure(yscrollcommand=self.scrollbar_y.set)
        
        # X方向スクロールバーの設定
        self.scrollbar_x = ttk.Scrollbar(self, orient="horizontal", command=self.msg_box.xview)
        self.scrollbar_x.pack(side=tk.BOTTOM, fill="x")
        self.msg_box.configure(xscrollcommand=self.scrollbar_x.set)
        self.msg_box.pack(side=tk.LEFT, fill="both", expand=True)

# Macのデスクトップ通知
def notification1():
    os.system("osascript -e 'display notification \"フォルダ削除\n処理完了\"'")

def notification2():
    os.system("osascript -e 'display notification \"ファイル削除\n処理完了\"'")

root = tk.Tk()
root.title("FILE REMOVER v0.0.3")
root.geometry("460x210")
root.configure(bg='#FFFACD')
style = ttk.Style()
style.theme_use('clam')
style.configure("Vertical.TScrollbar", gripcount=0,
                background="Green", darkcolor="DarkGreen", lightcolor="LightGreen",
                troughcolor="gray", bordercolor="gray", arrowcolor="white")
style.configure("Horizontal.TScrollbar", gripcount=0,
                background="Green", darkcolor="DarkGreen", lightcolor="LightGreen",
                troughcolor="gray", bordercolor="gray", arrowcolor="white")

# フォント設定
my_font = font.Font(root,family="System",size=18,weight="normal")
my_font2 = font.Font(root,family="System",size=16,weight="normal")

# フレームの作成・配置
frame = tk.Frame(root,background = '#FFFACD')
frame.grid(row=0,column=0, sticky=tk.NSEW, padx=5, pady=10)
frameA = FrameA(master=frame)
frameB = FrameB(master=frame)

# ラベルの作成・配置
label = tk.Label(frame,text='PATH',background = '#FFFACD',foreground = '#8b0000',font=my_font)
label.grid(row=0, column=0)

# パス入力エントリの作成・配置
entry = tk.Entry(frame,width=25,background = '#98fb98',foreground = '#8b0000',font=my_font)
entry.grid(row=0,column=1,sticky=tk.W)

# 実行ボタンの作成・配置
var_act = tk.IntVar()
btn = tk.Button(frame, text="削除",command=lambda:var_act.set(1),width=2,font=my_font)
btn.grid(row=0,column=2,padx=2)

# ラジオボタンの作成・配置
var = tk.IntVar()
rb1 = ttk.Radiobutton(frameA,text='フォルダ',value=1,variable=var)
rb1.pack(padx=30,side=tk.LEFT)

rb2 = ttk.Radiobutton(frameA,text='ファイル',value=2,variable=var)
rb2.pack(padx=30,side=tk.LEFT)

# クリアボタンの作成・配置
btn2 = tk.Button(frame, text="クリア",command=lambda:[entry.delete(0,tk.END),text_list[0].delete('1.0',tk.END)],width=2,font=my_font)
btn2.grid(row=1,column=2,padx=2)

text_list = list_text()
print(text_list)

while True:
    # フォルダパスの入力を待機
    btn.wait_variable(var_act)

    # 入力したフォルダパスを取得
    dirpath = entry.get()

    # ラジオボタンのvalueを取得
    v = var.get()

    if v == 1:
        path = dirpath + '/*' # 直下のフォルダを削除
        for f in glob.glob(path,recursive=True):
            if os.path.isdir(f):
                shutil.rmtree(f)

        datetime_now = datetime.datetime.now()
        datetime_now_str = datetime_now.strftime('%y/%m/%d %H:%M:%S')

        text_list[0].insert(tk.END,dirpath+'\n')
        text_list[0].insert(tk.END,f'フォルダ削除完了 {datetime_now_str}\n')
        text_list[0].see("end")
        notification1()
    else:
        path = dirpath + '/**' # 再帰的処理により下層ファイルも削除
        for f in glob.glob(path, recursive=True):
            if os.path.isfile(f):
                os.remove(f)

        datetime_now = datetime.datetime.now()
        datetime_now_str = datetime_now.strftime('%y/%m/%d %H:%M:%S')

        text_list[0].insert(tk.END,dirpath+'\n')
        text_list[0].insert(tk.END,f'ファイル削除完了 {datetime_now_str}\n')
        text_list[0].see("end")
        notification2()

root.mainloop()

参考サイト