Ccmmutty logo
Commutty IT
12 min read

自分の欲しいを全部乗せ!tkinterでメモ帳作り「3.3_既存のテキストファイルを開く」

https://cdn.magicode.io/media/notebox/501d241d-68a5-4304-9255-234b467605e7.jpeg

はじめに

このシリーズでは、tkinterを使って自分が欲しいと思う機能を全部乗せた 「自分だけのメモ帳」 を作成していきます。
一連の目次については、この記事の一番下に記載しています。
 
このページでは、
「既存のテキストファイルを開く」機能を追加します。

最初に作成したものを確認する

ファイルを開く

ファイルを開く流れは
  1. 開くファイルを選択するダイアログを表示する
  2. ファイルの文字コードを判定して読み込む
  3. 一度テキストエリアを全て削除し、読み込んだ内容を挿入する
  4. 読み込んだファイルのファイル名を取得して、タイトル部分を更新する
という感じです。
 
ファイルを開くダイアログ表示には
今回もキーボードショートカットを使用します。
 

設定しているキーボードショートカットについて

操作内容ショートカット
新規ウィンドウを作成するCtrl + n
ウィンドウを閉じるCtrl+w, Ctrl+q
【NEW】既存のファイルを開くCtrl+o
ウィンドウを常に最前面表示するCtrl + →
ウィンドウの最前面表示を解除するCtrl + ←
「Ctrl と oキー」を組み合わせて、
ファイルを開くダイアログを表示します。
 

今回作成したコード

追加した部分_入力と関数をbindする

#################
# キーバインドでショートカット実行できるようにする

## ウィンドウ関連

### 既存のファイルを開く
root.bind_all('<Control-KeyPress-o>', openFile)
 
"<Control-組み合わせる入力>" で Ctrl+入力 というようにショートカット操作が設定できます。
「KeyPress-」でキーボードの入力したときをトリガーにする、
「o」が入力するキーです。

追加した部分_モジュールのインポート

############
# モジュールインポート

## ファイル操作関連
### tkinter でファイルダイアログ操作する 標準ライブラリ
import tkinter.filedialog
### 文字コードを自動識別するライブラリ # pip install chardet
import chardet
### ファイルの名前やパスを取得するときに使用している 標準ライブラリ
import os
既存ファイルを開くために、新たに3つのモジュールをインポートしています。

tkinter.filedialog

tkinterでファイルを開く場合は、tkinter.filedialogモジュール の askopenfilename を使用します。
下記がオプションなどわかりやすかったです、ありがとうございます!
【Python/tkinter】ファイルを開くダイアログボックスの表示 | イメージングソリューション https://imagingsolution.net/program/python/tkinter/openfiledialog/

chardet

文字コードを判断して開きます。
こちらは標準モジュールではないので、pipインストールしています。
pip install chardet
追加内容は下記サイトの内容をほぼ使用させていただいています!
とても分かりやすかったです、本当にありがとうございます!!!
スグできる!Tkinterでシンプルなメモ帳(テキストエディタ)を作成! https://programming-self-study.blogspot.com/2021/07/tkintermemo.html

os

ファイルの名前やパスを取得します。
下記サイトにて使い方が丁寧に説明されています。
Pythonでパス文字列からファイル名・フォルダ名・拡張子を取得、結合 | note.nkmk.mehttps://note.nkmk.me/python-os-basename-dirname-split-splitext/
pythonで何か書くとき****note.nkmk.me**** さんを参照しないときはない! というほど参考にさせていただいています!!
 

追加した部分_動作を提供する関数

###############################
#### 各種機能を提供する関数 ####
###############################

#####################
# ウィンドウ関連

# 既存のファイルを開く
def openFile(self):
    #「開く」イベント
    global file
    dialog = tkinter.filedialog.askopenfilename(filetypes=[("All Files","*.*")])
    if len(dialog) != 0:
        #文字コードを自動識別して読み取るコード スグできる!Tkinterでシンプルなメモ帳(テキストエディタ)を作成https://programming-self-study.blogspot.com/2021/07/tkintermemo.html
        FILENAME = dialog
        tmp = open(FILENAME,"rb")
        encode = chardet.detect(tmp.read())["encoding"]
        tmp.close()
        file = open(FILENAME,"r",encoding=encode,errors="ignore")
        text = file.read()
        file.close()
        #一度文字を全て削除してから挿入する
        TextArea.delete("1.0",tkinter.END)
        TextArea.insert("1.0",text)
        file_title=os.path.basename(dialog)
        root.title(file_title)
tkinter.filedialog.askopenfilenameでファイルを開くダイアログを表示します。
ファイルを選択せずにキャンセルした場合、dialogになにも入りません。
0じゃなかったら、つまりファイルが選択されていたら開く処理を実行します。
global file
fileはこの時点ではグローバルである必要はないと思うのですが、
今後追加する機能で頻繁に使用するため、グローバルとしておきます。

メモ帳コード全体

############
# モジュールインポート # Pythonのモジュールとimportとfrom入門 - Qiita https://qiita.com/niwaka_dev/items/6e3d9ff6d797243c77c3

## tkinter モジュールをインポートする 標準ライブラリ
import tkinter

## ファイル操作関連
### tkinter でファイルダイアログ操作する 標準ライブラリ
import tkinter.filedialog
### 文字コードを自動識別するライブラリ # pip install chardet
import chardet
### ファイルの名前やパスを取得するときに使用している 標準ライブラリ
import os

## 別ウィンドウを開くときに使用している2つ 標準ライブラリ
import subprocess
import sys

############
# ウィンドウの基本設定

## 実行時の引数を取得する
args =sys.argv # print(args[0]) # →C:\Users\フルパス\stickypynote.py

## rootの設定
root = tkinter.Tk()
root.title("Untitled.txt") # タイトルバーに表示される文字列を指定する

x, y=644,188 # 最初のウィンドウサイズを指定する
root.geometry('%dx%d' % (x, y))

## テキスト入力エリア TextArea を作成
TextArea = tkinter.Text(root, font="メイリオ 8",wrap=tkinter.CHAR,undo=True,maxundo=0)
### wrap=tkinter.CHAR 文字単位で折り返す
### undo=True,maxundo=0 undoを有効にして、何回でもundoできる(0以下で無限)

###############
# スクロールバーの設定
## テキストエリアウィジェットに紐付ける形でスクロールバーを作成する
Scroll = tkinter.Scrollbar(TextArea)
## 右側に配置する。テキストエリア内で空きスペースが出来ないように、縦横に拡げて配置する
Scroll.pack(side=tkinter.RIGHT,  fill=tkinter.BOTH)
## スクロールバーのドラッグで縦軸方向にスクロールできるようにする
Scroll.config(command=TextArea.yview)
## テキストエリアウィジェットにスクロールバーをセットする
TextArea.config(yscrollcommand=Scroll.set)

###############################
#### 各種機能を提供する関数 ####
###############################

#####################
# 最前面on/off

# 最前面に表示する関数、最前面ボタンも切り替える
def saizen_on():
    root.attributes('-topmost',True), # ic(root.attributes('-topmost')) # ic| root.attributes('-topmost'): 1
    button_top_on.grid_remove(),
    button_top_off.grid()

# 最前面表示を解除する関数、最前面ボタンも切り替える
def saizen_off():
    root.attributes('-topmost',False), # ic(root.attributes('-topmost')) # ic| root.attributes('-topmost'): 0
    button_top_off.grid_remove(),
    button_top_on.grid()

# キーバインドショートカットから呼び出す
def saizen_on_bind(self):
    press_key=self.keysym # print(self) # <KeyPress event state=Control|0x40000 keysym=Right keycode=39 x=415 y=76>
    if press_key == "Right":
        saizen_on()
    elif press_key == "Left":
        saizen_off()

#####################
# ウィンドウ関連

# 新規ウィンドウで新規作成する
def newFile(self):
    subprocess.Popen(('python "'+args[0]+'"'), stdout = subprocess.PIPE, shell=True)

# ウィンドウを閉じる
def quitApp(self):
    root.destroy()

# 既存のファイルを開く
def openFile(self):
    #「開く」イベント
    # global file
    dialog = tkinter.filedialog.askopenfilename(filetypes=[("All Files","*.*")])
    if len(dialog) != 0:
        #文字コードを自動識別して読み取るコード スグできる!Tkinterでシンプルなメモ帳(テキストエディタ)を作成https://programming-self-study.blogspot.com/2021/07/tkintermemo.html
        FILENAME = dialog
        tmp = open(FILENAME,"rb")
        encode = chardet.detect(tmp.read())["encoding"]
        tmp.close()
        file = open(FILENAME,"r",encoding=encode,errors="ignore")
        text = file.read()
        file.close()
        #一度文字を全て削除してから挿入する
        TextArea.delete("1.0",tkinter.END)
        TextArea.insert("1.0",text)
        file_title=os.path.basename(dialog)
        root.title(file_title)

#####################
# 各ウィジェットの設定
#
# 参考
# PythonのTkinterでGUIアプリを作る - Qiita # https://qiita.com/canard0328/items/5ea096352e160b8ececa

## 最前面on/offボタン
### 最前面表示をoffにする関数を呼ぶボタン
button_top_off = tkinter.Button(root, font="meiryo 4",text = "▲",command=saizen_off)
### 最前面表示をonにする関数を呼ぶボタン
button_top_on = tkinter.Button(root,font="meiryo 4", text = "▽",command=saizen_on)

############
# gridの設定

## 最前面on/offボタン
button_top_off.grid(row=0,column=1,sticky=tkinter.E)
button_top_on.grid(row=0,column=1,sticky=tkinter.E)

## テキスト入力エリア
TextArea.grid(row=1,column=0,columnspan=2,sticky=tkinter.NSEW)

# 作成したウィンドウについて、各行列をどのように伸縮するか
root.rowconfigure(1, weight=1)
root.columnconfigure(0, weight=1)

#################
# キーバインドでショートカット実行できるようにする

## 最前面のon/offを切り替えるショートカット
root.bind_all("<Control-KeyPress-Right>", saizen_on_bind)
root.bind_all("<Control-KeyPress-Left>", saizen_on_bind)

## ウィンドウ関連
### 新規ウィンドウで新規作成する
root.bind_all("<Control-KeyPress-n>", newFile)
### ウィンドウを閉じる
root.bind_all("<Control-KeyPress-q>", quitApp)
root.bind_all("<Control-KeyPress-w>", quitApp)
### 既存のファイルを開く
root.bind_all('<Control-KeyPress-o>', openFile)

#################
# メインループ
root.mainloop()
 

おわりに。続きがメモれる!

今回は既存のテキストファイルを開く機能を追加しました。
これで書き捨てることなく、積み上げた文章の続きが書けますね!
 

Discussion

コメントにはログインが必要です。