Note taker with Python and tkinter

Here’s a post describing the note-taking app:

Tired of cluttered note apps? Here’s a clean, focused solution.

This simple desktop app, built with Python, helps you organize your thoughts. Write your notes L in a distraction-free editor.

It’s focused writing and clean formatting, simplified.

import tkinter as tk
import os
from tkinter import simpledialog, messagebox
from PIL import Image, ImageTk
from ttkthemes import ThemedTk

# my own modules
from codex.binding import binding
from codex.window import window


class Win:
    def __init__(self, title, version, folder, extension):
        self.extension = extension
        self.letter_size = 14  # Adjusted for better default readability
        self.root = ThemedTk(theme="arc")  # Using a modern theme
        self.filename = ""
        self.folder = folder
        self.root.title(f"{title} v.{version}")
        self.root.geometry("800x600") # Set a default size

        window(self)
        binding(self)
        self.define_menu()
        self.menu_voices()
        self.showlistitems()

    def define_menu(self):
        self.menubar = tk.Menu(self.root)
        self.root.config(menu=self.menubar)

    def change_extension(self, ext):
        self.extension = ext
        self.showlistitems()

    def menu_voices(self):
        voices = [
            ["About", lambda: messagebox.showinfo("Credits", "pythonprogramming.altervista.org \nv.3.0.0", parent=self.root)],
            ["Blog", lambda: os.startfile("https://pythonprogramming.altervista.org/wp-admin")],
            ["PNG", lambda: self.change_extension(".png")]
        ]
        for v in voices:
            self.menubar.add_command(label=v[0], command=v[1])

    def save(self):
        if self.filename:
            try:
                with open(os.path.join(self.folder, self.filename), "w", encoding="utf-8") as file:
                    file.write(self._text.get("1.0", tk.END))
            except Exception as e:
                messagebox.showerror("Error", f"Failed to save file: {e}")
        else:
            messagebox.showwarning("Warning", "No file selected.")

    def delete(self):
        if self.filename:
            if messagebox.askyesno("Confirm Delete", f"Are you sure you want to delete {self.filename}?"):
                try:
                    os.remove(os.path.join(self.folder, self.filename))
                    self._text.delete("1.0", tk.END)
                    self.filename = ""
                    self.lb_under_banner.config(text="")
                    self.showlistitems()
                except Exception as e:
                    messagebox.showerror("Error", f"Failed to delete file: {e}")
        else:
            messagebox.showwarning("Warning", "No file selected to delete.")

    def input_filename(self, title="New File", sentence="Enter a name for the new file (without extension):"):
        name = simpledialog.askstring(title, sentence, parent=self.root)
        return f"{name}{self.extension}" if name else ""

    def run(self, evt):
        if self.filename:
            file_path = os.path.join(self.folder, self.filename)
            try:
                os.startfile(file_path)
            except Exception as e:
                messagebox.showerror("Error", f"Could not open file: {e}")

    def open_folder(self):
        os.startfile(self.folder)

    def quit(self, evt=None):
        if messagebox.askyesno("Quit", "Do you want to save your changes before quitting?"):
            self.save()
        self.root.destroy()

    def newfile(self, evt=None):
        new_filename = self.input_filename()
        if new_filename:
            try:
                with open(os.path.join(self.folder, new_filename), "w") as file:
                    pass
                self.showlistitems()
                # Automatically select the new file
                for i, item in enumerate(self._lbx.get(0, tk.END)):
                    if item == new_filename:
                        self._lbx.selection_set(i)
                        self.showcontent(None)
                        break
            except Exception as e:
                messagebox.showerror("Error", f"Could not create file: {e}")

    def showlistitems(self):
        self._lbx.delete(0, tk.END)
        try:
            list_of_items = [f for f in os.listdir(self.folder) if f.lower().endswith(self.extension.lower())]
            list_of_items.sort(reverse=True)
            for item in list_of_items:
                self._lbx.insert(tk.END, item)
        except Exception as e:
            messagebox.showerror("Error", f"Could not read directory: {e}")

    def write_in_text(self, text):
        self._text.delete("1.0", tk.END)
        self._text.insert(tk.END, text)

    def join(self):
        # Implementation for joining files can be refined or kept as is
        pass

    def showcontent(self, evt):
        selection_indices = self._lbx.curselection()
        if not selection_indices:
            return

        selected_index = selection_indices[0]
        self.filename = self._lbx.get(selected_index)
        self.lb_under_banner.config(text=f"Selected: {self.filename}")

        if self.filename.lower().endswith((".png", ".jpg", ".jpeg", ".gif")):
            # Image handling can be improved
            messagebox.showinfo("Image", "Image display can be implemented here.")
        else:
            try:
                with open(os.path.join(self.folder, self.filename), "r", encoding="utf-8") as file:
                    self.write_in_text(file.read())
            except Exception as e:
                messagebox.showerror("Error", f"Could not read file: {e}")

    def clear(self):
        self._text.delete("1.0", tk.END)

    def copy(self):
        self.root.clipboard_clear()
        self.root.clipboard_append(self._text.get("1.0", "end-1c"))

def create_chapters_folder(folder):
    if not os.path.exists(folder):
        os.makedirs(folder)
        print(f"Created folder: {folder}")

if __name__ == "__main__":
    FOLDER_FOR_FILES = "snippets"
    FILE_EXTENSION = ".txt"
    create_chapters_folder(FOLDER_FOR_FILES)
    ver = "3.0.0"
    win = Win("ModernNotes", ver, folder=FOLDER_FOR_FILES, extension=FILE_EXTENSION)
    win.root.mainloop()


Subscribe to the newsletter for updates
Tkinter templates

Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Claude's Games

Arkanoid
Platform 2d

1. Memory game

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Advertisement