Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.52/75: Рейтинг темы: голосов - 75, средняя оценка - 4.52
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533

Добавление нескольких файлов для последующего редактирования

03.09.2019, 12:20. Показов 15961. Ответов 158

Студворк — интернет-сервис помощи студентам
Доброго времени суток форумчане! Не так давно, благодаря знатокам из данного форума была написана (спасибо за всё) программа. Суть её в следующем: На диске лежат файлики в которых 20 строк, каждую десятую строку программа вставляет пустую строку, затем копирует содержимое 10-й строки, добавляет перед пустой строкой (проще говоря дублирует 10-ю строку), затем дублирует 11-ю и добавляет перед 11-й строкой (капец туфтология), наглядно это вот так:

Было:
7
8
9
10
11
12
13

Стало:
7
8
9
10
10

11
11
12
13

И так программка делает каждую 10-ю строку! Строк может быть уйма. Всё работает всё делится, как надо, вопрос таков:
Файлов которые нужно редактировать много, поэтому, я хотелось бы сделать, что-то типа добавления или запоминания нескольких файлов, а затем их сразу переделывать, что каждый раз не указывать файл заново. Файлы лежат в разных папках, поэтому забирать из корня не выйдет. Желательно сделать наглядно, чтобы я уже видел, какие файлики я добавил, а какие нет! Заранее спасибо за помощь!

Собственно и сама программа:
Python
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
from tkinter import *
from tkinter import ttk
import os
 
from tkinter import messagebox
from tkinter import filedialog
 
def update_the_label():
    lb0 = Label(window, text = "-")
 
def clicked_dialogOpen():
    global choosefile
    choosefile=filedialog.askopenfilename(filetypes=(("Text files", "*.txt"), ("all files", "*.*")))
    lb0 = Label(window, text = choosefile)
    lb0.pack(side ="top")
 
def clicked():
    try:
        with open(choosefile, 'r+', encoding='utf-8') as f:
            lines = f.readlines()
            f.seek(0)
            for i in range(int(combo.get())-1, len(lines), int(combo.get())):
                lines[i]+=lines[i][0:21] + "\n\n"
                if i <len(lines)-1:
                    lines[i+1]=lines[i+1][0:21] + " Информация: " + "\n" + lines[i+1]
            f.writelines(lines)
        f.close()      
    except:
        messagebox.showerror("Ошибка", "Дядь, файлик то выбери!")
    messagebox.showinfo("Завершение", "Готова")
 
window = Tk()
window.title("Дырка")
window.geometry('220x400')
window.resizable('false', 'false')
 
lb1 = Label(window, text = "Диапазон строк: ")
lb1.pack(side ="top")
 
combo=ttk.Combobox(window, values=(2,10,50,100,250,500,600,700,800,900,1000), width=28)
combo.current(0)
combo.pack(side ="top")
 
btn3 = Button(window, text = "Обновить список", command = update_the_label, width=26)
btn3.pack(side = "top")
 
btn2 = Button(window, text = "Открыть файл", command=clicked_dialogOpen, width=26)
btn2.pack(side ="top")
 
btn = Button(window, text ="Зарубить", command=clicked, width=26)
btn.pack(side ="top")
 
lb2 = Label(window, text = "_________________________")
lb2.pack(side ="top")
 
lb3 = Label(window, text = "Список отредактированных файлов:")
lb3.pack(side ="top")
 
window.mainloop()
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
03.09.2019, 12:20
Ответы с готовыми решениями:

Сохранить данные из них для последующего просмотра и редактирования
имеется несколько полей в которые заносятся данные. как мне сохранить данные из них для последующего просмотра и редактирования?

Как целиком загрузить таблицу из SQL БД в браузер для последующего её редактирования?
Как целиком загрузить таблицу из SQL БД в браузер для последующего её редактирования?

Добавление картинки через диалоговое окно по кнопке, для последующего сохранения в таблицу
Здравствуйте, в бд имеется таблица с полями Оле. В поля Оле добавляются картинки с изделиями. Создал форму для добавления картинок и...

158
Автоматизируй это!
Эксперт Python
 Аватар для Welemir1
7391 / 4818 / 1246
Регистрация: 30.03.2015
Сообщений: 13,688
Записей в блоге: 29
04.09.2019, 15:57
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Alli_Lupin Посмотреть сообщение
ТС хочет переиспользуемую переменную. Что бы и сюда использовать, и туда использовать,
так вот Х вернулся, пусть и переиспользует как хочет) или объянит четко чего он хочет (раз не хочет читать )
1
5037 / 1064 / 149
Регистрация: 29.01.2013
Сообщений: 6,232
04.09.2019, 15:58
Welemir1, он хочет переиспользовать переменную за пределами локальной области видимости)
1
Автоматизируй это!
Эксперт Python
 Аватар для Welemir1
7391 / 4818 / 1246
Регистрация: 30.03.2015
Сообщений: 13,688
Записей в блоге: 29
04.09.2019, 16:00
Цитата Сообщение от Damenikx Посмотреть сообщение
Так а вы теперь попробуйте её впихнуть отдельно в другую функцию, но не затрагивая fileDialog
легко
Python
1
2
3
4
5
6
7
def get_value():
    x=1
    return x
 
def another_func():
    z = get_value() +2
    return z
результат будет 3 (1+2)

Добавлено через 42 секунды
Цитата Сообщение от Alli_Lupin Посмотреть сообщение
он хочет переиспользовать переменную за пределами локальной области видимости)
ну так получи ее там и в той области видимости где необходимо
1
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
04.09.2019, 16:01  [ТС]
Цитата Сообщение от Welemir1 Посмотреть сообщение
ну так получи ее там и в той области видимости где необходимо
Чтобы её там получить нужно обратиться к функции, а если обратиться к функции то открывается fileDialog, опять!
0
5037 / 1064 / 149
Регистрация: 29.01.2013
Сообщений: 6,232
04.09.2019, 16:01
Цитата Сообщение от Welemir1 Посмотреть сообщение
ну так получи ее там и в той области видимости где необходимо
вот мы его к этому и подводим.
1
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
04.09.2019, 16:03  [ТС]
Цитата Сообщение от Welemir1 Посмотреть сообщение
z = get_value()
Представьте, что здесь ещё fileDialog, и вам не надо его вызывать, вам нужно только Х

Добавлено через 1 минуту
Неужели я настолько туп, что не понимаю. Может я плохо показал, что на деле нужно.
0
Автоматизируй это!
Эксперт Python
 Аватар для Welemir1
7391 / 4818 / 1246
Регистрация: 30.03.2015
Сообщений: 13,688
Записей в блоге: 29
04.09.2019, 16:05
ну после первого вызова сохрани в какую-то переменную этот путь, куча есть разных решений если понимать что автору нужно и знать матчасть
1
5037 / 1064 / 149
Регистрация: 29.01.2013
Сообщений: 6,232
04.09.2019, 16:05
Damenikx, вы немного зациклились на своих способах решения проблемы. Вам бы отвлечься чем, потом перечитать всё то, что вам умные ребята, не чета мне, посоветовали.
1
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
04.09.2019, 16:07  [ТС]
Вот:

Python
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
def clicked_dialogOpen():
    takeFile = filedialog.askopenfilename(filetypes=(("Text files", "*.txt"), ("all files", "*.*")))
    return takeFile
 
def change_file():
    try:
        with open(takeFile, 'r+', encoding='utf-8') as f:
            lines = f.readlines()
            f.seek(0)
            for i in range(int(combo.get()) - 1, len(lines), int(combo.get())):
                lines[i] += lines[i][0:21] + "\n\n"
                if i < len(lines) - 1:
                    lines[i + 1] = lines[i + 1][0:21] + " Информация: " + "\n" + lines[i + 1]
            f.writelines(lines)
        f.close()
    except:
        messagebox.showerror("Ошибка", "Дядь, файлик то выбери!")
    messagebox.showinfo("Завершение", "Готова")
 
window = Tk()
window.title("Дырка")
window.geometry('220x400')
window.resizable('false', 'false')
 
lb1 = Label(window, text="Диапазон строк: ")
lb1.pack(side="top")
 
combo = ttk.Combobox(window, values=(2, 10, 50, 100, 250, 500, 600, 700, 800, 900, 1000), width=28)
combo.current(0)
combo.pack(side="top")
 
btn2 = Button(window, text="Открыть файл", command=clicked_dialogOpen, width=26)
btn2.pack(side="top")
 
btn = Button(window, text="Зарубить", command=change_file, width=26)
btn.pack(side="top")
Если мне вызвать ещё раз функцию def clicked_dialogOpen() в функции change_file, то я два раза буду открывать далоговое окно выбора файла. Мне нужен всего - то путь takePath.

Добавлено через 1 минуту
Alli_Lupin, да, я вчера так делал, отвлёкся, перечитал. Всё равно не понимаю
0
Автоматизируй это!
Эксперт Python
 Аватар для Welemir1
7391 / 4818 / 1246
Регистрация: 30.03.2015
Сообщений: 13,688
Записей в блоге: 29
04.09.2019, 16:10
Цитата Сообщение от Damenikx Посмотреть сообщение
def clicked_dialogOpen():
* * takeFile = filedialog.askopenfilename(filetypes=((" Text files", "*.txt"), ("all files", "*.*")))
* * return takeFile
def change_file():
* * try:
* * * * with open(takeFile, 'r+', encoding='utf-8') as f:
Python
1
2
3
4
5
6
7
8
9
10
11
def clicked_dialogOpen():
* * return filedialog.askopenfilename(filetypes=(("Text files", "*.txt"), ("all files", "*.*")))
 
def change_file(file_name):
    try:
        with open(file_name, 'r+', encoding='utf-8') as f:
            pass #отсальное опущено
 
 
file = clicked_dialogOpen() #эту переменную и потом можно использовать, если нужна
change_file(file)
0
Эксперт Python
 Аватар для dondublon
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 6
04.09.2019, 16:17
Лучший ответ Сообщение было отмечено Damenikx как решение

Решение

Damenikx, уже даже жалко становится, вы так стараетесь.
Окей, тут 2 варианта. В первом в функцию change_file надо передать takeFile как параметр.
1 вариант - всё делаем по одному нажанию, в одной функции. Внутри её получам файл и меняем:
Python
1
2
3
def open_and_cnahge():
  filename = clicked_dialogOpen()
  change_file(filename)
2й вариант - по нажатию двух кнопок, как сейчас, тогда имя файла надо где-то прихранивать. Где? Минимальная область, которая для этого достаточна - ваш диалог, который с кнопками. Но тут надо знать, как в Tk, в функциях-обработчиках, обратиться к диалогу, а я этого не знаю. Как вариант - создать небольшой классик для хранения, и подписывать на него метода этого классика:
(Назовём его Storage)
Python
1
2
3
4
5
6
7
8
9
10
class Storage(object):
    .... тут будем хранить имя файла. 
    def clicked_dialogOpen():
        .... всё то же самое, только в конце self.filename = получыенное имя
    def change_file():
         ... аналогично, имя получаем из self.filename
storage = Storage()
btn2 = Button(window, text="Открыть файл", command=storage.clicked_dialogOpen, width=26)
 
btn = Button(window, text="Зарубить", command=storage.change_file, width=26)
На самом деле это тоже грубовато, потому что смешиваеся гуй и безгуёвая обработка, но для начала вам сойдёт.
0
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
04.09.2019, 16:19  [ТС]
Мама, зачем ты меня родила таким тупым?

dondublon, Welemir1. Спасибо за помощь, сейчас буду разбираться.
0
Эксперт Python
 Аватар для dondublon
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 6
04.09.2019, 16:22
Damenikx, да, в методы Storage не забудьте добавить self, как параметр. Я скопипастил и забыл.
1
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
04.09.2019, 16:25  [ТС]
Цитата Сообщение от dondublon Посмотреть сообщение
На самом деле это тоже грубовато, потому что смешиваеся гуй и безгуёвая обработка, но для начала вам сойдёт.
Поэтому, изначально, я и использовал глобальную переменную. Я тоже не знаю, как хранить имя в обработчике кнопки, а так как кнопки "два штука", я и использовал глобалку.

Welemir1, если использовать данный метод то есть проблема, при запуске программы мы сначала должны выбрать файлы для обработки. А если понадобиться ещё? Значит перезагружать программу?

Добавлено через 1 минуту
Скорее всего, мне надо будет переделывать всё. За основу возьму Ваши советы. Проблема в том, что главный то вопрос не решён видимо это действительно не правильно делать на 2 кнопки.
0
Эксперт Python
 Аватар для dondublon
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 6
04.09.2019, 16:28
Damenikx, вот поэтому в Qt, к примеру, принято в делать наследника от графического компонента (виджета). В наследнике делается логика, в т. ч. нужные переменные. Они не глобальные, они внутри класса.
1
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
04.09.2019, 16:31  [ТС]
dondublon, возможно надо использовать классы тогда, а не отдельные функции вне класса?
0
Эксперт Python
 Аватар для dondublon
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 6
04.09.2019, 16:57
Damenikx, о каких классах речь? Вот я привёл 2 варианта, во втором используется класс для хранения filename.
1
 Аватар для Damenikx
955 / 341 / 114
Регистрация: 04.08.2018
Сообщений: 2,533
04.09.2019, 17:01  [ТС]
dondublon, это просто мысли в слух. Сижу, разбираюсь. Спасибо Вам.
0
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
05.09.2019, 02:23
Цитата Сообщение от Damenikx Посмотреть сообщение
Но вы сказали там, далеко вверху, что нельзя использовать глобальные переменные
Если бы нельзя было использовать глобальные переменные, то тогда их не было бы в питоне. Просто нужно хорошо понимать как работают глобальные переменные и тогда их использовать. Не важно, с глобальной переменной или без нее, важно сделать код, который будет работать.

Добавлено через 20 минут
Цитата Сообщение от Damenikx Посмотреть сообщение
Скорее всего, мне надо будет переделывать всё.
Для начала Вам нужно продумать, что Вы хотите сделать, и четко сформулировать свою задачу. Например не понятно, почему средствами ОС нельзя скопировать все нужные для обработки файлы в одну папку, и уже с ней работать. У Вас что, постоянно с течением времени в разные папки добавляются файлы, которые Вам нужно обрабатывать? Тогда какой критерий выбора необходимого файла для обработки. Если Вы выбираете эти файлы сами, а не программа, то проще вручную, с помощью проводника, собирать эти файлы в одну папку. И там уже их обрабатывать. Если таких файлов постоянно поступает уж очень большое количество, то сделать , что бы питон выдавал Вам список файлов из разных папок, а вы указывали какой файл обрабатывать, тогда это немного упростит работу, в отличие сбора их в одну папку проводником. Но в идеале нужно, что бы Ваша программа сама по некоторым признакам выбирала нужные файлы и отправляла на обработку.
В общем еще раз внимательно продумайте алгоритм и для начала четко опишите свою задачу в теме на этом форуме.

Добавлено через 1 час 5 минут
Damenikx, Начал помаленьку разбираться с Вашей задачей. Буду давать свои замечания по ходу.
Взял за основу Ваш код с глобальной переменной.
Для начала, название кнопки "Открыть файл" не соответствует тому, что она делает. У Вас происходит не открытие файла, а открытие окна проводника и выбор в нем файла. Поэтому правильнее было бы назвать кнопку "Выбрать файл".

Добавлено через 39 минут
Обработка файлов идет нормально.
У Вас проблема с записью внизу сообщений, какие файлы выбраны и какие обработаны.
По этой же причине кнопка "Обновить список" не работает.

Добавлено через 20 минут
Цитата Сообщение от Damenikx Посмотреть сообщение
Желательно сделать наглядно, чтобы я уже видел, какие файлики я добавил, а какие нет!
Если я правильно понимаю, у Вас именно в этом проблема, как правильно выводить информацию внизу формы?
Существуют способы изменять метки в уже выведенной форме, Вы просто этого не знаете.
И еще, по моему для того, что бы правильно работала форма, нужно структуру ее создания помещать в функцию. По крайней мере Лутц так делает, и я используя его примеры, тоже так делаю.
Кликните здесь для просмотра всего текста
Python
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# файл *.pyw (расширение .pyw необходимо для подавления окна DOS)
 
from tkinter import *                              # импорт объектов для графики
from tkinter.messagebox import *                   # импорт объектов для диалоговых окон
import shelve                                      # импорт модуля для работы с базой данных 
 
class PhoneBook:
    # класс Телефонная книга
    def __init__(self, nameBook, dicRec={}):
        # метод инициализации атрибутов экземпляров класса  и передача в метод значений для атрибутов
        self.nameBook = nameBook                   # инициализация атрибута Имя книги
        self.dicRec = dicRec                       # перечень записей в виде словаря, по умолчанию пустой
    def loadBook(self):
        # загрузка записей из базы данных
        db = shelve.open(self.nameBook)            # открытие базы данных (имя берется из атрибута nameBook экземпляра класса)
        self.dicRec = dict(db.items())             # загрузка записей из базы данных в атрибут dicRec экземпляра класса (в словарь экземпляра класса)
        db.close()                                 # закрытие базы данных
    def saveBook(self):
        # сохранение записей в базе данных
        db = shelve.open(self.nameBook)            # открытие базы данных
        for (key, record) in self.dicRec.items():  # запись содержимого из 
            db[key] = record                       # словаря экземпляра класса в базу данных
        db.close()                                 # закрытие базы данных
 
class PhoneRec:
    # класс Запись
    def __init__(self, keyRec, char, label, phone, familyName, comment, delR=''):
        # инициализация атрибутов экземпляров класса
        self.keyRec = keyRec                       # ключ записи
        self.char = char                           # буква, на странице которой находится запись
        self.label = label                         # метка, к чему относится запись
        self.phone = phone                         # телефон
        self.familyName = familyName               # Ф.И.О.
        self.comment = comment                     # комментарий
        self.delR = delR                           # служебное поле для пометки записи:
                                                   # ''- видимая, 'с' - скрытая, 'у' - удаляемая
 
fieldnamesRec = ('keyRec', 'char', 'label', 'phone', 'familyName', 'comment', 'delR')  # кортеж имен полей в записи
activCh = 'А'                                      # буква, актмвная на текущий момент
typeRec = ''                                       # тип выводимых на экран записей, '' - открытые, "с" - скрытые
dicRem = {}                                        # словарь оставшихся не выведенными записей
 
def onDeleteRequest():
#    print('Got wm delete') # щелчок на кнопке X в окне: можно отменить или перехватить
    saveRec()
    window.destroy()         # возбудит событие <Destroy>
#def doRootDestroy(event):
#    print('Got event <destroy>') # для каждого виджета в корневом окне
def makeWidgets():
    # создание графической формы
    global entriesRec, entRec, lab1, alph          # перечень глобальных переменных, которые будут использоваться и за пределами функции
    entRec = {}                                    # словарь, в который будут заносится объекты ввода entFind (поиск) и entKeyRec (ключ)
    window = Tk()                                  # создание главного окна
    window.title('Телефоны')                       # заголовок окна
    window.geometry('1260x600+0+0')                # размеры окна
#    window.bind('<Destroy>', doRootDestroy)              # для корневого и дочерних 
    window.protocol('WM_DELETE_WINDOW', onDeleteRequest) # на кнопке X окна (перехватывает нажатие кнопки Х)
    form1 = Frame(window)                          # создание внутри окна window контейнера form1
    form1.pack()
    lab1 = Label(form1, text=activCh, fg="#eee", bg="#333", width=5)  # метка, показывающая
    lab1.pack(side=LEFT)                                              # активную букву
    Label(form1, text='  ', width=30).pack(side=LEFT)                 # вспомагательная пустая метка для улучшения расположения
    alph = ["А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", 
            "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Э", "Ю", "Я"]         # список букв
    for i in range(len(alph)):                     # создание кнопок с буквами
        Button(form1, text=alph[i], command=(lambda x=alph[i]: fetchChr(x))).pack(side=LEFT)
    ent = Entry(form1, width=27)                   # поле ввода для поиска
    ent.pack(side=LEFT)
    entRec['entFind'] = ent                        # поместить объект поля ввода в словарь entRec
    Button(form1, text="Поиск", command=fetchFind).pack(side=LEFT)     # создание кнопки Поиск
 
    form2 = Frame(window)                          # создание внутри окна window контейнера form2
    form2.pack()
    entriesRec = {}                # словарь, для занесения в него объектов Entry ячеек таблицы ввода записей
    fieldnamesRecCyr = ('№№', 'Буква', 'Метка', 'Телефон', 'ФИО', 'Комментарий', 'тип')  # кортеж имен полей на руском
    for (ix, label) in enumerate(fieldnamesRecCyr): # создание надписей заголовков столбцов таблицы
        lab = Label(form2, text=label)
        lab.grid(row=2, column=ix)
    for i in range(1, 26):         # создаются ячейки таблицы для ввода записей
        for (ix, label) in enumerate(fieldnamesRec):
            if label == 'keyRec' or label == 'char' or label == 'delR':  # выделяются столбцы, которые потом будут иметь особый режим доступа
                ent = Entry(form2, state='normal', width=6)
            else:
                ent = Entry(form2, width=40)
            ent.grid(row=i+2, column=ix)
            entriesRec[label+str(i)] = ent   # объекты ячеек таблицы заносятся в словарь, причем к имени 
                                             # столбца ячейки добавляется номер строки, 
                                             # тем самым однозначно определяются координаты ячейки,
                                             # что бы к ней обращаться
    form3 = Frame(window)                            # создание внутри окна window контейнера form3
    form3.pack()
    Button(window, text="Следующая страница", command=fetchNext).pack()  # кнопка Следующая страница
    Label(window, text='      ', width=10).pack(side=LEFT)       # вспомогательная пустая метка
    labKeyRec = Label(window, text='№').pack(side=LEFT)     # надпись перед полем ввода номера ключа
    ent = Entry(window, width=10)                                # поле ввода номера ключа
    ent.pack(side=LEFT)
    entRec['entKeyRec'] = ent             # занесение объекта поле ввода номера ключа в словарь entRec
    Button(window, text="Скрыть", command=hideRec).pack(side=LEFT)             # кнопка Скрыть (запись)
    Button(window, text="Показать скрытые", command=fetchHide).pack(side=LEFT) # кнопка Показать скрытые
    Button(window, text="Открыть", command=openRec).pack(side=LEFT)            # кнопка Открыть (запись)
    Label(window, text=' ', width=5).pack(side=LEFT)                           # вспомогательная пустая метка
    Button(window, text="Удалить", command=delKeyRec).pack(side=LEFT)          # кнопка удалить (запись)
    Label(window, text='      ', width=30).pack(side=LEFT)                     # вспомогательная пустая метка
    btns = Button(window, text="Сохранить", command=interSave).pack(side=LEFT)   # кнопка Сохранить (страницу)
    Label(window, text='      ', width=20).pack(side=LEFT)                     # вспомогательная пустая метка
    Button(window, text="Выход", command=fin).pack(side=LEFT)                  # кнопка Выход (из программы)
    return window                                              # функция makeWidgets возвращает окно window
 
def clear_sheet():
    # очистка листа
    for i in range(1, 26):
        for field in fieldnamesRec:
            if field == 'keyRec' or field == 'delR':              # для очистки полей keyRec и delR,
                entriesRec[field+str(i)].config(state='normal')   # нужно открыть их для записи
                entriesRec[field+str(i)].delete(0, END)
                entriesRec[field+str(i)].config(state='readonly')
            else:
                entriesRec[field+str(i)].delete(0, END)         # очистка остальных полей
def fetchChr(ch):
    # выбрать записи на букву ch
    global activCh, typeRec, lab1
    saveRec()                      # предварительно сохранить предыдущую страницу
    typeRec = ''                   # выбор для буквы делать только из открытых записей
    activCh = ch                   # сделать ch текущей буквой
    lab1.config(text=activCh)      # написать, для какой буквы выводятся записи
    dicRecChr = {}                 # словарь, в который помещаются выбранные записи
    for key in t1.dicRec.keys():      # выбор записей и помещение их в словарь
        if t1.dicRec[key].char == ch:
            dicRecChr[key] = t1.dicRec[key]
    fetch(dicRecChr)                        # вывод записей в таблицу формы
def interSave():
    # # принудительное сохранение текущей страницы и повторный вывод записей для этой буквы начиная с первой страницы
    fetchChr(activCh)
def fetchHide():
    # вывод скрытых записей
    global typeRec, lab1
    saveRec()
    lab1.config(text='скр')
    typeRec = 'с'
    fetch(t1.dicRec)
def fetch(dicR):
    # вывод записей из заданнго словаря
    global dicRem                        # словарь записей, оставшихся не выведенными
    clear_sheet()                        # очистка таблицы
    count = 1                            # счетчик показывающий номер строки, в которую выводится запись
    dicRe = dicR.copy()                  # словарь, ведущий учет записей, которые еще не выведены
    while count <= 25 and len(dicRe):    # в цикле, заполнение строк таблицы записями
        for key in dicR.keys():            # в цикле вывод записи удовлетворяющей условию
            if dicR[key].delR == typeRec:
                record = dicR[key]                   # запись для вывода
                for field in fieldnamesRec:          # в цикле последовательное заполнение полей в строке
                    if field == 'keyRec' or field == 'delR':    # поля, которые необходимо открыть для записи
                        entriesRec[field+str(count)].config(state='normal')
                        entriesRec[field+str(count)].insert(0, getattr(record, field))
                        entriesRec[field+str(count)].config(state='readonly')
                    else:
                        entriesRec[field+str(count)].insert(0, getattr(record, field))  # все остальные поля
                count += 1         # переход к следующей строке таблицы
                dicRe.pop(key)     # удаление записи, которая выведена из словаря учета оставшихся записей           
                if count > 25:     # если все строки таблицы заполнены, то выход из цикла while
                    break
            else:
                dicRe.pop(key) # удаление из словаря учета записи, которая не удовлетворяет условию вывода в таблицу
    dicRem = dicRe.copy()      # словарь записей, оставшихся не выведенными
 
def fetchNext():
    # вывод на следующей странице записей, оставшихся не выведенными
    saveRec()
    fetch(dicRem)
 
def delKeyRec():
    # физическое удаление из базы данных записи, которая указана в ячейке entKeyRec
    key = entRec['entKeyRec'].get()  # из ячейки entKeyRec берется ключ записи для удаления
    if askyesno('Подтверждение', 'Удалить запись без возможности востановления?'):  # подтверждение на удаление
        del t1.dicRec[key]               # запись удаляется из динамического словаря t1.dicRec
        db = shelve.open(t1.nameBook)    # открывается база данных
        del db[key]                      # указанная запись физически удаляется из базы данных
        db.close()                       # база данных закрывается
        for i in range(1, 26): # ищется строка таблицы с этой записью, и помечается как удаленная, 
            if entriesRec['keyRec'+str(i)].get() == key:         # что бы потом при сохранении страницы,
                entriesRec['delR'+str(i)].config(state='normal') # она не была вновь занесена в базу данных
                entriesRec['delR'+str(i)].insert(0, 'у')
                entriesRec['delR'+str(i)].config(state='readonly')
        entRec['entKeyRec'].delete(0, END)            # очищается ячейка, содержащая номер удаляемой записи
    else:
        showinfo('Отмена', 'Удаление записи отменено')   # удаление отменено
def hideRec():
    # пометить как скрытую
    key = entRec['entKeyRec'].get()  # из ячейки entKeyRec берется ключ записи для сокрытия
    for i in range(1, 26):           # ищется строка таблицы с этой записью, и помечается как скрытая
        if entriesRec['keyRec'+str(i)].get() == key:
            entriesRec['delR'+str(i)].config(state='normal')
            entriesRec['delR'+str(i)].insert(0, 'с')
            entriesRec['delR'+str(i)].config(state='readonly')
    entRec['entKeyRec'].delete(0, END)           # очищается ячейка, содержащая номер скрываемой записи записи
def openRec():
    # открыть скрытую запись
    key = entRec['entKeyRec'].get()   # из ячейки entKeyRec берется ключ записи для открытия
    for i in range(1, 26):            # ищется строка таблицы с этой записью, и помечается как открытая
        if entriesRec['keyRec'+str(i)].get() == key:
            entriesRec['delR'+str(i)].config(state='normal')
            entriesRec['delR'+str(i)].delete(0, END)
            entriesRec['delR'+str(i)].insert(0, '')
            entriesRec['delR'+str(i)].config(state='readonly')
    entRec['entKeyRec'].delete(0, END)           # очищается ячейка, содержащая номер открываемой записи 
 
def fetchFind():
    # поиск записей по заданной строке
    global lab1
    saveRec()
    clear_sheet()
    lab1.config(text='поиск')      # сигнализирует о режиме поиска
    strF = entRec['entFind'].get() # строка для поиска берется из ячейки entFind
    dicFind = {}                   # словарь, для занесения в него найденных записей
    for key in t1.dicRec.keys():   # в тлефонном справочнике ищутся записи содержащие искомую строку
        record = t1.dicRec[key]
        for field in fieldnamesRec:
            if (field != 'keyRec' and field != 'char' and field != 'delR' and # поиск в полях, за исключением перечисленных
                getattr(record, field).find(strF) != -1):
                dicFind[key] = record
                break
    fetch(dicFind)                  # вывод найденных записей
def saveRec():
    # сохранение текущей страницы
    global typeRec
    for i in range(1, 26):       # просмотр строк и при наличии хотя бы в одном поле строки данных, сохранение ее
        key = entriesRec['keyRec'+str(i)].get() # проверка наличия в строке ключа
        if entriesRec['delR'+str(i)].get() == 'у': # записи помеченные как удаленные пропускаются
            continue
        elif key:                # иначе, если запись не удаленная и с ключом, то она перезаписывается
            record = t1.dicRec[key]
            for field in fieldnamesRec:
                setattr(record, field, entriesRec[field+str(i)].get())
            t1.dicRec[key] = record
        else: # иначе, если в строке нет ключа, но в одном из полей есть данные, то создается запись-экземпляр
            existRec = False                                               # и помещается а словарь t1.dicRec
            for field in fieldnamesRec:
                if entriesRec[field+str(i)].get(): existRec = True # Если существует запись в поле на этой строке
            if existRec:     # если данные в строке существуют, то создается запись
                if entriesRec['char'+str(i)].get():  # если поле буквы не пусто, то в запись заносится эта буква
                    char = entriesRec['char'+str(i)].get()
                else:              # иначе в запись заносится буква, являющаяся на данный момент активной
                    char = activCh
                label = entriesRec['label'+str(i)].get()             # заполняются переменные
                phone = entriesRec['phone'+str(i)].get()             # для формирования записи
                familyName = entriesRec['familyName'+str(i)].get()
                comment = entriesRec['comment'+str(i)].get()
                if len(t1.dicRec)>0: # если телефонный справочник не пуст, то к максимальному значению ключа 
                    L = sorted(t1.dicRec.items(), key=lambda item: int(item[0]))  # прибавляется единица
                    keyRec = str(int(L[-1][0]) + 1)
                else:        # иначе записи присваивается ключ равный 1
                    keyRec = "1"
                record = PhoneRec(keyRec, char, label, phone, familyName, comment) # создается запись, экземпляр класса PhoneRec
                t1.dicRec[keyRec] = record     #  и записывается в словарь t1.dicRec
    t1.saveBook()  # словарь t1.dicRec сохраняется во внешней базе данных "Телефоны"
 
def fin():            # сохранение перед закрытием окна
    saveRec()
    window.destroy()
 
if __name__ == '__main__':
 
    t1 = PhoneBook("Телефоны")   # создание экземпляра класса PhoneBook
    t1.loadBook()                # загрузка внешней базы данных в словарь t1.dicRec,
                                 # с которым в дальнейшем будет производится вся работа, 
                                 # перед выгрузкой потом назад в базу данных
    window = makeWidgets()       # создание формы
    fetchChr('А')                # вывод в качестве стартовой страницу с буквой "А"
    window.mainloop()            # передача управления форме


Я по аналогии с Лутцом называю функцию, в которой конструируется форма, именем makeWidgets()

Поэтому первое, что я Вам рекомендую сделать, это разместить код создания формы в функцию.
Что касается изменение меток Label в уже открытой форме, то я завтра найду , где описаны приемы, как это делается, и дам Вам ссылку.
1
1732 / 970 / 199
Регистрация: 22.02.2018
Сообщений: 2,693
Записей в блоге: 6
05.09.2019, 03:43
Damenikx, Вот еще один проект (точнее одна его часть, так как он из двух модулей), где кстати я при работе с выведенной формой меняю текст метки lab1 с помощью метода config(), следующим образом lab1.config(text=activCh)
Кликните здесь для просмотра всего текста
Python
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# файл booksCatalog.pyw (расширение .pyw необходимо для подавления окна DOS)
 
from tkinter import *                              # импорт объектов для графического интерфейса
from tkinter.messagebox import *                   # импорт объектов для диалоговых окон
import shelve                                      # импорт модуля для работы с базой данных 
import booksRecord as bR                           # импорт модуля с формой для одной выбранной записи
 
class RecordsBook:
    # класс Книга записей
    def __init__(self, nameBook, dicRec={}):
        # метод инициализации атрибутов экземпляров класса  и передача в метод значений для атрибутов
        self.nameBook = nameBook                   # инициализация атрибута Имя книги
        self.dicRec = dicRec                       # перечень записей в виде словаря, по умолчанию пустой
    def loadBook(self):
        # загрузка записей из базы данных
        db = shelve.open(self.nameBook)            # открытие базы данных (имя берется из атрибута nameBook класса)
        self.dicRec = dict(db.items())             # загрузка записей из базы данных в атрибут dicRec экземпляра класса (в словарь экземпляра класса)
        db.close()                                 # закрытие базы данных
    def saveBook(self):
        # сохранение записей в базе данных
        db = shelve.open(self.nameBook)            # открытие базы данных
        for (key, record) in self.dicRec.items():  # запись содержимого из 
            db[key] = record                       # словаря экземпляра класса в базу данных
        db.close()                                 # закрытие базы данных
 
class Record:
    # класс Запись
    def __init__(self, keyRec, char, label, name, author, 
                 year, city, publishing, comment, delR=''):
        # инициализация атрибутов экземпляров класса
        self.keyRec = keyRec                       # ключ записи
        self.char = char                           # буква, на странице которой находится запись
        self.label = label                         # метка, к чему относится запись
        self.name = name                           # Название
        self.author = author                       # Автор
        self.year = year                           # Год
        self.city = city                           # Город
        self.publishing = publishing               # Издательство
        self.comment = comment                     # комментарий
        self.delR = delR                           # служебное поле для пометки записи:
                                                   # ''- видимая, 'с' - скрытая, 'у' - удаляемая
    #def __str__(self):                            # метод для отладки
    #    return '[Record: %s, %s, %s, %s, %s, %s, %s, %s]' % (self.char, self.label, self.name, self.author, self.year, self.city, self.publishing, self.comment)
 
fieldnamesRecTab = ('keyRec', 'char', 'label', 'name', 'author', 'comment', 'delR')  # кортеж имен полей записи в таблице
fieldnamesRec = ('char', 'label', 'name', 'author', 'year', 'city', 'publishing', 'comment')   # кортеж имен полей для формы с одной записью
fieldnamesRecCyr = {'char':'Буква', 'label':'Метка', 'name':'Название', 'author':'Автор', 'year':'Год', 'city':'Город', 'publishing':'Издательство', 'comment':'Комментарий'} # словарь для перевода полей в кирилицу
fieldnamesRecFull = ('keyRec', 'char', 'label', 'name', 'author', 'year', 'city', 'publishing',
                    'comment', 'delR')     # кортеж всех полей в записи
activCh = 'А'                                      # буква, актмвная на текущий момент
typeRec = ''                                       # тип выводимых на экран записей, '' - открытые, "с" - скрытые
dicRem = {}                                        # словарь оставшихся не выведенными записей
 
def onDeleteRequest():
#    print('Got wm delete') # щелчок на кнопке X в окне: можно отменить или перехватить
    saveRec()
    window.destroy()         # возбудит событие <Destroy>
#def doRootDestroy(event):
#    print('Got event <destroy>') # для каждого виджета в корневом окне
def makeWidgets():
    # создание графической формы
    global entriesRec, entRec, lab1, alph          # перечень глобальных переменных, которые будут использоваться и за пределами функции
    entRec = {}                                    # словарь, в который будут заносится объекты ввода entFind (поиск) и entKeyRec (ключ)
    window = Tk()                                  # создание главного окна
    window.title('Книги')                       # заголовок окна
    window.geometry('1260x600+0+0')                # размеры окна
#    window.bind('FocusIn', updatePage)             # при получении окном фокуса, обновление таблицы записей
#    window.bind('<Destroy>', doRootDestroy)              # для корневого и дочерних 
    window.protocol('WM_DELETE_WINDOW', onDeleteRequest) # на кнопке X окна (перехватывает нажатие кнопки Х)
    form1 = Frame(window)                          # создание внутри окна window контейнера form1
    form1.pack()
    lab1 = Label(form1, text=activCh, fg="#eee", bg="#333", width=5)  # метка, показывающая
    lab1.pack(side=LEFT)                                              # активную букву
    Label(form1, text='  ', width=30).pack(side=LEFT)                 # вспомагательная пустая метка для улучшения расположения
    alph = ["А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", 
            "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Э", "Ю", "Я"]         # список букв
    for i in range(len(alph)):                     # создание кнопок с буквами
        Button(form1, text=alph[i], command=(lambda x=alph[i]: fetchChr(x))).pack(side=LEFT)
    ent = Entry(form1, width=27)                   # поле ввода для поиска
    ent.pack(side=LEFT)
    entRec['entFind'] = ent                        # поместить объект поля ввода в словарь entRec
    Button(form1, text="Поиск", command=fetchFind).pack(side=LEFT)     # создание кнопки Поиск
 
    form2 = Frame(window)                          # создание внутри окна window контейнера form2
    form2.pack()
    entriesRec = {}                # словарь, для занесения в него объектов Entry ячеек таблицы ввода записей
    fieldnamesRecTabCyr = ('№№', 'Буква', 'Метка', 'Название', 'Автор', 'Комментарий', 'тип')  # кортеж имен полей на руском
    #fieldnamesRecCyr = {'char':'Буква', 'label':'Метка', 'name':'Название', 'author':'Автор', 'year':'Год', 'city':'Город', 'publishing':'Издательство', 'comment':'Комментарий'}
    #('char', 'label', 'name', 'author', 'year', 'city', 'publishing', 'comment')
    for (ix, label) in enumerate(fieldnamesRecTabCyr): # создание надписей заголовков столбцов таблицы
        lab = Label(form2, text=label)
        lab.grid(row=2, column=ix)
    for i in range(1, 26):         # создаются ячейки таблицы для ввода записей
        for (ix, label) in enumerate(fieldnamesRecTab):
            if label == 'keyRec' or label == 'char' or label == 'delR':  # выделяются столбцы, которые потом будут иметь особый режим доступа
                ent = Entry(form2, state='normal', width=6)
            else:
                ent = Entry(form2, width=40)
            ent.grid(row=i+2, column=ix)
            entriesRec[label+str(i)] = ent   # объекты ячеек таблицы заносятся в словарь, причем к имени 
                                             # столбца ячейки добавляется номер строки, 
                                             # тем самым однозначно определяются координаты ячейки,
                                             # что бы к ней обращаться
    form3 = Frame(window)                            # создание внутри окна window контейнера form3
    form3.pack()
    Button(window, text="Следующая страница", command=fetchNext).pack()  # кнопка Следующая страница
    Label(window, text='      ', width=10).pack(side=LEFT)       # вспомогательная пустая метка
    labKeyRec = Label(window, text='№').pack(side=LEFT)     # надпись перед полем ввода номера ключа
    ent = Entry(window, width=10)                                # поле ввода номера ключа
    ent.pack(side=LEFT)
    entRec['entKeyRec'] = ent             # занесение объекта поле ввода номера ключа в словарь entRec
    Button(window, text="Скрыть", command=hideRec).pack(side=LEFT)             # кнопка Скрыть (запись)
    Button(window, text="Показать скрытые", command=fetchHide).pack(side=LEFT) # кнопка Показать скрытые
    Button(window, text="Открыть", command=openRec).pack(side=LEFT)            # кнопка Открыть (запись)
    Label(window, text=' ', width=2).pack(side=LEFT)                           # вспомогательная пустая метка
    Button(window, text="Удалить", command=delKeyRec).pack(side=LEFT)          # кнопка удалить (запись)
    Label(window, text=' ', width=10).pack(side=LEFT)                           # вспомогательная пустая метка
    Button(window, text="Вывести запись", command=fetchRecord).pack(side=LEFT) # кнопка выводит запись в отдельной форме
    Label(window, text=' ', width=3).pack(side=LEFT)                           # вспомогательная пустая метка
    Button(window, text="Восстановить", command=updatePage).pack(side=LEFT)
    Label(window, text=' ', width=30).pack(side=LEFT)                     # вспомогательная пустая метка
    btns = Button(window, text="Сохранить", command=interSave).pack(side=LEFT)   # кнопка Сохранить (страницу)
    Label(window, text='      ', width=20).pack(side=LEFT)                     # вспомогательная пустая метка
    Button(window, text="Выход", command=fin).pack(side=LEFT)                  # кнопка Выход (из программы)
    return window                                              # функция makeWidgets возвращает окно window
 
def clear_sheet():
    # очистка листа
    for i in range(1, 26):
        for field in fieldnamesRecTab:
            if field == 'keyRec' or field == 'delR':              # для очистки полей keyRec и delR,
                entriesRec[field+str(i)].config(state='normal')   # нужно открыть их для записи
                entriesRec[field+str(i)].delete(0, END)
                entriesRec[field+str(i)].config(state='readonly')
            else:
                entriesRec[field+str(i)].delete(0, END)         # очистка остальных полей
def fetchChr(ch):
    # выбрать записи на букву ch
    global activCh, typeRec, lab1
    saveRec()                      # предварительно сохранить предыдущую страницу
    typeRec = ''                   # выбор для буквы делать только из открытых записей
    activCh = ch                   # сделать ch текущей буквой
    lab1.config(text=activCh)      # написать, для какой буквы выводятся записи
    dicRecChr = {}                 # словарь, в который помещаются выбранные записи
    for key in t1.dicRec.keys():      # выбор записей и помещение их в словарь
        if t1.dicRec[key].char == ch:
            dicRecChr[key] = t1.dicRec[key]
    fetch(dicRecChr)                        # вывод записей в таблицу формы
def interSave():
    # принудительное сохранение текущей страницы и повторный вывод записей для этой буквы начиная с первой страницы
    fetchChr(activCh)
def fetchHide():
    # вывод скрытых записей
    global typeRec, lab1
    saveRec()
    lab1.config(text='скр')
    typeRec = 'с'              # выбор делать только из скрытых записей
    fetch(t1.dicRec)
def fetch(dicR):
    # вывод записей из заданнго словаря
    global dicRem                        # словарь записей, оставшихся не выведенными
    clear_sheet()                        # очистка таблицы
    count = 1                            # счетчик показывающий номер строки, в которую выводится запись
    dicRe = dicR.copy()                  # словарь, ведущий учет записей, которые еще не выведены
    while count <= 25 and len(dicRe):    # в цикле, заполнение строк таблицы записями
        for key in dicR.keys():            # в цикле вывод записи удовлетворяющей условию
            if dicR[key].delR == typeRec:
                record = dicR[key]                   # запись для вывода
                for field in fieldnamesRecTab:          # в цикле последовательное заполнение полей в строке
                    if field == 'keyRec' or field == 'delR':    # поля, которые необходимо открыть для записи
                        entriesRec[field+str(count)].config(state='normal')
                        entriesRec[field+str(count)].insert(0, getattr(record, field))
                        entriesRec[field+str(count)].config(state='readonly')
                    else:
                        entriesRec[field+str(count)].insert(0, getattr(record, field))  # все остальные поля
                count += 1         # переход к следующей строке таблицы
                dicRe.pop(key)     # удаление записи, которая выведена из словаря учета оставшихся записей           
                if count > 25:     # если все строки таблицы заполнены, то выход из цикла while
                    break
            else:
                dicRe.pop(key) # удаление из словаря учета записи, которая не удовлетворяет условию вывода в таблицу
    dicRem = dicRe.copy()      # словарь записей, оставшихся не выведенными
 
def fetchNext():
    # вывод на следующей странице записей, оставшихся не выведенными
    saveRec()
    fetch(dicRem)
 
def updatePage():
    # обновление страницы
    global activCh, typeRec, lab1
    lab1.config(text=activCh)      # написать, для какой буквы выводятся записи
    dicRecChr = {}                 # словарь, в который помещаются выбранные записи
    for key in t1.dicRec.keys():      # выбор записей и помещение их в словарь
        if t1.dicRec[key].char == activCh:
            dicRecChr[key] = t1.dicRec[key]
    fetch(dicRecChr)                        # вывод записей в таблицу формы
 
def delKeyRec():
    # физическое удаление из базы данных записи, которая указана в ячейке entKeyRec
    key = entRec['entKeyRec'].get()  # из ячейки entKeyRec берется ключ записи для удаления
    if askyesno('Подтверждение', 'Удалить запись без возможности востановления?'):  # подтверждение на удаление
        del t1.dicRec[key]               # запись удаляется из динамического словаря t1.dicRec
        db = shelve.open(t1.nameBook)    # открывается база данных
        del db[key]                      # указанная запись физически удаляется из базы данных
        db.close()                       # база данных закрывается
        for i in range(1, 26): # ищется строка таблицы с этой записью, и помечается как удаленная, 
            if entriesRec['keyRec'+str(i)].get() == key:         # что бы потом при сохранении страницы,
                entriesRec['delR'+str(i)].config(state='normal') # она не была вновь занесена в базу данных
                entriesRec['delR'+str(i)].insert(0, 'у')
                entriesRec['delR'+str(i)].config(state='readonly')
        entRec['entKeyRec'].delete(0, END)            # очищается ячейка, содержащая номер удаляемой записи
    else:
        showinfo('Отмена', 'Удаление записи отменено')   # удаление отменено
def hideRec():
    # пометить как скрытую
    key = entRec['entKeyRec'].get()  # из ячейки entKeyRec берется ключ записи для сокрытия
    for i in range(1, 26):           # ищется строка таблицы с этой записью, и помечается как скрытая
        if entriesRec['keyRec'+str(i)].get() == key:
            entriesRec['delR'+str(i)].config(state='normal')
            entriesRec['delR'+str(i)].insert(0, 'с')
            entriesRec['delR'+str(i)].config(state='readonly')
    entRec['entKeyRec'].delete(0, END)           # очищается ячейка, содержащая номер скрываемой записи записи
def openRec():
    # открыть скрытую запись
    key = entRec['entKeyRec'].get()   # из ячейки entKeyRec берется ключ записи для открытия
    for i in range(1, 26):            # ищется строка таблицы с этой записью, и помечается как открытая
        if entriesRec['keyRec'+str(i)].get() == key:
            entriesRec['delR'+str(i)].config(state='normal')
            entriesRec['delR'+str(i)].delete(0, END)
            entriesRec['delR'+str(i)].insert(0, '')
            entriesRec['delR'+str(i)].config(state='readonly')
    entRec['entKeyRec'].delete(0, END)           # очищается ячейка, содержащая номер открываемой записи 
 
def fetchFind():
    # поиск записей по заданной строке
    global lab1
    saveRec()
    clear_sheet()
    lab1.config(text='поиск')      # сигнализирует о режиме поиска
    strF = entRec['entFind'].get() # строка для поиска берется из ячейки entFind
    dicFind = {}                   # словарь, для занесения в него найденных записей
    for key in t1.dicRec.keys():   # в тлефонном справочнике ищутся записи содержащие искомую строку
        record = t1.dicRec[key]
        for field in fieldnamesRecTab:
            if (field != 'keyRec' and field != 'char' and field != 'delR' and # поиск в полях, за исключением перечисленных
                getattr(record, field).find(strF) != -1):
                dicFind[key] = record
                break
    fetch(dicFind)                  # вывод найденных записей
def saveRec():
    # сохранение текущей страницы
    global typeRec
    for i in range(1, 26):       # просмотр строк и при наличии хотя бы в одном поле строки данных, сохранение ее
        key = entriesRec['keyRec'+str(i)].get() # проверка наличия в строке ключа
        if entriesRec['delR'+str(i)].get() == 'у': # записи помеченные как удаленные пропускаются
            continue
        elif key:                # иначе, если запись не удаленная и с ключом, то она перезаписывается
            record = t1.dicRec[key]
            for field in fieldnamesRecTab:
                setattr(record, field, entriesRec[field+str(i)].get())
            t1.dicRec[key] = record
        else: # иначе, если в строке нет ключа, но в одном из полей есть данные, то создается запись-экземпляр
            existRec = False                                               # и помещается а словарь t1.dicRec
            for field in fieldnamesRecTab:
                if entriesRec[field+str(i)].get(): existRec = True # Если существует запись в поле на этой строке
            if existRec:     # если данные в строке существуют, то создается запись
                if entriesRec['char'+str(i)].get():  # если поле буквы не пусто, то в запись заносится эта буква
                    char = entriesRec['char'+str(i)].get()
                else:              # иначе в запись заносится буква, являющаяся на данный момент активной
                    char = activCh
                label = entriesRec['label'+str(i)].get()             # заполняются переменные
                name = entriesRec['name'+str(i)].get()             # для формирования записи
                author = entriesRec['author'+str(i)].get()
                year = ''
                city = ''
                publishing = ''
                comment = entriesRec['comment'+str(i)].get()
                if len(t1.dicRec)>0: # если телефонный справочник не пуст, то к максимальному значению ключа 
                    L = sorted(t1.dicRec.items(), key=lambda item: int(item[0]))  # прибавляется единица
                    keyRec = str(int(L[-1][0]) + 1)
                else:        # иначе записи присваивается ключ равный 1
                    keyRec = "1"
                record = Record(keyRec, char, label, name, author, year, city, publishing, comment) # создается запись, экземпляр класса Record
                t1.dicRec[keyRec] = record     #  и записывается в словарь t1.dicRec
    t1.saveBook()  # словарь t1.dicRec сохраняется во внешней базе данных "Книги"
 
 
def fetchRecord():
    # вывод формы с одной записью
    #global bR.m1_root, bR.m1_fieldnamesRec, current_key, bR.m1_winRec
    saveRec()                     # сохранение текущей страницы таблицы
    #bR.m1_root = window           
    bR.m1_fieldnamesRec = fieldnamesRec       # передача в модуль имен полей
    bR.m1_fieldnamesRecCyr = fieldnamesRecCyr # передача в модуль словаря для перевода полей в кирилицу
    currentKey = entRec['entKeyRec'].get()   # из ячейки entKeyRec берется ключ записи
    #print(key)
    #current_key = key
    bR.m1_recBook(t1)                        # передача в модуль через функцию экземпляра класса RecordsBook
    currentRecord = t1.dicRec[currentKey]    # экземпляр записи для вывода в форме в модуле
    bR.m1_curRec(currentRecord)              # передача в модуль через функцию экземпляра записи
    bR.m1_winRec = bR.m1_makeWidgets()       # создание в модуле формы с одной записью
    bR.m1_fetchRecord(currentRecord)         # вывод в форме в модуле указанной записи
    bR.m1_winRec.mainloop()                  # передача управления форме в модуле
 
def fin():            # сохранение перед закрытием окна крестом
    saveRec()         # сохранение текущей страницы
    window.destroy()  # закрытие окна
 
if __name__ == '__main__':
 
    t1 = RecordsBook("Книги")   # создание экземпляра класса RecordsBook
    t1.loadBook()                # загрузка внешней базы данных в словарь t1.dicRec,
                                 # с которым в дальнейшем будет производится вся работа, 
                                 # перед выгрузкой потом назад в базу данных
    window = makeWidgets()       # создание формы
    fetchChr('А')                # вывод в качестве стартовой страницу с буквой "А"
    window.mainloop()            # передача управления форме


Добавлено через 3 минуты
Если запустите этот код, то увидите как он работает. При выборе некоторой буквы, в левом верхнем углу меняется запись, показывающая какая буква сейчас выбрана.

Аналогичный прием нужно использовать и Вам, что бы менять записи внизу формы.
Но не забудте поместить описание формы в функцию.

Добавлено через 44 минуты
Damenikx, А вообще то, так как Вы говорите, что у Вас большое количество файлов, то выводить информацию внизу формы бессмысленно. Нужно менять алгоритм решения задачи. Например помещать информацию, какие файлы обработаны, в базу данных. И при выборе файла проверять , сличая с БД, что файл не обрабатывался. Так как при повторной обработке в нем будет нарушена его структура. Или еще лучше, после обработки файла менять его название, добавляя в конец названия специальную метку, что файл обработан.
В общем еще раз как следует продумайте алгоритм вашей работы с файлами, на всех этапах этой работы.

Добавлено через 15 минут
Хотя, если Вы просматриваете файлы последовательно, и просто отвлеклись и забыли какой последний файл обработали, то Ваш алгоритм вполне подойдет. Но если повреждение файла это серьезная проблема, то я бы еще добавил сохранение информации об обработанных файлах в базе данных или изменение имени, как я говорил выше. Но это уже смотрите сами, на сколько это необходимо.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.09.2019, 03:43
Помогаю со студенческими работами здесь

Поиск и перемещение файлов в папку для их последующего удаления
пытаюсь организовать поиск и перемещение файлов в папку для их последующего удаления, решил сначала попробовать взять записанные в файл...

Добавление нескольких файлов в БД
Мне надо вывести в бд сразу несколько файлов в форме. сказали что надо преобразовать массив в строку с помощью serialize() чтобы добавить...

Добавление нескольких файлов в бд
Добрый день. Столкнулься с проблемой, так как сам в програмировании пребиваю на начальной стадии обучения прошу совета. Необходимо...

Процедурное создание мира с целью его последующего редактирования
Привет, Я так и не придумал как сформировать свой запрос в гугле, поэтому надеюсь на вашу помощь. Итак, я хочу, чтобы юнити создал мне...

Добавление нескольких файлов в OpenFileDialog
Надо сделать чтоб можно было выбрать несколько файлов в OpenDialog Пока вот что сделал, место пути выдаёт OpenFileDialog1. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru