Python
 Computer >> コンピューター >  >> プログラミング >> Python

PythonのTkinterでメモ帳アプリを自作する方法【初心者向け完全ガイド】

TkinterはPythonに標準搭載されているGUIライブラリで、これを使えばさまざまなデスクトップアプリケーションを簡単に作成できます。本記事では、Tkinterを活用して、Windowsのメモ帳のようなテキストエディタを実際に開発していきます。

完成するメモ帳にはメニューバーが備わっており、新規ファイルの作成、既存ファイルを開く、保存、編集、切り取り・コピー・貼り付けなど、テキストエディタに必要な基本機能をすべて実装します。

前提条件

  • Pythonがインストールされていること
  • Tkinterがインストールされていること

補足: TkinterはPython 3.xでは標準ライブラリとして同梱されているため、別途インストールは不要です。

メニュー項目の追加

今回作成するメモ帳には、「ファイル」「編集」「コマンド」「ヘルプ」の4つの主要メニューを配置します。それぞれのサブメニューは以下の構成です。

ファイルメニュー

「新規」「開く」「保存」「終了」の4つのサブ項目を持たせます。

編集メニュー

「切り取り」「コピー」「貼り付け」の3つのサブ項目を設定します。

コマンドメニュー

「コマンドについて」という1つのサブ項目のみを含みます。

ヘルプメニュー

「メモ帳について」というサブ項目を1つだけ持たせます。

これらのメニュー項目とサブ項目は、以下のコードで実装できます。

# 新規ファイルを作成
self.__thisFileMenu.add_command(label="New",
command=self.__newFile)
# 既存ファイルを開く
self.__thisFileMenu.add_command(label="Open",
command=self.__openFile)
# 現在のファイルを保存
self.__thisFileMenu.add_command(label="Save",
command=self.__saveFile)
# メニュー内に区切り線を追加
self.__thisFileMenu.add_separator()
self.__thisFileMenu.add_command(label="Exit",
command=self.__quitApplication)
self.__thisMenuBar.add_cascade(label="File", menu=self.__thisFileMenu)
# 切り取り機能
self.__thisEditMenu.add_command(label="Cut",
command=self.__cut)
# コピー機能
self.__thisEditMenu.add_command(label="Copy",
command=self.__copy)
# 貼り付け機能
self.__thisEditMenu.add_command(label="Paste",
command=self.__paste)
self.__thisMenuBar.add_cascade(label="Edit", menu=self.__thisEditMenu)
# メモ帳の説明を表示
self.__thisHelpMenu.add_command(label="About Notepad",
command=self.__showAbout)
self.__thisCommandMenu.add_command(label = "About Commands", command=self.__showCommand)
self.__thisMenuBar.add_cascade(label="Commands", menu=self.__thisCommandMenu)
self.__thisMenuBar.add_cascade(label="Help", menu=self.__thisHelpMenu)

各メニュー項目への機能実装

メニューの準備ができたら、次に各メニュー項目に実際の動作を実装していきます。このメモ帳に追加する機能の一覧は以下の通りです(もちろん、他の機能を自由に追加することも可能です)。

  • ファイルを開く
  • 新規ファイル作成
  • ファイルの保存
  • アプリケーションの終了
  • バージョン情報の表示
  • コマンド情報の表示
  • 切り取り
  • コピー
  • 貼り付け

上記の機能を実装するコードがこちらです。

def __quitApplication(self):
    self.__root.destroy()
    # exit()
def __showAbout(self):
    showinfo("About Notepad","Simple text editor like notepad using Python")
def __showCommand(self):
    showinfo("Notepad", "Just Another TextPad \n Copyright \n with BSD license you can use it'")
def __openFile(self):
    self.__file = askopenfilename(defaultextension=".txt", filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
    if self.__file == "":
        # 開くファイルがない場合
        self.__file = None
    else:
        # ファイルを開いてウィンドウタイトルを設定
        self.__root.title(os.path.basename(self.__file) + " - Notepad")
        self.__thisTextArea.delete(1.0,END)
        file = open(self.__file,"r")
        self.__thisTextArea.insert(1.0,file.read())
        file.close()
def __newFile(self):
    self.__root.title("Untitled Notepad")
    self.__file = None
    self.__thisTextArea.delete(1.0,END)
def __saveFile(self):
    if self.__file == None:
        # 名前を付けて保存
        self.__file = asksaveasfilename(initialfile='Untitled.txt', defaultextension=".txt", filetypes=[("All Files","*.*"), ("Text Documents","*.txt")])
        if self.__file == "":
            self.__file = None
        else:
            # ファイルへ書き込み
            file = open(self.__file,"w")
            file.write(self.__thisTextArea.get(1.0,END))
            file.close()
            # ウィンドウタイトルを変更
            self.__root.title(os.path.basename(self.__file) + " - Notepad")
    else:
        file = open(self.__file,"w")
        file.write(self.__thisTextArea.get(1.0,END))
        file.close()
def __cut(self):
    self.__thisTextArea.event_generate("<<Cut>>")
def __copy(self):
    self.__thisTextArea.event_generate("<<Copy>>")
def __paste(self):
    self.__thisTextArea.event_generate("<<Paste>>")

必要なパッケージのインポート、メニュー項目の追加、そして各機能の実装が完了しました。次に、Tkinterライブラリを使用したメモ帳風テキストエディタの完全なプログラムを見ていきましょう。

メモ帳アプリの完全なソースコード

# osライブラリをインポート
import os
# tkinterからすべてをインポート
from tkinter import *
# メッセージボックス用
from tkinter.messagebox import *
# ファイルダイアログ用
from tkinter.filedialog import *
class Notepad:
    # ルートウィジェットのセットアップ
    __root = Tk()
    __thisWidth = 500
    __thisHeight = 700
    __thisTextArea = Text(__root)
    __thisMenuBar = Menu(__root)
    __thisFileMenu = Menu(__thisMenuBar, tearoff=0)
    __thisEditMenu = Menu(__thisMenuBar, tearoff=0)
    __thisHelpMenu = Menu(__thisMenuBar, tearoff=0)
    __thisCommandMenu = Menu(__thisMenuBar, tearoff=0)
    # スクロールバーの追加
    __thisScrollBar = Scrollbar(__thisTextArea)
    __file = None
    def __init__(self,**kwargs):
        # アイコンの設定
        try:
            self.__root.wm_iconbitmap("Notepad.ico")
        except:
            pass
        # ウィンドウサイズの設定(デフォルトは300x300)
        try:
            self.__thisWidth = kwargs['width']
        except KeyError:
            pass
        try:
            self.__thisHeight = kwargs['height']
        except KeyError:
            pass
        # ウィンドウタイトル
        self.__root.title("Untitled-Notepad")
        # ウィンドウを画面中央に配置
        screenWidth = self.__root.winfo_screenwidth()
        screenHeight = self.__root.winfo_screenheight()
        left = (screenWidth / 2) - (self.__thisWidth / 2)
        top = (screenHeight / 2) - (self.__thisHeight /2)
        self.__root.geometry('%dx%d+%d+%d' % (self.__thisWidth, self.__thisHeight, left, top))
        # テキストエリアを自動的にリサイズ可能にする
        self.__root.grid_rowconfigure(0, weight=1)
        self.__root.grid_columnconfigure(0, weight=1)
        # コントロール(ウィジェット)の追加
        self.__thisTextArea.grid(sticky = N + E + S + W)
        # 新規ファイル
        self.__thisFileMenu.add_command(label="New",
        command=self.__newFile)
        # 既存ファイルを開く
        self.__thisFileMenu.add_command(label="Open",
        command=self.__openFile)
        # 現在のファイルを保存
        self.__thisFileMenu.add_command(label="Save",
        command=self.__saveFile)
        # 区切り線を追加
        self.__thisFileMenu.add_separator()
        self.__thisFileMenu.add_command(label="Exit",
        command=self.__quitApplication)
        self.__thisMenuBar.add_cascade(label="File", menu=self.__thisFileMenu)
        # 切り取り機能
        self.__thisEditMenu.add_command(label="Cut",
        command=self.__cut)
        # コピー機能
        self.__thisEditMenu.add_command(label="Copy",
        command=self.__copy)
        # 貼り付け機能
        self.__thisEditMenu.add_command(label="Paste",
        command=self.__paste)
        self.__thisMenuBar.add_cascade(label="Edit", menu=self.__thisEditMenu)
        # メモ帳の説明
        self.__thisHelpMenu.add_command(label="About Notepad",
        command=self.__showAbout)
        self.__thisCommandMenu.add_command(label = "About Commands", command=self.__showCommand)
        self.__thisMenuBar.add_cascade(label="Commands", menu=self.__thisCommandMenu)
        self.__thisMenuBar.add_cascade(label="Help", menu=self.__thisHelpMenu)
        self.__root.config(menu=self.__thisMenuBar)
        self.__thisScrollBar.pack(side=RIGHT,fill=Y)
        # スクロールバーがコンテンツに応じて自動調整される
        self.__thisScrollBar.config(command=self.__thisTextArea.yview)
        self.__thisTextArea.config(yscrollcommand=self.__thisScrollBar.set)
    def __quitApplication(self):
        self.__root.destroy()
        # exit()
    def __showAbout(self):
        showinfo("About Notepad","Simple text editor like notepad using Python")
    def __showCommand(self):
        showinfo("Notepad", "Just Another TextPad \n Copyright \n with BSD license you can use it'")
    def __openFile(self):
        self.__file = askopenfilename(defaultextension=".txt", filetypes=[("All Files","*.*"),("Text Documents","*.txt")])
        if self.__file == "":
            # 開くファイルがない場合
            self.__file = None
        else:
            # ファイルを開き、ウィンドウタイトルを設定
            self.__root.title(os.path.basename(self.__file) + " - Notepad")
            self.__thisTextArea.delete(1.0,END)
            file = open(self.__file,"r")
            self.__thisTextArea.insert(1.0,file.read())
            file.close()
    def __newFile(self):
        self.__root.title("Untitled Notepad")
        self.__file = None
        self.__thisTextArea.delete(1.0,END)
    def __saveFile(self):
        if self.__file == None:
            # 名前を付けて保存
            self.__file = asksaveasfilename(initialfile='Untitled.txt', defaultextension=".txt", filetypes=[("All Files","*.*"), ("Text Documents","*.txt")])
            if self.__file == "":
                self.__file = None
            else:
                # ファイルへ書き込み
                file = open(self.__file,"w")
                file.write(self.__thisTextArea.get(1.0,END))
                file.close()
                # ウィンドウタイトルを変更
                self.__root.title(os.path.basename(self.__file) + " - Notepad")
        else:
            file = open(self.__file,"w")
            file.write(self.__thisTextArea.get(1.0,END))
            file.close()
    def __cut(self):
        self.__thisTextArea.event_generate("<<Cut>>")
    def __copy(self):
        self.__thisTextArea.event_generate("<<Copy>>")
    def __paste(self):
        self.__thisTextArea.event_generate("<<Paste>>")
    def run(self):
        # メインアプリケーションを実行
        self.__root.mainloop()
# アプリケーションの起動
notepad = Notepad(width=600,height=400)
notepad.run()

実行結果

上記のプログラムを実行すると、ポップアップ形式のメモ帳テキストエディタが起動します。

このメモ帳では、テキストの入力・保存はもちろん、保存したファイル(またはその他のファイル)を開くこともできます。さらに、開いたファイルの内容に対して切り取り・コピー・貼り付けといった編集操作も自由に行えます。作成したメモ帳のすべてのメニュー項目を実際に試してみてください。

まとめ

本記事では、Pythonの標準GUIライブラリであるTkinterを使って、ファイル操作やクリップボード編集などの基本機能を備えたメモ帳アプリを構築する手順を解説しました。クラス設計やイベント駆動の仕組みを学ぶ絶好の題材なので、ぜひ自分なりにカスタマイズしながら理解を深めてみてください。

  1. Pythonで作るWebサイトブロッカー ― 業務時間中にSNSへのアクセスを自動遮断する方法

    大手IT企業で働いたことがある方なら、FacebookやYouTube、InstagramといったSNS系のWebサイトが社内からアクセスできないよう制限されていることに気づいた経験があるかもしれません。こうした制限は、サードパーティ製アプリに頼らなくても実現できます。自分専用のオリジナルツールを作れば、好きなWebサイトを自由にブロックできるのです。しかもPythonでWebサイトブロッカーを開発するのは、それほど難しいことではありません。この記事では、指定したWebサイトをブロックするPythonスクリプトの作り方を解説します。前提条件Python 3.x がインストールされていることPy

  2. 【Python】Tkinterで作るカラーゲーム – 30秒で文字の色を当てるGUIゲーム開発

    GUIアプリケーションの開発において、Pythonの標準ライブラリ「Tkinter」は非常に人気が高く、初心者でも扱いやすいツールです。追加のインストール作業なしに使えるため、Tkinterを活用すればシンプルなGUIゲームでも手軽に開発できます。 この記事では、Tkinterを使った「カラーゲーム」の作り方を紹介します。このゲームでは、画面に表示される単語の文字色をプレイヤーが入力し、正解するたびにスコアが1点ずつ加算されます。制限時間は30秒で、使用される色は赤(Red)、青(Blue)、緑(Green)、ピンク(Pink)、黒(Black)、黄(Yellow)、オレンジ(Orange)、