-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path02-listbox_extra.py
More file actions
161 lines (146 loc) · 11.1 KB
/
02-listbox_extra.py
File metadata and controls
161 lines (146 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# Дополнительное задание к уроку "Повторение tkinter, Scrollbar и Listbox"
# Задача: добавить к основному домашнему заданию функцию
# записи данных в файл из Listbox
# Окно сделано в виде класса, наследованного от tkinter.Tk
# Также добавлена функция чтения данных из файла в Listbox,
# если этот файл уже был создан.
# При чтении данных из файла, программа спросит, очистить ли перед этим Listbox.
# Наконец, при записи данных в файл программа покажет его путь,
# и спросит, надо ли запустить его на экране
# Импортируем tkinter и messagebox
import tkinter as tk
import tkinter.messagebox as mb
# Также метод из os на получения расположения скрипта
from os import getcwd
# Создаём класс окна, наследуем от tkinter.Tk
class ListboxFileWriter(tk.Tk):
# Файл, с которым мы будем работать, будет находиться по пути "путь_к_скрипту/ListboxWriter/generated.txt"
# Такой путь мы и запишем в отдельное поле
__file_path__ = getcwd() + "\\ListboxWriter\\generated.txt"
# Разделим создание виджетов по функциям.
# Сначала создадим Listbox и полосы прокрутки к нему
def createBoxAndScrolls(self):
# В объявлении виджетов ставим ключевое слово self вместо названия переменной окна,
# так как мы сейчас типа находимся внутри этого окна 0_0
self.scrollY = tk.Scrollbar(self, orient='vertical') # Одна полоса вертикальная
# Используем параметры rowspan/columnspan и sticky,
# чтобы полосы покрывали всё пространство под и слева от Listbox'а
self.scrollY.grid(column=1, row=1, rowspan=5, sticky='ns')
self.scrollX = tk.Scrollbar(self, orient='horizontal') # И другая полоса горизонтальная
self.scrollX.grid(column=2, row=6, sticky='ew')
# Создаём сам Listbox, украшаем его, привязываем полосы прокрутки и делаем расположение
self.listbox = tk.Listbox(self, font='Helvetica', bg='black', fg='lightskyblue', yscrollcommand=self.scrollY.set, xscrollcommand=self.scrollX.set)
self.listbox.grid(row=1, column=2, rowspan=5, sticky='nsew')
# А теперь наоборот, к полосам привязываем Listbox
self.scrollY.config(command=self.listbox.yview)
self.scrollX.config(command=self.listbox.xview)
# Теперь функция создания поля ввода
def createEntry(self):
self.entry = tk.Entry(self)
self.entry.grid(row=1, column=3, sticky='ew')
# Перед тем, как создать кнопки, напишем для них функции
# Первые две повторяем из основного д/з, только не забываем использовать ключевое слово self
def __append_item_to_listbox__(self):
entry_text = self.entry.get()
# Если поле ввода пустое, не добавляем элемент в Listbox
if len(entry_text) == 0:
mb.showerror("ОШИБКА", "Не удалось получить введённые данные!")
return
self.listbox.insert('end', entry_text)
self.entry.delete(0, 'end')
def __delete_item_from_listbox__(self):
try:
select = self.listbox.curselection()
self.listbox.delete(select)
except tk.TclError:
mb.showerror("ОШИБКА!", "Вы не выбрали элемент для удаления!")
# Сделаем функцию, которая будет запускать сгенерированный файл
def ___launch_file___(self):
# Только здесь нам понадобится метод запуска файла из os
# Импортируем его локально
from os import startfile
# Запускаем файл)))
startfile(self.__file_path__)
# Ну а теперь напишем функцию для записи элементов Listbox'a в файл
def __write_items_to_file__(self):
# Локально импортируем метод создания папки из os
from os import mkdir
# И метод на проверку существования пути из os.path
from os.path import exists
# При записи данных в файл мы также должны предусмотреть ту ситуацию,
# в которой ни файла, ни даже папки с ним не будет создано
# (а такое будет, если кто-то захочет запустить скрипт у себя на компьютере в первый раз)
# В случае отсутствия файла или папки вылезет FileNotFoundError, в блоке его обработки создадим папку, если даже её нет,
# перевызовем функцию, и open уже сам создаст файл, дай ему только существующую папку
try:
# Открываем файл функцией open
file = open(self.__file_path__, "w") # Открываем файл в режиме записи (w)
# Делаем пробег по элементам Listbox'а, метод нашёл на StackOverflow
for i, listbox_entry in enumerate(self.listbox.get(0, 'end')):
# Записываем каждый в файл отдельной строкой
file.write(str(listbox_entry))
# Пишем перенос строки
file.write("\n")
mb.showinfo("ГОТОВО", "Все данные из Listbox'а успешно записаны в локальный файл! \nПуть к файлу: " + self.__file_path__)
# Спрашиваем у пользователя, запустить ли файл на экране
if mb.askyesno("ПРИМЕЧАНИЕ", "Открыть файл?"):
# Если да, вызываем ранее написанную функцию
self.___launch_file___()
file.close()
# Если вылезает исключение
except FileNotFoundError:
# Проверяем наличие папки ListboxWriter функцией os.exists
if not exists(getcwd() + "\\ListboxWriter\\"):
# Если её нет, создаём её функцией os.mkdir
mkdir(getcwd() + "\\ListboxWriter\\")
# Вызываем функцию ещё раз
self.__write_items_to_file__()
# Других вариантов развития события быть просто не может
else:
mb.showerror("ОШИБКА", "Не удалось найти файл. На этом наши полномочия всё(((")
# И напишем функцию для чтения элементов из файла и занесения их в Listbox
def __read_items_from_file__(self):
# Так же само обрабатываем FileNotFoundError
try:
# На этот раз открываем файл в режиме чтения (r)
file = open(self.__file_path__, "r")
# Получаем список всех строк файла методом readlines
lines = file.readlines()
# Вызываем YesNo окно, спрашиваем у пользователя, опустошить ли Listbox
if mb.askyesno("ПРИМЕЧАНИЕ", "Очистить ли Listbox перед внесением в него данных из файла"):
self.listbox.delete(0, 'end')
# Циклом по списку строк вставляем их в Listbox
for item in lines:
self.listbox.insert('end', item)
file.close()
except FileNotFoundError:
# Здесь просто вызываем ошибку, так как перед тем, как использовать эту функцию,
# пользователь должен был хотя бы один раз произвести запись в файл
mb.showError("ОШИБКА", "Вы ещё ни разу не создавали файл, или же удалили его. Не удалось прочитать данные из файла!")
# Ну и теперь создадим сами кнопки с соответствующими функциями
def createButtons(self):
self.button_append = tk.Button(self, text="Добавить", command=self.__append_item_to_listbox__)
self.button_append.grid(row=2, column=3, sticky='nsew')
self.button_delete = tk.Button(self, text="Удалить", command=self.__delete_item_from_listbox__)
self.button_delete.grid(row=3, column=3, sticky='nsew')
self.button_write = tk.Button(self, text="Записать в файл", command=self.__write_items_to_file__)
self.button_write.grid(row=4, column=3, sticky='nsew')
self.button_read = tk.Button(self, text="Прочитать из файла", command=self.__read_items_from_file__)
self.button_read.grid(row=5, column=3, sticky='nsew')
# И наконец, в конструкторе вызовем __init__ суперкласса,
# укажем одинаковые минимальные и максимальные размеры, чтобы они были неизменными.
# Укажем заголовок и начальные размеры, и в завершение создадим все виджеты функциями
def __init__(self):
tk.Tk.__init__(self)
self.minsize(width=330, height=215)
self.maxsize(width=330, height=215)
self.title("ListboxFileWriter")
self.geometry("330x215")
self.createBoxAndScrolls()
self.createEntry()
self.createButtons()
self.mainloop()
# Наконец, дописываем запуск программы, просто создаём окно
if __name__ == "__main__":
main_window = ListboxFileWriter()
# Спасибо за внимание)))