質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1193閲覧

GUIの書き込み機能を作りたい。

fuji36_om

総合スコア8

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

リストボックス

ユーザーがリストから1つ以上のアイテムを選択できるようにするGUI要素です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/09/17 01:44

前提・実現したいこと

GUIに手入力で書き込んだ後に、CSVファイルとして保存、読み込みを行いたい。

現在は、GUIの表示機能のために、no、姓 名、性別、生年月日のリストを入れているが、最終的になくし
手入力で書き込んだ内容を一時的に保存する(歯抜けの状態も保存できる)機能に作り替えたい。

できれば後述のmemory関数の部分の変更だけで済ませたいです。

発生している問題・エラーメッセージ

その行内のリストボックス内に、何も入っていなかったら、何もしない。
その行内のリストボックス内に、新しく書き込んだら、各リスト内にそれぞれ追加する。
その行内のリストボックス内に、書き込み済みなら、各リスト内に上書きする(修正内容の上書きも兼ねてる)。
そういった機能にmemory関数を書き換えたいが、うまくいかない。

現在はinvalid syntaxしかしていない。

該当のソースコード

python

1#tkinterのインポート 2import tkinter as tk 3from tkinter import messagebox 4#生年月日が適切かを確認するため、parseを使用 5from dateutil.parser import parse 6#CSVを読み込むための機能を追加 7import pandas as pd 8# ウィンドウを作成 9root = tk.Tk() 10root.title("Hello, World!") # タイトル 11root.geometry("650x300") # サイズ 12 13行数=3 14 15bt_挿入_削除=[] 16 17tx_no=[] 18tx_姓=[] 19tx_名=[] 20tx_性別=[] 21tx_生年月日=[] 22 23pageid = 0 24no = [1,2,3,4,5,6,7,8,9,10,11] 25= ["渡邊","柳川","清野","根本","阿部","稲田","木内","三宅","石村","本郷","山田"] 26= ["沙樹","和臣","菜緒","駿斗","亜依","和徳","喜雄","美南","比呂","香帆","比呂"] 27性別 = ["女","男","女","男","女","男","男","女","男","女","男"] 28生年月日 = ["1988/07/15","1966/09/04","1979/06/08","1992/03/14",\ 29 "1977/04/04","1963/11/06","1972/08/21","1992/11/30",\ 30 "1967/12/07","1965/03/20","1977/04/04"] 31# =================================== 32 33def 画面作成(): 34 y = 50 35 x = 140 36 title=['No.','姓','名','性別','生年月日'] 37 for i in title: 38 obj = tk.Label(text= i) 39 obj.place(x=x, y=y) 40 x += 80 41 y = 80 42 43 for index in range(行数): 44 x = 140 45 obj = tk.Entry(width=10) 46 obj.place(x=x, y=y) 47 tx_no.append(obj) 48 x += 80 49 obj = tk.Entry(width=10) 50 obj.place(x=x, y=y) 51 tx_姓.append(obj) 52 x += 80 53 obj = tk.Entry(width=10) 54 obj.place(x=x, y=y) 55 tx_名.append(obj) 56 x += 80 57 obj = tk.Entry(width=10) 58 obj.place(x=x, y=y) 59 tx_性別.append(obj) 60 x += 80 61 obj = tk.Entry(width=14) 62 obj.place(x=x, y=y) 63 tx_生年月日.append(obj) 64 y += 31 65 66def 削除1(): 67 print('削除1') 68 削除(0) 69 70def 削除2(): 71 print('削除2') 72 削除(1) 73 74def 削除3(): 75 print('削除3') 76 削除(2) 77 78 79def 削除(index): 80 global pageid 81 num = pageid 82 if( var.get() == True): 83 del no[num] 84 del[num] 85 del[num] 86 del 性別[num] 87 del 生年月日[num] 88 else: 89 no.insert(num, '') 90.insert(num, '') 91.insert(num, '') 92 性別.insert(num, '') 93 生年月日.insert(num, '') 94 clear() 95 画面表示() 96 97def 画面作成_ボタン(): 98 func= [削除1,削除2,削除3] 99 y = 78 100 for index in range(行数): 101 x = 50 102 obj = tk.Button(width=10,text='挿入',command = func[index]) 103 obj.place(x=x, y=y) 104 bt_挿入_削除.append(obj) 105 y += 30 106 107 Clear_button = tk.Button(root,text='クリア',command = clear) 108 Clear_button.place(width=50,x=25,y=250) 109 110 Read_button = tk.Button(root,text='読込',command = btn_read) 111 Read_button.place(width=50,x=130,y=250) 112 113 Save_button = tk.Button(root,text='保存',command = btn_save) 114 Save_button.place(width=50,x=200,y=250) 115 116 Prev_button = tk.Button(root,text='前ボタン',command = 前ページ) 117 Prev_button.place(width=50,x=330,y=250) 118 119 Next_button = tk.Button(root,text='次ボタン',command = 次ページ) 120 Next_button.place(width=50,x=400,y=250) 121 122 123#エントリーの表示 124def 画面表示(): 125 global pageid 126 for index in range(行数): 127 if((index+pageid) >= len(no)) : return 128 tx_no[index].insert(tk.END,no[index+pageid]) 129 tx_姓[index].insert(tk.END,[index+pageid]) 130 tx_名[index].insert(tk.END,[index+pageid]) 131 tx_性別[index].insert(tk.END,性別[index+pageid]) 132 tx_生年月日[index].insert(tk.END,生年月日[index+pageid]) 133 134def Memory(): 135 global pageid 136 for index in range(行数): 137 if not tx_no[index].get() and not tx_姓[index].get() and not tx_名[index].get() and not tx_性別[index].get() and not tx_生年月日[index].get(): 138 print("作業せず") 139 return 140 else: 141 for index in range(行数): 142 if tx_no[index].get(): 143 no[index+pageid] = tx_no[index].get() 144 else: 145 return 146 147 if tx_姓[index].get(): 148[index+pageid] = tx_姓[index].get() 149 else: 150 return 151 152 if tx_名[index].get(): 153[index+pageid] = tx_名[index].get() 154 else: 155 return 156 157 if tx_性別[index].get(): 158 性別[index+pageid] = tx_性別[index].get() 159 else: 160 return 161 162 if tx_生年月日[index].get(): 163 生年月日[index+pageid] = tx_生年月日[index].get() 164 else: 165 return 166 167#def check_content(): 168 169# =================================== 170 171#エントリーの全消去 172def clear(): 173 for index in range(行数): 174 tx_no[index].delete(0,tk.END) 175 tx_姓[index].delete(0,tk.END) 176 tx_名[index].delete(0,tk.END) 177 tx_性別[index].delete(0,tk.END) 178 tx_生年月日[index].delete(0,tk.END) 179 180#読み込み 181def btn_read(): 182 df = pd.read_csv('test2.csv', encoding='shift_jis',header=None) 183 no.clear() 184.clear() 185.clear() 186 性別.clear() 187 生年月日.clear() 188 189 for i in range(len(df)): 190 no.append(str(df.iloc[i, 0])) 191.append(str(df.iloc[i, 1])) 192.append(str(df.iloc[i, 2])) 193 性別.append(str(df.iloc[i, 3])) 194 生年月日.append(str(df.iloc[i, 4])) 195 clear() 196 index=0 197 画面表示() 198 199#保存 200def btn_save(): 201 with open('test.csv', mode='w') as file: 202 file.write("No,姓,名,性別,生年月日\n") 203 for index in range(len(no)): 204 s = str(no[index]) + "," + str([index])+ "," + \ 205 str([index]) + "," + str(性別[index]) + "," + str(生年月日[index]) + "\n" 206 file.write(s) 207 208def 前ページ(): 209 global pageid 210 print("btn_prev:s:", no) 211 Memory() 212 if (pageid-3) <0: 213 messagebox.showerror('エラー', 'これ以上は前に戻れません') 214 print("これ以上は前に戻れません") 215 return 216 #if check_content(): 217 #return 218 clear() 219 pageid -= 3 220 画面表示() 221 print("btn_prev:e:", no) 222 223def 次ページ(): 224 global pageid 225 print("btn_next:s:", no) 226 print(pageid) 227 Memory() 228 #if check_content(): 229 #return 230 clear() 231 pageid+=3 232 画面表示() 233 print("btn_next:e:", no) 234 print(pageid) 235 236def change(): 237 for index in range(行数): 238 if(var.get() == True): 239 print('削除') 240 bt_挿入_削除[index].config(text='削除') 241 else: 242 print('挿入') 243 bt_挿入_削除[index].config(text='挿入') 244 245ar = tk.BooleanVar() 246t_btn = tk.Checkbutton(variable=var, text="挿入 / 削除",command = change) 247t_btn.place(x=40, y=50) 248 249# =================================== 250 251画面作成() 252画面作成_ボタン() 253画面表示() 254root.mainloop( ) 255

試したこと

memory部分を変更して、目的とする機能を追加したいが思いつかない。

python

1def Memory(): 2 global pageid 3 for index in range(行数): 4 if not tx_no[index].get() and not tx_姓[index].get() and not tx_名[index].get() and not tx_性別[index].get() and not tx_生年月日[index].get(): 5 print("作業せず") 6 return 7 else: 8 for index in range(行数): 9 if len(no) >= no[index+pageid] 10 no[index+pageid] = tx_no[index].get() 11 else: 12 no[index+pageid].append(tx_no[index]) 13 14 for index in range(行数): 15 if len() >=[index+pageid] 16[index+pageid] = tx_姓[index].get() 17 else: 18[index+pageid].append(tx_姓[index]) 19 20 for index in range(行数): 21 if len() >=[index+pageid] 22[index+pageid] = tx_名[index].get() 23 else: 24[index+pageid].append(tx_名[index]) 25 26 for index in range(行数): 27 if len(性別) >= 性別[index+pageid] 28 性別[index+pageid] = tx_性別[index].get() 29 else: 30 性別[index+pageid].append(tx_性別[index]) 31 32 for index in range(行数): 33 if len(生年月日) >= 生年月日[index+pageid] 34 生年月日[index+pageid] = tx_生年月日[index].get() 35 else: 36 生年月日[index+pageid].append(tx_生年月日[index])

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

日本語コードが読みづらく、1から作り直させていただきました。
(classによるフォーマットで申し訳御座いません。)

データは辞書形式で、Entryウィジェットなどもリストで管理しているので各種応用がしやすいと思います。
ページを切り替えた場合のデータの保存も
遷移時のEntry取得→辞書を更新→Entryの中身削除→辞書から次のページデータを表示
という形で再現しております。

python

1import os 2import csv 3import pandas as pd 4import tkinter as tk 5from tkinter import messagebox 6from tkinter import filedialog 7 8class MainWindow(tk.Frame): 9 def __init__(self, master): 10 super().__init__(master) 11 self.master.title('Hello, World!') 12 self.master.geometry('650x300') 13 14 # 各種事前定義 15 self.data_dic = {'No': ['1','2','3','4','5','6','7','8','9','10','11'], 16 '姓': ['渡邊','柳川','清野','根本','阿部','稲田','木内','三宅','石村','本郷','山田'], 17 '名': ['沙樹','和臣','菜緒','駿斗','亜依','和徳','喜雄','美南','比呂','香帆','比呂'], 18 '性別': ['女','男','女','男','女','男','男','女','男','女','男'], 19 '生年月日': ['1988/07/15','1966/09/04','1979/06/08','1992/03/14','1977/04/04', 20 '1963/11/06','1972/08/21','1992/11/30','1967/12/07','1965/03/20','1977/04/04'] 21 } 22 self.colum = 3 23 self.title = [key for key in self.data_dic.keys()] 24 self.tx_data = [list() for i in range(len(self.title))] 25 self.InsertAndRemoveStatus = [] 26 self.pageid = 0 27 28 # 各種ウィジェット生成 29 self.CreateWidget() 30 31 ##### メインとなるウィジェットの生成 32 def CreateWidget(self): 33 ############################## 34 # Label及びEntryの生成 35 y = 50 36 x = 140 37 for i in self.title: 38 tk.Label(self.master, text=i).place(x=x, y=y) 39 x += 80 40 41 y = 80 42 for i in range(self.colum): 43 x = 140 44 for e, box in enumerate(self.tx_data): 45 width = 10 46 if e == 4: 47 width = 14 48 obj = tk.Entry(self.master, width=width) 49 obj.place(x=x, y=y) 50 box.append(obj) 51 x += 80 52 y += 31 53 54 ############################## 55 # 辞書データをEntryに挿入していく 56 for (key, value), box in zip(self.data_dic.items(), self.tx_data): 57 for data, widget in zip(value, box): 58 widget.insert(tk.END, data) 59 60 ############################## 61 # Button関連の生成 62 self.var = tk.BooleanVar() 63 tk.Checkbutton(variable=self.var, text="挿入 / 削除",command =self.LabelChange).place(x=40, y=50) 64 65 x = 50 66 y = 78 67 for i in range(self.colum): 68 obj = tk.Button(self.master, width=10, text='挿入') 69 obj.place(x=x, y=y) 70 self.InsertAndRemoveStatus.append(obj) 71 y += 30 72 73 button_data = {'クリア':[25, self.FieldClear], '読込':[130, self.DataRead], '保存': [200, self.DataSave], 74 '前ボタン': [330, self.PreviousPage], '次ボタン':[400, self.NextPage]} 75 for key, value in button_data.items(): 76 tk.Button(self.master, text=key, command=value[1]).place(width=50, x=value[0], y=250) 77 78 ##### Button Event 79 def LabelChange(self): 80 # 行数でループするのではなく直接buttonを格納しているリストから更新する事で簡潔に済む 81 if self.var.get(): 82 [label.configure(text='削除') for label in self.InsertAndRemoveStatus] 83 else: 84 [label.configure(text='挿入') for label in self.InsertAndRemoveStatus] 85 86 def NextPage(self): 87 self.TemporaryMemory() 88 self.FieldClear() 89 self.pageid += 1 90 self.EntryLoading() 91 92 def PreviousPage(self): 93 # 真偽値を測ってページidが0ならば処理を中断+エラーメッセージ 94 if self.pageid == 0: 95 messagebox.showerror('エラー', 'これ以上は前に戻れません') 96 return 97 98 self.TemporaryMemory() 99 self.FieldClear() 100 self.pageid -= 1 101 self.EntryLoading() 102 103 def EntryLoading(self): 104 for (key, value), box in zip(self.data_dic.items(), self.tx_data): 105 for widget, data in zip(box, value[self.pageid*self.colum: self.pageid*self.colum+self.colum]): 106 widget.insert(tk.END, data) 107 108 def DataRead(self): 109 fTyp = [('', '.csv')] 110 iDir = os.path.abspath(os.path.dirname(__file__)) 111 file_name = filedialog.askopenfilename(filetypes=fTyp, initialdir=iDir) 112 113 # 真偽値を測りTrueの場合に読み込み処理、self.data_dicの内容を書き換える 114 # pageidもリセットする 115 if file_name: 116 self.pageid = 0 117 df = pd.read_csv(file_name, encoding='shift_jis', header=None) 118 df = df.fillna('') 119 self.FieldClear() 120 for i in df: 121 dic = {} 122 tmp = [] 123 for e, data in enumerate(df[i]): 124 if e == 0: 125 header = data 126 else: 127 tmp.append(data) 128 self.data_dic[header] = tmp 129 130 for (key, value), box in zip(self.data_dic.items(), self.tx_data): 131 for data, widget in zip(value, box): 132 widget.insert(tk.END, data) 133 134 def DataSave(self): 135 fTyp = [('', '.csv')] 136 iDir = os.path.abspath(os.path.dirname(__file__)) 137 file_name = filedialog.asksaveasfilename(filetypes=fTyp, initialdir=iDir) 138 139 # 保存時に拡張子が入力されていない場合に拡張子を補完 140 if '.csv' not in file_name: 141 file_name = file_name + '.csv' 142 # 真偽値を測り、Trueの場合に書き込み処理、csv.writerを使用しlinetarminatorで行末を改行指定 143 if file_name: 144 self.TemporaryMemory() 145 with open(file_name, mode='w') as csvfile: 146 writer = csv.writer(csvfile, lineterminator='\n') 147 writer.writerow([key for key in self.data_dic.keys()]) 148 for index in range(len(self.data_dic['No'])): 149 word = [] 150 for values in self.data_dic.values(): 151 word.append(values[index]) 152 writer.writerow(word) 153 messagebox.showinfo('書き込み完了', f'{file_name}に保存しました') 154 155 def FieldClear(self): 156 # Entryウィジェット内の入力された文字列を全て消去 157 for box in self.tx_data: 158 for data in box: 159 data.delete(0, tk.END) 160 161 def TemporaryMemory(self): 162 keys = [key for key in self.data_dic.keys()] 163 for e, box in enumerate(self.tx_data): 164 for n, widget in enumerate(box): 165 data = widget.get() 166 try: 167 self.data_dic[keys[e]][n+self.pageid*self.colum] = data 168 except: 169 pass 170 171 172if __name__ == '__main__': 173 root = tk.Tk() 174 window = MainWindow(master = root) 175 window.mainloop()

投稿2020/09/17 11:09

編集2020/09/17 11:59
nto

総合スコア1438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuji36_om

2020/09/17 13:26

ご回答、ありがとうございます。 今回要望にmemory meomoryとうるさく書いたのは、私自身独学でまだまだ初心者の域を出ることができず、自身の親類に、潰しがきくがひどく気難しいSEに講師を頼んでいる背景にあります。 親類の提唱する「教えない指導」に疑問を呈しつつも相槌をうち、言葉巧みに情報を抜いて学習しつつ、どうしても教えてもらえない、かつ自力で解決できない場合、このサイトを活用しております。 単刀直入に回答してくれ、すねもせず、嫌味も言わず、かつ褒めて育てるような講師なら最高だったのですが。 一応、今作っているプログラムがその親類との共通の話題なので、自分が意味を知らない単語を使われると、内容が理解できない、昨日から飛躍しすぎた内容では相手と会話ができないため、今回は別の方の案を採用しました。
guest

0

ベストアンサー

要望でMemory関数を修正するとなるとこんな感じかと。

python

1def Memory(): 2 global pageid 3 for index in range(行数): 4 if not tx_no[index].get() and not tx_姓[index].get() and not tx_名[index].get() and not tx_性別[index].get() and not tx_生年月日[index].get(): 5 print("作業せず") 6 else: 7 for i in range(len(no), index+pageid+1): 8 no.append('') 9.append('') 10.append('') 11 性別.append('') 12 生年月日.append('') 13 14 no[index+pageid] = tx_no[index].get() 15[index+pageid] = tx_姓[index].get() 16[index+pageid] = tx_名[index].get() 17 性別[index+pageid] = tx_性別[index].get() 18 生年月日[index+pageid] = tx_生年月日[index].get()

まずEntryヴィジェット全てが未入力でreturnしてしまっていますが、
三行分あるのでこのままだと一行目が全て未入力で、
二行目以降に追加や修正がある場合はそれが無視されてしまいます。

またlistより大きい位置Entryヴィジェットに入力があった場合は、
そのサイズ分まで空文字要素を追加する方法で対処しています。

投稿2020/09/17 07:47

yureighost

総合スコア2183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuji36_om

2020/09/17 10:06

す、すごい!動きました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問