Код ниже.
import sys import logging logging.basicConfig(level=logging.INFO) L, A = 500, 500 if not sys.version.startswith('3.1'): from tkinter import * from tkinter import filedialog from tkinter import messagebox from tkinter import ttk from os import path else: raise ValueError('Python version is not supported') class StatusBar: """ строка состояния tkinter """ def __init__(self, master=None, init_text=None): self.status = Label(master, text=init_text, bd=1, anchor=E, relief=SUNKEN) self.status.pack(side=BOTTOM, fill=X) def set_text(self, text): self.status['text'] = text def append_text(self, text): self.status['text'] += ' | ' + text def get_text(self): return self.status['text'] class MainWindow(Tk): """ Показывает статус бар """ def __init__(self, title): super().__init__() self.ext = '' self.title(title) self.minsize(L, A) self.geometry("%dx%d" % (L, A)) self.notebook = ttk.Notebook(self) self.tab = ttk.Frame(self.notebook) self.tab.pack() self.status_bar = StatusBar(self.tab, "Жду пока ты начнешь писать...") self.other = ttk.Frame(self.notebook) self.other.pack() self.create_interface(self.tab) self.bind("<Control-n>", self.new_tab) self.bind("<Delete>", self.delete_last_tab) self.mainloop() def create_interface(self, tab=None): self.tab = tab self.frame = ttk.Frame(self.tab) self.frame.pack() self.frame_y = ttk.Frame(self.tab) self.frame_z = ttk.Frame(self.tab) self.frame_z.pack() self.frame_y.pack(fill=BOTH, expand=1) self.open = Button(self.frame, text="Открыть", width=15, relief=FLAT, command=self.openfile) self.open.pack(side=LEFT) self.save = Button(self.frame, text="Cохранить", width=15, relief=FLAT, command=self.save) self.save.pack(side=LEFT) self.new_tab_bt = Button(self.frame, text="Создать заметку", width=15, relief=FLAT, command=self.new_tab) self.new_tab_bt.pack(side=LEFT) self.help_bt = Button(self.frame, text="Помощь", relief=FLAT, command=self.help) self.help_bt.pack(side=LEFT) # текстовое поле для пользователя scroll_text = Scrollbar(self.frame_y) scroll_text.pack(side=RIGHT, fill=Y, pady=5) self.text = Text(self.frame_y, width=80, yscrollcommand=scroll_text.set, wrap=WORD, undo=True) # сочетания клавиш self.text.bind("<KeyPress>", self.count_all) self.text.bind("<Control-s>", self.save) # Нажатие Ctrl + S будет сохранить файл как self.text.bind("<Control-o>", self.openfile) # Нажатие CTRL+O будет открыть файл self.text.bind("<Control-a>", self.select_all) # scroll_text.config(command=self.text.yview) self.text.pack(fill=BOTH, expand=1) self.notebook.add(self.tab, text="No name") self.notebook.pack(expand=1, fill="both") def new_tab(self, e=None): """ Создает новую вкладку :c """ master = self.other master = ttk.Frame(self.notebook) master.pack() self.create_interface(master) tabs = self.notebook.tabs() tabs_l = [self.notebook.index(tab) for tab in tabs] self.notebook.select(tabs_l[-1]) def delete_last_tab(self, e=None): """ чтобы закрыть последнюю вкладку """ tabs = self.notebook.tabs() tabs_l = [self.notebook.index(tab) for tab in tabs] if len(tabs_l) > 1: self.notebook.forget(tabs_l[-1]) def openfile(self, e=None): """ Открыть файл """ fname = filedialog.askopenfilename() self.clear() if fname: idx = self.notebook.index(self.notebook.select()) self.notebook.forget(idx) name = fname[::-1] name = name[:name.find('/'):] name = name[::-1] self.ext = name[name.find('.')::] name = name[:name.find('.'):] self.notebook.add(self.tab, text=name) try: with open(fname, encoding='utf-8') as f: lines = f.readlines() for line, content in enumerate(lines): self.text.insert(float(line) + 1, content) except UnicodeDecodeError as e: logging.info("Ошибка%s" % e) logging.info("жаль но вы допустили ошибочку..") with open(fname) as f: lines = f.readlines() for line, content in enumerate(lines): self.text.insert(float(line) + 1, content) except FileNotFoundError: logging.info("Файл% S не найден" % fname) self.count_all() self.notebook.select(idx) def save_as(self, e=None): """ Функция, чтобы сохранить как открытие окна просит пользователя сообщить имя конечного файла """ txt = self.text.get(1.0, END) fname = filedialog.asksaveasfilename(filetypes=[("Text Files", "txt")]) if fname: idx = self.notebook.index(self.notebook.select()) self.notebook.forget(idx) name = fname[::-1] name = name[:name.find('/'):] name = name[:name.find('.'):-1] self.notebook.add(self.tab, text=name) with open(fname, 'w+') as f: f.write(txt) else: messagebox.showinfo("Уведомление", "Вы должны поставить имя") def save(self, e=None): """ Если файл уже существует в папке с тем же именем, это сохранить но, за исключением, как это называется """ idx = self.notebook.index(self.notebook.select()) fname = self.notebook.tab(idx)['text'] + self.ext if path.isfile(fname): with open(fname, "w") as f: f.write(self.text.get(1.0, END)) else: self.save_as() def count_words(self): """ счета слов """ txt = self.text.get(1.0, END) if len(txt) >= 1: txt = txt.split() self.status_bar.set_text("слова: " + str(len(txt))) def count_chars(self): """ счет символов""" txt = self.text.get(1.0, END) if len(txt) >= 1: txt = list(txt) self.status_bar.append_text("Символов: " + str(len(txt))) def count_lines(self): """ счета строк """ if len(self.text.get(1.0, END)) >= 1: self.status_bar.append_text("строк: " + str(int(self.text.index('end').split('.')[0])-1)) def count_all(self, e=None): """ Метод, который выполняет другие три счетчика методы""" self.count_words() self.count_chars() self.count_lines() def clear(self): """ Этот метод ясно только по имени... """ self.text.delete(1.0, END) def select_all(self, e=None): """ чтобы выбрать все c клавиатуры ctrl+a :x """ self.text.tag_add(SEL, "1.0", END) self.text.mark_set(INSERT, "1.0") self.text.see(INSERT) return 'break' @staticmethod def help(): """ Окно помощи """ help_window = Toplevel() help_window.title('Помощь') help_window.minsize(200, 130) help_window.resizable(0, 0) Message(help_window, text="Чтобы удалить заметку нажмите: <Delete>\n\nСоздать: <Ctrl+N>\ \n\nRAZRAB MARIK ", justify=LEFT).pack(pady=15) btn_close = Button(help_window, text="Закрыть", command=help_window.destroy) btn_close.pack(fill=X) MainWindow('Заметки.')