回答編集履歴

3

一部修正

2020/09/17 11:59

投稿

nto
nto

スコア1438

test CHANGED
@@ -172,7 +172,7 @@
172
172
 
173
173
  def LabelChange(self):
174
174
 
175
- # 同じtextvariableを使用している為、ループする必要はなく1度の更新で全て反映できる
175
+ # 行数でループするのではなく直接buttonを格納しているリストから更新する事簡潔済む
176
176
 
177
177
  if self.var.get():
178
178
 

2

修正

2020/09/17 11:59

投稿

nto
nto

スコア1438

test CHANGED
@@ -1 +1,367 @@
1
+ 日本語コードが読みづらく、1から作り直させていただきました。
2
+
3
+ (classによるフォーマットで申し訳御座いません。)
4
+
5
+
6
+
7
+ データは辞書形式で、Entryウィジェットなどもリストで管理しているので各種応用がしやすいと思います。
8
+
9
+ ページを切り替えた場合のデータの保存も
10
+
11
+ 遷移時のEntry取得→辞書を更新→Entryの中身削除→辞書から次のページデータを表示
12
+
13
+ という形で再現しております。
14
+
15
+ ```python
16
+
17
+ import os
18
+
19
+ import csv
20
+
21
+ import pandas as pd
22
+
23
+ import tkinter as tk
24
+
25
+ from tkinter import messagebox
26
+
27
+ from tkinter import filedialog
28
+
29
+
30
+
31
+ class MainWindow(tk.Frame):
32
+
33
+ def __init__(self, master):
34
+
35
+ super().__init__(master)
36
+
37
+ self.master.title('Hello, World!')
38
+
39
+ self.master.geometry('650x300')
40
+
41
+
42
+
43
+ # 各種事前定義
44
+
45
+ self.data_dic = {'No': ['1','2','3','4','5','6','7','8','9','10','11'],
46
+
47
+ '姓': ['渡邊','柳川','清野','根本','阿部','稲田','木内','三宅','石村','本郷','山田'],
48
+
49
+ '名': ['沙樹','和臣','菜緒','駿斗','亜依','和徳','喜雄','美南','比呂','香帆','比呂'],
50
+
51
+ '性別': ['女','男','女','男','女','男','男','女','男','女','男'],
52
+
53
+ '生年月日': ['1988/07/15','1966/09/04','1979/06/08','1992/03/14','1977/04/04',
54
+
55
+ '1963/11/06','1972/08/21','1992/11/30','1967/12/07','1965/03/20','1977/04/04']
56
+
57
+ }
58
+
59
+ self.colum = 3
60
+
61
+ self.title = [key for key in self.data_dic.keys()]
62
+
63
+ self.tx_data = [list() for i in range(len(self.title))]
64
+
65
+ self.InsertAndRemoveStatus = []
66
+
67
+ self.pageid = 0
68
+
69
+
70
+
71
+ # 各種ウィジェット生成
72
+
73
+ self.CreateWidget()
74
+
75
+
76
+
77
+ ##### メインとなるウィジェットの生成
78
+
79
+ def CreateWidget(self):
80
+
81
+ ##############################
82
+
83
+ # Label及びEntryの生成
84
+
85
+ y = 50
86
+
87
+ x = 140
88
+
89
+ for i in self.title:
90
+
91
+ tk.Label(self.master, text=i).place(x=x, y=y)
92
+
93
+ x += 80
94
+
95
+
96
+
97
+ y = 80
98
+
99
+ for i in range(self.colum):
100
+
101
+ x = 140
102
+
103
+ for e, box in enumerate(self.tx_data):
104
+
105
+ width = 10
106
+
107
+ if e == 4:
108
+
109
+ width = 14
110
+
111
+ obj = tk.Entry(self.master, width=width)
112
+
113
+ obj.place(x=x, y=y)
114
+
115
+ box.append(obj)
116
+
117
+ x += 80
118
+
119
+ y += 31
120
+
121
+
122
+
123
+ ##############################
124
+
125
+ # 辞書データをEntryに挿入していく
126
+
127
+ for (key, value), box in zip(self.data_dic.items(), self.tx_data):
128
+
129
+ for data, widget in zip(value, box):
130
+
131
+ widget.insert(tk.END, data)
132
+
133
+
134
+
135
+ ##############################
136
+
137
+ # Button関連の生成
138
+
139
+ self.var = tk.BooleanVar()
140
+
141
+ tk.Checkbutton(variable=self.var, text="挿入 / 削除",command =self.LabelChange).place(x=40, y=50)
142
+
143
+
144
+
145
+ x = 50
146
+
147
+ y = 78
148
+
149
+ for i in range(self.colum):
150
+
151
+ obj = tk.Button(self.master, width=10, text='挿入')
152
+
153
+ obj.place(x=x, y=y)
154
+
155
+ self.InsertAndRemoveStatus.append(obj)
156
+
157
+ y += 30
158
+
159
+
160
+
161
+ button_data = {'クリア':[25, self.FieldClear], '読込':[130, self.DataRead], '保存': [200, self.DataSave],
162
+
163
+ '前ボタン': [330, self.PreviousPage], '次ボタン':[400, self.NextPage]}
164
+
165
+ for key, value in button_data.items():
166
+
167
+ tk.Button(self.master, text=key, command=value[1]).place(width=50, x=value[0], y=250)
168
+
169
+
170
+
171
+ ##### Button Event
172
+
173
+ def LabelChange(self):
174
+
175
+ # 同じtextvariableを使用している為、ループする必要はなく1度の更新で全てに反映できる
176
+
177
+ if self.var.get():
178
+
179
+ [label.configure(text='削除') for label in self.InsertAndRemoveStatus]
180
+
181
+ else:
182
+
183
+ [label.configure(text='挿入') for label in self.InsertAndRemoveStatus]
184
+
185
+
186
+
187
+ def NextPage(self):
188
+
189
+ self.TemporaryMemory()
190
+
191
+ self.FieldClear()
192
+
193
+ self.pageid += 1
194
+
195
+ self.EntryLoading()
196
+
197
+
198
+
199
+ def PreviousPage(self):
200
+
201
+ # 真偽値を測ってページidが0ならば処理を中断+エラーメッセージ
202
+
203
+ if self.pageid == 0:
204
+
205
+ messagebox.showerror('エラー', 'これ以上は前に戻れません')
206
+
207
+ return
208
+
209
+
210
+
211
+ self.TemporaryMemory()
212
+
213
+ self.FieldClear()
214
+
215
+ self.pageid -= 1
216
+
217
+ self.EntryLoading()
218
+
219
+
220
+
221
+ def EntryLoading(self):
222
+
223
+ for (key, value), box in zip(self.data_dic.items(), self.tx_data):
224
+
225
+ for widget, data in zip(box, value[self.pageid*self.colum: self.pageid*self.colum+self.colum]):
226
+
227
+ widget.insert(tk.END, data)
228
+
229
+
230
+
231
+ def DataRead(self):
232
+
233
+ fTyp = [('', '.csv')]
234
+
235
+ iDir = os.path.abspath(os.path.dirname(__file__))
236
+
237
+ file_name = filedialog.askopenfilename(filetypes=fTyp, initialdir=iDir)
238
+
239
+
240
+
241
+ # 真偽値を測りTrueの場合に読み込み処理、self.data_dicの内容を書き換える
242
+
243
+ # pageidもリセットする
244
+
245
+ if file_name:
246
+
247
+ self.pageid = 0
248
+
249
+ df = pd.read_csv(file_name, encoding='shift_jis', header=None)
250
+
251
+ df = df.fillna('')
252
+
253
+ self.FieldClear()
254
+
255
+ for i in df:
256
+
257
+ dic = {}
258
+
259
+ tmp = []
260
+
261
+ for e, data in enumerate(df[i]):
262
+
263
+ if e == 0:
264
+
265
+ header = data
266
+
267
+ else:
268
+
269
+ tmp.append(data)
270
+
271
+ self.data_dic[header] = tmp
272
+
273
+
274
+
275
+ for (key, value), box in zip(self.data_dic.items(), self.tx_data):
276
+
277
+ for data, widget in zip(value, box):
278
+
279
+ widget.insert(tk.END, data)
280
+
281
+
282
+
283
+ def DataSave(self):
284
+
285
+ fTyp = [('', '.csv')]
286
+
287
+ iDir = os.path.abspath(os.path.dirname(__file__))
288
+
289
+ file_name = filedialog.asksaveasfilename(filetypes=fTyp, initialdir=iDir)
290
+
291
+
292
+
1
- `正常動作していない部分があった為修正中`
293
+ # 保存時拡張子が入力されていない場合に拡張子を補完
294
+
295
+ if '.csv' not in file_name:
296
+
297
+ file_name = file_name + '.csv'
298
+
299
+ # 真偽値を測り、Trueの場合に書き込み処理、csv.writerを使用しlinetarminatorで行末を改行指定
300
+
301
+ if file_name:
302
+
303
+ self.TemporaryMemory()
304
+
305
+ with open(file_name, mode='w') as csvfile:
306
+
307
+ writer = csv.writer(csvfile, lineterminator='\n')
308
+
309
+ writer.writerow([key for key in self.data_dic.keys()])
310
+
311
+ for index in range(len(self.data_dic['No'])):
312
+
313
+ word = []
314
+
315
+ for values in self.data_dic.values():
316
+
317
+ word.append(values[index])
318
+
319
+ writer.writerow(word)
320
+
321
+ messagebox.showinfo('書き込み完了', f'{file_name}に保存しました')
322
+
323
+
324
+
325
+ def FieldClear(self):
326
+
327
+ # Entryウィジェット内の入力された文字列を全て消去
328
+
329
+ for box in self.tx_data:
330
+
331
+ for data in box:
332
+
333
+ data.delete(0, tk.END)
334
+
335
+
336
+
337
+ def TemporaryMemory(self):
338
+
339
+ keys = [key for key in self.data_dic.keys()]
340
+
341
+ for e, box in enumerate(self.tx_data):
342
+
343
+ for n, widget in enumerate(box):
344
+
345
+ data = widget.get()
346
+
347
+ try:
348
+
349
+ self.data_dic[keys[e]][n+self.pageid*self.colum] = data
350
+
351
+ except:
352
+
353
+ pass
354
+
355
+
356
+
357
+
358
+
359
+ if __name__ == '__main__':
360
+
361
+ root = tk.Tk()
362
+
363
+ window = MainWindow(master = root)
364
+
365
+ window.mainloop()
366
+
367
+ ```

1

修正

2020/09/17 11:40

投稿

nto
nto

スコア1438

test CHANGED
@@ -1,355 +1 @@
1
- クラス化してしまい、フォーマットが多少異なると思いますが
2
-
3
- データ自体を辞書で管理すると各種応用が効きやすくなると思います。
4
-
5
-
6
-
7
- ```python
8
-
9
- import os
10
-
11
- import csv
12
-
13
- import pandas as pd
14
-
15
- import tkinter as tk
16
-
17
- from tkinter import messagebox
18
-
19
- from tkinter import filedialog
20
-
21
-
22
-
23
- class MainWindow(tk.Frame):
24
-
25
- def __init__(self, master):
26
-
27
- super().__init__(master)
28
-
29
- self.master.title('Hello, World!')
30
-
31
- self.master.geometry('650x300')
32
-
33
-
34
-
35
- # 各種事前定義
36
-
37
- self.data_dic = {'No': ['1','2','3','4','5','6','7','8','9','10','11'],
38
-
39
- '姓': ['渡邊','柳川','清野','根本','阿部','稲田','木内','三宅','石村','本郷','山田'],
40
-
41
- '名': ['沙樹','和臣','菜緒','駿斗','亜依','和徳','喜雄','美南','比呂','香帆','比呂'],
42
-
43
- '性別': ['女','男','女','男','女','男','男','女','男','女','男'],
44
-
45
- '生年月日': ['1988/07/15','1966/09/04','1979/06/08','1992/03/14','1977/04/04',
46
-
47
- '1963/11/06','1972/08/21','1992/11/30','1967/12/07','1965/03/20','1977/04/04']
48
-
49
- }
50
-
51
- self.colum = 3
52
-
53
- self.title = [key for key in self.data_dic.keys()]
54
-
55
- self.tx_data = [list() for i in range(len(self.title))]
56
-
57
- self.InsertAndRemoveStatus = []
58
-
59
- self.pageid = 0
60
-
61
-
62
-
63
- # 各種ウィジェット生成
64
-
65
- self.CreateWidget()
66
-
67
-
68
-
69
- ##### メインとなるウィジェットの生成
70
-
71
- def CreateWidget(self):
72
-
73
- ##############################
74
-
75
- # Label及びEntryの生成
76
-
77
- y = 50
78
-
79
- x = 140
80
-
81
- for i in self.title:
82
-
83
- tk.Label(self.master, text=i).place(x=x, y=y)
84
-
85
- x += 80
86
-
87
-
88
-
89
- y = 80
90
-
91
- for i in range(self.colum):
92
-
93
- x = 140
94
-
95
- for e, box in enumerate(self.tx_data):
96
-
97
- width = 10
98
-
99
- if e == 4:
100
-
101
- width = 14
102
-
103
- obj = tk.Entry(self.master, width=width)
104
-
105
- obj.place(x=x, y=y)
106
-
107
- box.append(obj)
108
-
109
- x += 80
110
-
111
- y += 31
112
-
113
-
114
-
115
- ##############################
116
-
117
- # 辞書データをEntryに挿入していく
118
-
119
- for (key, value), box in zip(self.data_dic.items(), self.tx_data):
120
-
121
- for data, widget in zip(value, box):
122
-
123
- widget.insert(tk.END, data)
124
-
125
-
126
-
127
- ##############################
128
-
129
- # Button関連の生成
130
-
131
- self.var = tk.BooleanVar()
132
-
133
- tk.Checkbutton(variable=self.var, text="挿入 / 削除",command =self.LabelChange).place(x=40, y=50)
134
-
135
-
136
-
137
- x = 50
138
-
139
- y = 78
140
-
141
- for i in range(self.colum):
142
-
143
- obj = tk.Button(self.master, width=10, text='挿入')
144
-
145
- obj.place(x=x, y=y)
146
-
147
- self.InsertAndRemoveStatus.append(obj)
148
-
149
- y += 30
150
-
151
-
152
-
153
- button_data = {'クリア':[25, self.FieldClear], '読込':[130, self.DataRead], '保存': [200, self.DataSave],
154
-
155
- '前ボタン': [330, self.PreviousPage], '次ボタン':[400, self.NextPage]}
156
-
157
- for key, value in button_data.items():
158
-
159
- tk.Button(self.master, text=key, command=value[1]).place(width=50, x=value[0], y=250)
160
-
161
-
162
-
163
- ##### Button Event
164
-
165
- def LabelChange(self):
166
-
167
- # 同じtextvariableを使用している為、ループする必要はなく1度の更新で全てに反映できる
168
-
169
- if self.var.get():
170
-
171
- [label.configure(text='削除') for label in self.InsertAndRemoveStatus]
172
-
173
- else:
174
-
175
- [label.configure(text='挿入') for label in self.InsertAndRemoveStatus]
176
-
177
-
178
-
179
- def NextPage(self):
180
-
181
- self.TemporaryMemory()
182
-
183
- self.FieldClear()
184
-
185
- self.pageid += 1
186
-
187
- self.EntryLoading()
188
-
189
-
190
-
191
- def PreviousPage(self):
192
-
193
- # 真偽値を測ってページidが0ならば処理を中断+エラーメッセージ
194
-
195
- if self.pageid == 0:
196
-
197
- messagebox.showerror('エラー', 'これ以上は前に戻れません')
198
-
199
- return
200
-
201
-
202
-
203
- self.TemporaryMemory()
204
-
205
- self.FieldClear()
206
-
207
- self.pageid -= 1
208
-
209
- self.EntryLoading()
210
-
211
-
212
-
213
- def EntryLoading(self):
214
-
215
- for (key, value), box in zip(self.data_dic.items(), self.tx_data):
216
-
217
- for widget, data in zip(box, value[self.pageid*self.colum: self.pageid*self.colum+self.colum]):
218
-
219
- widget.insert(tk.END, data)
220
-
221
-
222
-
223
- def DataRead(self):
224
-
225
- fTyp = [('', '.csv')]
226
-
227
- iDir = os.path.abspath(os.path.dirname(__file__))
228
-
229
- file_name = filedialog.askopenfilename(filetypes=fTyp, initialdir=iDir)
230
-
231
-
232
-
233
- # 真偽値を測りTrueの場合に読み込み処理、self.data_dicの内容を書き換える
234
-
235
- # pageidもリセットする
236
-
237
- if file_name:
238
-
239
- self.pageid = 0
240
-
241
- df = pd.read_csv(file_name, encoding='shift_jis', header=None)
242
-
243
- self.FieldClear()
244
-
245
- for i in df:
246
-
247
- dic = {}
248
-
249
- tmp = []
250
-
251
- for e, data in enumerate(df[i]):
252
-
253
- if e == 0:
254
-
255
- header = data
256
-
257
- else:
258
-
259
- tmp.append(data)
260
-
261
- self.data_dic[header] = tmp
262
-
263
-
264
-
265
- for (key, value), box in zip(self.data_dic.items(), self.tx_data):
266
-
267
- for data, widget in zip(value, box):
268
-
269
- widget.insert(tk.END, data)
270
-
271
-
272
-
273
- def DataSave(self):
274
-
275
- fTyp = [('', '.csv')]
276
-
277
- iDir = os.path.abspath(os.path.dirname(__file__))
278
-
279
- file_name = filedialog.asksaveasfilename(filetypes=fTyp, initialdir=iDir)
280
-
281
-
282
-
283
- # 保存時拡張子が入力されていない場合に拡張子を補完
1
+ `正常動作していない部分があった為修正中`
284
-
285
- if '.csv' not in file_name:
286
-
287
- file_name = file_name + '.csv'
288
-
289
- # 真偽値を測り、Trueの場合に書き込み処理、csv.writerを使用しlinetarminatorで行末を改行指定
290
-
291
- if file_name:
292
-
293
- with open(file_name, mode='w') as csvfile:
294
-
295
- writer = csv.writer(csvfile, lineterminator='\n')
296
-
297
- writer.writerow([key for key in self.data_dic.keys()])
298
-
299
- for index in range(len(self.data_dic['No'])):
300
-
301
- word = []
302
-
303
- for values in self.data_dic.values():
304
-
305
- word.append(values[index])
306
-
307
- writer.writerow(word)
308
-
309
- messagebox.showinfo('書き込み完了', f'{file_name}に保存しました')
310
-
311
-
312
-
313
- def FieldClear(self):
314
-
315
- # Entryウィジェット内の入力された文字列を全て消去
316
-
317
- for box in self.tx_data:
318
-
319
- for data in box:
320
-
321
- data.delete(0, tk.END)
322
-
323
-
324
-
325
- def TemporaryMemory(self):
326
-
327
- keys = [key for key in self.data_dic.keys()]
328
-
329
- for e, box in enumerate(self.tx_data):
330
-
331
- for n, widget in enumerate(box):
332
-
333
- data = widget.get()
334
-
335
- try:
336
-
337
- self.data_dic[keys[e]][n+self.pageid*self.colum] = data
338
-
339
- except:
340
-
341
- pass
342
-
343
-
344
-
345
-
346
-
347
- if __name__ == '__main__':
348
-
349
- root = tk.Tk()
350
-
351
- window = MainWindow(master = root)
352
-
353
- window.mainloop()
354
-
355
- ```