🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

[ก๊อปวางแล้วใช้ได้เลย] มาสร้างแอป Notepad ง่ายๆ ด้วย Python กันเถอะ! (พร้อมฟังก์ชันบันทึกไฟล์)

"อยากลองเขียนโปรแกรมสร้างอะไรสักอย่างที่จับต้องได้จัง!"

สำหรับคุณที่กำลังคิดแบบนั้นอยู่ บทความนี้จะอธิบายวิธีสร้าง "แอป Notepad" ง่ายๆ ในแบบของคุณเอง ที่สามารถพิมพ์ข้อความและบันทึกเป็นไฟล์ได้ด้วยภาษา Python ในแบบที่เข้าใจง่ายที่สุดในโลกครับ

สวัสดีครับ! ผมเป็นนักพัฒนาเว็บที่เรียนรู้ด้วยตัวเองโดยใช้ AI ช่วย ซึ่งเมื่อไม่กี่เดือนก่อนยังไม่มีความรู้ด้านโปรแกรมมิ่งเลยแม้แต่น้อย ตอนแรกผมก็อยู่ในระดับที่ว่า "บันทึกไฟล์เหรอ? มันคือคาถาอะไรหรือเปล่า?" (555) เพราะอย่างนั้น ผมเลยตั้งใจจะใช้ศัพท์เทคนิคให้น้อยที่สุด แล้วมาแชร์จุดที่ผมเคยติดขัดสมัยเป็นมือใหม่เหมือนกันไปพร้อมๆ กับทุกคนครับ

เป้าหมายของบทความนี้มีเพียงหนึ่งเดียว นั่นคือ เพื่อให้คุณได้สัมผัสกับความรู้สึกประทับใจที่ว่า "โปรแกรมที่ฉันสร้างเองมันทำงานได้!" ครับ ด้วยเหตุนี้ เรื่องยากๆ เราจะเก็บไว้ทีหลัง! ก่อนอื่น มาลองสัมผัสกับโค้ดที่สมบูรณ์แบบที่แค่ก๊อปวางก็ทำงานได้กันเลย!


ขั้นตอนที่ 1: มาลองรันกันเลย! โค้ดที่สมบูรณ์อยู่ตรงนี้แล้ว

สิบปากว่าไม่เท่าตาเห็นครับ ก่อนอื่นให้คัดลอกโค้ดด้านล่างทั้งหมด ไปบันทึกเป็นไฟล์ชื่อ memo_app.py แล้วลองรันดูได้เลยครับ สำหรับใครที่ยังไม่มีสภาพแวดล้อมสำหรับรัน Python ก็เตรียมให้พร้อมก่อนนะครับ

ถ้าคุณคิดว่า "เอ๊ะ, นี่โค้ดสำเร็จรูปแล้วเหรอ?" "แล้วคำอธิบายล่ะ?" คุณคิดถูกแล้วครับ! การได้สัมผัสประสบการณ์ว่า "มันทำงานได้" ก่อน คือเคล็ดลับที่สนุกที่สุดในการเรียนเขียนโปรแกรมครับ


import tkinter as tk
import tkinter.filedialog as filedialog

def save_file():
    """ฟังก์ชันสำหรับบันทึกไฟล์"""
    file_path = filedialog.asksaveasfilename(
        defaultextension=".txt",
        filetypes=[("ไฟล์ข้อความ", "*.txt"), ("ไฟล์ทั้งหมด", "*.*")]
    )
    if not file_path:
        return
    try:
        with open(file_path, 'w', encoding='utf-8') as file:
            text_content = text_area.get(1.0, tk.END)
            file.write(text_content)
    except Exception as e:
        print(f"เกิดข้อผิดพลาด: {e}")

def open_file():
    """ฟังก์ชันสำหรับเปิดไฟล์"""
    file_path = filedialog.askopenfilename(
        filetypes=[("ไฟล์ข้อความ", "*.txt"), ("ไฟล์ทั้งหมด", "*.*")]
    )
    if not file_path:
        return
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            text_content = file.read()
            text_area.delete(1.0, tk.END)
            text_area.insert(tk.END, text_content)
    except Exception as e:
        print(f"เกิดข้อผิดพลาด: {e}")

# สร้างหน้าต่างหลัก
window = tk.Tk()
window.title("Notepad แบบง่าย")
window.geometry("600x400")

# สร้างพื้นที่สำหรับป้อนข้อความ
text_area = tk.Text(window, wrap=tk.WORD)
text_area.pack(expand=True, fill=tk.BOTH)

# สร้างแถบเมนู
menu_bar = tk.Menu(window)
window.config(menu=menu_bar)

# สร้างเมนู "ไฟล์"
file_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="ไฟล์", menu=file_menu)
file_menu.add_command(label="เปิด...", command=open_file)
file_menu.add_command(label="บันทึกเป็น...", command=save_file)
file_menu.add_separator()
file_menu.add_command(label="ออก", command=window.quit)

# แสดงหน้าต่าง
window.mainloop()
    

เป็นยังไงบ้างครับ? ถ้ามีหน้าต่างแบบนี้ปรากฏขึ้นมาก็ถือว่าสำเร็จอย่างงดงาม!

ภาพหน้าจอของแอป Notepad แบบง่ายที่สร้างด้วย Python ที่ด้านบนของหน้าต่างมีเมนู 'ไฟล์' และตรงกลางมีพื้นที่สำหรับป้อนข้อความขนาดใหญ่

ลองพิมพ์ข้อความ หรือเลือก "บันทึกเป็น..." กับ "เปิด..." จากเมนูดูสิครับ ไม่รู้สึกประทับใจหน่อยเหรอที่มันทำงานเป็นโปรแกรม Notepad ได้จริงๆ?


ขั้นตอนที่ 2: สำรวจโค้ด! มาแอบดูการทำงานของมันกัน

หลังจากที่ได้สัมผัสประสบการณ์ "มันทำงานได้!" กันไปแล้ว ต่อไปเรามาสำรวจกันว่า "ทำไมมันถึงทำงานได้?" กันดีกว่าครับ เราจะมาแยกส่วนโค้ดเมื่อสักครู่ออกเป็นชิ้นๆ แล้วอธิบายหน้าที่ของแต่ละส่วนกัน

① เตรียมกล่องเครื่องมือวิเศษ (import)

โค้ดสองบรรทัดแรกเปรียบเสมือนคาถาสำหรับเรียก "เครื่องมืออำนวยความสะดวก" ที่เราจะใช้เข้ามาใน Python ครับ


import tkinter as tk
import tkinter.filedialog as filedialog
    

② สร้างฐานรากของแอป (การสร้างหน้าต่าง)

ต่อไป เราจะสร้างหน้าต่างหลักของแอปกันครับ ถ้าเปรียบกับการสร้างบ้าน ส่วนนี้ก็คือการวางฐานรากและขึ้นโครงสร้างนั่นเอง


# สร้างหน้าต่างหลัก
window = tk.Tk()
window.title("Notepad แบบง่าย")
window.geometry("600x400")

# ... (โค้ดส่วนอื่น) ...

# แสดงหน้าต่าง
window.mainloop()
    

③ เตรียมพื้นที่สำหรับเขียน (พื้นที่ข้อความ)

ไหนๆ ก็เป็น Notepad แล้ว ก็ต้องมีพื้นที่สำหรับพิมพ์ข้อความใช่ไหมครับ ส่วนนี้แหละครับที่ทำหน้าที่นั้น


# สร้างพื้นที่สำหรับป้อนข้อความ
text_area = tk.Text(window, wrap=tk.WORD)
text_area.pack(expand=True, fill=tk.BOTH)
    

④ สร้างกล่องรวบรวมคำสั่ง (ฟังก์ชัน)

ในที่สุดก็มาถึงหัวใจของแอปนี้ นั่นคือการอธิบายกระบวนการทำงานเฉพาะอย่าง "การเปิดไฟล์" และ "การบันทึกไฟล์" ครับ กระบวนการเหล่านี้ถูกกำหนดไว้ในรูปแบบของ ฟังก์ชัน ซึ่งเปรียบเสมือน "กล่องที่มีประโยชน์สำหรับรวบรวมคำสั่ง" ครับ

การบันทึกไฟล์: ฟังก์ชัน `save_file()`


def save_file():
    """ฟังก์ชันสำหรับบันทึกไฟล์"""
    file_path = filedialog.asksaveasfilename(
        defaultextension=".txt",
        filetypes=[("ไฟล์ข้อความ", "*.txt"), ("ไฟล์ทั้งหมด", "*.*")]
    )
    if not file_path:
        return
    try:
        with open(file_path, 'w', encoding='utf-8') as file:
            text_content = text_area.get(1.0, tk.END)
            file.write(text_content)
    except Exception as e:
        print(f"เกิดข้อผิดพลาด: {e}")
    

โค้ดส่วนนี้มีประเด็นสำคัญอยู่มากมายครับ

  1. `filedialog.asksaveasfilename(...)`: นี่คือคำสั่งสำหรับแสดงกล่องโต้ตอบ "บันทึกเป็น" ครับ ตำแหน่งที่จัดเก็บไฟล์ที่ผู้ใช้เลือก (หรือที่อยู่ของไฟล์) จะถูกเก็บไว้ในตัวแปรที่ชื่อ `file_path` ครับ
  2. `if not file_path: return`: หากผู้ใช้กดปุ่ม "ยกเลิก" ในกล่องโต้ตอบ `file_path` จะมีค่าเป็นว่าง ในกรณีนั้น บรรทัดสำคัญนี้จะทำให้ฟังก์ชันสิ้นสุดการทำงานโดยไม่ทำอะไรเลย
  3. `with open(file_path, 'w', encoding='utf-8') as file:`: นี่คือหัวใจของการจัดการไฟล์!
    • `open()`: คำสั่งสำหรับเปิดไฟล์ตามตำแหน่งที่ระบุในโหมดที่กำหนด
    • `'w'`: หมายถึงโหมด `write` (เขียน) ถ้าไม่มีไฟล์อยู่จะสร้างขึ้นมาใหม่ ถ้ามีอยู่แล้วจะเขียนทับ
    • `encoding='utf-8'`: เป็นคาถาที่สำคัญสุดๆ เพื่อป้องกันปัญหาตัวอักษรเพี้ยน (ภาษาต่างดาว) โดยระบุให้ใช้ "UTF-8" ซึ่งเป็นรูปแบบการเข้ารหัสตัวอักษรมาตรฐานที่สามารถจัดการกับภาษาเกือบทั้งหมดในโลกได้อย่างถูกต้อง ถ้าไม่เขียนบรรทัดนี้ อาจทำให้ภาษาไทยไม่สามารถบันทึกได้อย่างถูกต้องครับ
    • `with ... as file:`: การใช้ синтаксис นี้จะช่วยให้ไฟล์ถูกปิดโดยอัตโนมัติหลังจากที่การทำงานในบล็อกนี้เสร็จสิ้น การลืมปิดไฟล์อาจทำให้เกิดปัญหาเช่นหน่วยความจำรั่วไหลได้ ดังนั้นนี่จึงเป็นวิธีการเขียนที่ปลอดภัยและแนะนำเป็นอย่างยิ่งครับ (แนะนำในเอกสารทางการเช่นกัน)
  4. `text_area.get(1.0, tk.END)`: ใช้สำหรับดึงข้อความทั้งหมดที่ถูกป้อนเข้ามาในพื้นที่ข้อความ
  5. `file.write(text_content)`: ใช้สำหรับเขียนข้อความที่ดึงมาลงในไฟล์ที่เปิดอยู่

ในทำนองเดียวกัน ฟังก์ชัน `open_file()` ก็แค่ใช้ `'r'` (โหมด read: อ่าน) เพื่ออ่านเนื้อหาของไฟล์แล้วนำมาแสดงในพื้นที่ข้อความเท่านั้นเองครับ หลักการทำงานแทบจะเหมือนกันเลย!


ขั้นตอนที่ 3: ขั้นประยุกต์! มาดัดแปลงให้เป็น Notepad ในแบบของคุณกัน

เมื่อเข้าใจหลักการพื้นฐานแล้ว ต่อไปเรามาทำให้มันน่าสนใจยิ่งขึ้นกันเถอะ! แค่เพิ่มโค้ดนิดหน่อยก็สามารถติดตั้งฟังก์ชันที่มีประโยชน์ได้แล้วครับ

ตัวอย่างการดัดแปลง ①: ทำให้เป็นดีไซน์สไตล์โหมดมืด

โหมดมืดที่กำลังเป็นที่นิยมในปัจจุบัน มาลองเปลี่ยนดีไซน์ให้ถนอมสายตากันดูครับ แค่ระบุสีพื้นหลังและสีตัวอักษรในส่วนที่สร้าง `window` กับ `text_area` เท่านั้นเอง


# สร้างหน้าต่างหลัก
window = tk.Tk()
window.title("Notepad โหมดมืด")
window.geometry("600x400")
window.config(bg="#2d2d2d") # เพิ่มสีพื้นหลังของหน้าต่าง

# สร้างพื้นที่สำหรับป้อนข้อความ
text_area = tk.Text(
    window, 
    wrap=tk.WORD,
    bg="#1e1e1e",          # สีพื้นหลังของพื้นที่ข้อความ
    fg="#dcdcdc",          # สีตัวอักษร
    insertbackground="#ffffff" # สีของเคอร์เซอร์
)
text_area.pack(expand=True, fill=tk.BOTH)
    

เพียงเท่านี้ ก็ได้บรรยากาศที่ทันสมัยขึ้นมาทันทีเลยใช่ไหมล่ะครับ!


ตัวอย่างการดัดแปลง ②: เพิ่มคีย์ลัด

การเปิดเมนูทุกครั้งมันน่ารำคาญใช่ไหมครับ มาทำให้สามารถบันทึกด้วย "Ctrl + S" และเปิดด้วย "Ctrl + O" กันเถอะครับ ตอนที่เพิ่มรายการลงในเมนู ให้ระบุคีย์ลัดด้วย `accelerator` แล้วใช้ `window.bind` เพื่อเชื่อมโยงการทำงานของคีย์บอร์ดเข้ากับฟังก์ชัน

ก่อนอื่น ให้เปลี่ยนส่วนของการสร้างเมนูเป็นแบบนี้ครับ


# สร้างเมนู "ไฟล์"
file_menu = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="ไฟล์", menu=file_menu)
# ใช้ accelerator เพื่อแสดงคีย์ลัดเป็นคำใบ้
file_menu.add_command(label="เปิด...", command=open_file, accelerator="Ctrl+O")
file_menu.add_command(label="บันทึกเป็น...", command=save_file, accelerator="Ctrl+S")
file_menu.add_separator()
file_menu.add_command(label="ออก", command=window.quit)
    

จากนั้น ให้เพิ่มโค้ดสำหรับเชื่อมโยงการทำงานของคีย์เข้ากับฟังก์ชันไว้ก่อน `window.mainloop()` ครับ


# การผูกคีย์ลัด
# ใช้ lambda เพื่อรับอาร์กิวเมนต์ของอีเวนต์
window.bind("<Control-s>", lambda event: save_file())
window.bind("<Control-o>", lambda event: open_file())

# แสดงหน้าต่าง
window.mainloop()
    

เมธอด `bind` จะเรียกฟังก์ชันเมื่อเกิดอีเวนต์ขึ้น (ในกรณีนี้คือการกดคีย์) แต่ตอนนั้นมันจะส่งข้อมูลเกี่ยวกับอีเวนต์ (อ็อบเจกต์ `event`) มาเป็นอาร์กิวเมนต์ด้วย แต่ฟังก์ชัน `save_file` และ `open_file` ของเราถูกออกแบบมาให้ไม่รับอาร์กิวเมนต์ ดังนั้นเราจึงใช้ `lambda event:` เพื่อทำหน้าที่เป็นตัวกลางในการเพิกเฉยต่ออาร์กิวเมนต์และเรียกฟังก์ชันเป้าหมายแทน เป็นเทคนิคเล็กๆ น้อยๆ ที่ดีเลยใช่ไหมครับ!


ข้อควรระวัง (ไม้เท้ากันหมา)

การจัดการไฟล์เป็นส่วนที่มักเกิดข้อผิดพลาดที่ไม่คาดคิดได้ง่ายครับ ผมเองก็เคยจ้องหน้าจอข้อผิดพลาดแล้วปวดหัวมานับครั้งไม่ถ้วน... แค่รู้ข้อผิดพลาดที่พบบ่อยๆ ไว้ ก็ช่วยให้เราไม่ตื่นตระหนกได้แล้วครับ

ในโค้ดของเรา เราใช้บล็อก `try...except` เพื่อดักจับข้อผิดพลาด ดังนั้นต่อให้เกิดข้อผิดพลาดขึ้น แอปก็จะไม่แครช และจะมีข้อความแสดงข้อผิดพลาดปรากฏขึ้นในคอนโซลแทน นี่ก็เป็นอีกหนึ่งเทคนิคสำคัญในการสร้างโปรแกรมที่ปลอดภัยครับ


สรุป: ความสำเร็จเล็กๆ คือก้าวที่ยิ่งใหญ่สู่ขั้นต่อไป

お疲れ様でした!今回はPythonの`Tkinter`を使って、ファイル保存機能付きのシンプルなメモ帳アプリを作成しました。

コピペから始めて、その仕組みを理解し、最後は自分で改造するところまで体験していただけたでしょうか。「自分で書いたコードが、目に見える形で動く」という経験は、何物にも代えがたい喜びであり、プログラミング学習を続ける上で最高のモチベーションになります。

今回作ったアプリは、ほんの始まりに過ぎません。検索機能、文字数カウント、自動保存など、アイデア次第でいくらでも機能を追加できます。ぜひ、この記事を土台にして、あなただけのオリジナルアプリ開発に挑戦してみてください!

ไปยังขั้นตอนถัดไป

เมื่อเข้าใจพื้นฐานของแอป GUI แล้ว ต่อไปมาลองควบคุม "เวลา" กันดูไหมครับ? ในบทความหน้า เราจะอธิบายวิธีใช้โมดูล `time` ของ Python เพื่อสร้างแอปจับเวลาที่สามารถแจ้งเตือนเมื่อถึงเวลาที่กำหนด มาท้าทายตัวเองด้วยการสร้างเครื่องมือที่มีประโยชน์ในชีวิตประจำวันอย่างนาฬิกาปลุกหรือตัวจับเวลา Pomodoro กันเถอะ!

→ มาสร้างแอปจับเวลาด้วย Python กันเถอะ (โมดูล time)

ของแถม: โค้ด Python ฉบับสมบูรณ์ที่พร้อมใช้งาน

นี่คือโค้ด Python ฉบับสมบูรณ์เวอร์ชันสุดท้ายที่รวมเอาตัวอย่างการประยุกต์ใช้ดีไซน์สไตล์โหมดมืดและคีย์ลัดที่อธิบายไว้ในบทความนี้ทั้งหมดแล้วครับ แค่คัดลอกโค้ดนี้ไปใช้ ก็จะได้แอป Notepad ที่มีฟังก์ชันครบครันไปใช้ได้ทันที!

<?php
/*
นี่คือโค้ด Python ไม่ใช่ไฟล์ PHP ที่จะรันบนเว็บเซิร์ฟเวอร์
กรุณาเปลี่ยนนามสกุลเป็น .py แล้วรันด้วยตัวแปลภาษา Python
ตัวอย่าง: python your_file_name.py
*/
?>
import tkinter as tk
import tkinter.filedialog as filedialog

def save_file():
    """ฟังก์ชันสำหรับบันทึกไฟล์"""
    file_path = filedialog.asksaveasfilename(
        defaultextension=".txt",
        filetypes=[("ไฟล์ข้อความ", "*.txt"), ("ไฟล์ทั้งหมด", "*.*")]
    )
    if not file_path:
        return
    try:
        with open(file_path, 'w', encoding='utf-8') as file:
            text_content = text_area.get(1.0, tk.END)
            file.write(text_content)
    except Exception as e:
        # ตามหลักแล้วควรบันทึกใน로그หรือแจ้งผู้ใช้ผ่านไดอะล็อกจะดีกว่า
        print(f"เกิดข้อผิดพลาด: {e}")
        window.title(f"ข้อผิดพลาด: {e}")


def open_file():
    """ฟังก์ชันสำหรับเปิดไฟล์"""
    file_path = filedialog.askopenfilename(
        filetypes=[("ไฟล์ข้อความ", "*.txt"), ("ไฟล์ทั้งหมด", "*.*")]
    )
    if not file_path:
        return
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            text_content = file.read()
            text_area.delete(1.0, tk.END)
            text_area.insert(tk.END, text_content)
            window.title(f"Notepad - {file_path}")
    except Exception as e:
        print(f"เกิดข้อผิดพลาด: {e}")
        window.title(f"ข้อผิดพลาด: {e}")


# --- การตั้งค่า GUI ---

# สร้างหน้าต่างหลัก
window = tk.Tk()
window.title("Notepad ขั้นสูง")
window.geometry("800x600")
window.config(bg="#2d2d2d") # สีพื้นหลังของหน้าต่าง

# สร้างพื้นที่สำหรับป้อนข้อความ
text_area = tk.Text(
    window,
    wrap=tk.WORD,
    bg="#1e1e1e",          # สีพื้นหลังของพื้นที่ข้อความ
    fg="#dcdcdc",          # สีตัวอักษร
    insertbackground="#ffffff", # สีของเคอร์เซอร์ (สีขาวเพื่อให้มองเห็นง่าย)
    undo=True,             # เปิดใช้งานฟังก์ชัน Undo/Redo
    autoseparators=True
)
text_area.pack(expand=True, fill=tk.BOTH, padx=5, pady=5)


# สร้างแถบเมนู
menu_bar = tk.Menu(window)
window.config(menu=menu_bar)

# สร้างเมนู "ไฟล์"
file_menu = tk.Menu(menu_bar, tearoff=0, bg="#2d2d2d", fg="#dcdcdc")
menu_bar.add_cascade(label="ไฟล์", menu=file_menu)
file_menu.add_command(label="เปิด...", command=open_file, accelerator="Ctrl+O")
file_menu.add_command(label="บันทึกเป็น...", command=save_file, accelerator="Ctrl+S")
file_menu.add_separator()
file_menu.add_command(label="ออก", command=window.quit)

# การผูกคีย์ลัด (ใช้ lambda เพื่อเพิกเฉยต่ออาร์กิวเมนต์ของอีเวนต์)
window.bind("<Control-s>", lambda event: save_file())
window.bind("<Control-o>", lambda event: open_file())
window.bind("<Control-S>", lambda event: save_file()) # รองรับการกด Shift พร้อมกันด้วย
window.bind("<Control-O>", lambda event: open_file()) # รองรับการกด Shift พร้อมกันด้วย

# เริ่มลูปการแสดงผลของหน้าต่าง
window.mainloop()