Q&A
前提
Tkinterでアプリケーションを作成したのですが、データの数によってウィンドウの大きさが左右されるため、データが表示された範囲まで追えるように上下のスクロールバーで操作できるようにしたいと考えております。
実現したいこと
下記コードのアプリケーションのウィンドウにY軸のスクロールバーを追加して、データがウィンドウからはみ出した際に全て閲覧できるようにしたい。
発生している問題・エラーメッセージ
該当のソースコード
Python
1from tkinter import * 2 3class Application(Frame): 4 def __init__(self, master): 5 super().__init__(master) 6 7 master.geometry('1000x850') 8 master.title('DAアルゴリズムによるマッチングアプリ') 9 master.resizable(False, True) 10 11 canvas = Canvas(master) 12 13 bar = Scrollbar(self.master, orient=VERTICAL) 14 bar.pack(side=RIGHT, fill=Y) 15 bar.config(command=canvas.yview) 16 17 canvas.config(yscrollcommand=bar.set) 18 canvas.config(scrollregion=(0, 0, 0, 10000)) 19 canvas.bind_all('<MouseWheel>', lambda eve: canvas.yview_scroll(int(-eve.delta/120), 'units')) 20 canvas.pack(side=LEFT, fill=BOTH, expand=True) 21 22 self.frame = Frame(canvas) 23 24 canvas.create_window((0, 0), window=self.frame, anchor=NW) 25 26 self.widget1() 27 self.label_lst = [] 28 self.entry_lst = [] 29 self.button_lst = [] 30 self.s_prefs = [] 31 self.c_prefs = [] 32 33 def widget1(self): 34 Label(self.frame, text='学生の人数を入力 >>').grid(row=0, column=0, pady=5) 35 self.f1 = IntVar(value='') 36 Entry1 = Entry(self.frame, textvariable=self.f1, width=5).grid(row=0, column=1, pady=5) 37 38 Label(self.frame, text='研究室の数を入力 >>').grid(row=0, column=2, pady=5) 39 self.f2 = IntVar(value='') 40 Entry2 = Entry(self.frame, textvariable=self.f2, width=5).grid(row=0, column=3, pady=5) 41 42 Button1 = Button(self.frame, text='OK', command=self.btn1_clicked, width=5).grid(row=0, column=4, pady=5) 43 44 def btn1_clicked(self): 45 S = self.f1.get() 46 C = self.f2.get() 47 48 for i in range(S): 49 label = Label(self.frame, text=['学生',i+1,'の希望順に研究室の番号をスペース区切りで入力 >>']).grid(row=i+1, column=0, pady=5) 50 self.f_s_pref = StringVar(value='') 51 self.s_prefs.append(self.f_s_pref) 52 entry = Entry(self.frame, textvariable=self.f_s_pref, width=40).grid(row=i+1, column=1, pady=5) 53 self.label_lst.append(label) 54 self.entry_lst.append(entry) 55 56 button = Button(self.frame, text='OK', command=self.btn2_clicked, width=5).grid(row=S, column=2, pady=5) 57 self.button_lst.append(button) 58 59 def btn2_clicked(self): 60 S = self.f1.get() 61 C = self.f2.get() 62 63 for i in range(C): 64 label = Label(self.frame, text=['研究室',i+1,'の希望順に学生の番号をスペース区切りで入力 >>']).grid(row=S+1+i, column=0, pady=5) 65 self.f_c_pref = StringVar(value='') 66 self.c_prefs.append(self.f_c_pref) 67 entry = Entry(self.frame, textvariable=self.f_c_pref, width=40).grid(row=S+1+i, column=1, pady=5) 68 self.label_lst.append(label) 69 self.entry_lst.append(entry) 70 71 button = Button(self.frame, text='OK', command=self.btn3_clicked, width=5).grid(row=S+1+i, column=2, pady=5) 72 self.button_lst.append(button) 73 74 def btn3_clicked(self): 75 S = self.f1.get() 76 C = self.f2.get() 77 78 label = Label(self.frame, text=['研究室1から順に定員をスペース区切りで入力 >>']).grid(row=S+C+1, column=0, pady=5) 79 self.f_capa = StringVar(value='') 80 entry = Entry(self.frame, textvariable=self.f_capa, width=20).grid(row=S+C+1, column=1, pady=5) 81 self.label_lst.append(label) 82 self.entry_lst.append(entry) 83 84 button = Button(self.frame, text='OK', command=self.btn4_clicked, width=5).grid(row=S+C+1, column=2, pady=5) 85 self.button_lst.append(button) 86 87 def btn4_clicked(self): 88 S = self.f1.get() 89 C = self.f2.get() 90 91 s_prefs = [i.get().split() for i in self.s_prefs] 92 for i in range(S): 93 for j in range(C): 94 s_prefs[i][j] = int(s_prefs[i][j]) 95 96 c_prefs = [i.get().split() for i in self.c_prefs] 97 for i in range(C): 98 for j in range(S): 99 c_prefs[i][j] = int(c_prefs[i][j]) 100 101 c_rank = [[0]*S for i in range(C)] 102 for i in range(C): 103 for j in range(S): 104 k = c_prefs[i][j] 105 c_rank[i][k-1] = j+1 106 107 capacity = [int(s) for s in self.f_capa.get().split()] 108 s_matched = [0]*(S+1) 109 c_matched = [[0]*(S+1) for i in range(C)] 110 num_match = 0 111 s_filled = [0]*(S+1) 112 c_filled = [0]*C 113 position = [0]*(S+1) 114 115 t = 1 116 while num_match < S: 117 for i in range(S): 118 if s_filled[i]==0: 119 j = s_prefs[i][position[i]]-1 120 if c_filled[j]<capacity[j]: 121 c_matched[j][i] = 1 122 s_matched[i] = j 123 s_filled[i] = 1 124 c_filled[j] += 1 125 num_match += 1 126 127 else: 128 temp = -1 129 rejected = S 130 for k in range(S): 131 if c_matched[j][k]==1: 132 if c_rank[j][i] < c_rank[j][k] and c_rank[j][k] > temp: 133 s_filled[rejected] = 1 134 position[rejected] -= 1 135 c_matched[j][rejected] = 1 136 s_matched[rejected] = j 137 s_filled[k] = 0 138 position[k] += 1 139 rejected = k 140 c_matched[j][k] = 0 141 temp = c_prefs[j][k] 142 143 if temp > -1: 144 c_matched[j][i] = 1 145 s_matched[i] = j 146 s_filled[i] = 1 147 else: 148 position[i] += 1 149 if position[i]==C: 150 s_matched[i] = -1 151 s_filled[i] = 1 152 num_match += 1 153 t += 1 154 155 Label(self.frame, text='マッチング結果').grid(row=S+C+2, column=0, pady=5) 156 for i in range(S): 157 if s_matched[i]==-1: 158 label = Label(self.frame, text='学生{0}:'.format(i+1)).grid(row=S+C+3+i, column=0, pady=5) 159 self.label_lst.append(label) 160 else: 161 label = Label(self.frame, text='学生{0}: 研究室{1}'.format(i+1, s_matched[i]+1)).grid(row=S+C+3+i, column=0, pady=5) 162 self.label_lst.append(label) 163 164 for j in range(C): 165 if c_filled[j]==0: 166 label = Label(self.frame, text=': 研究室{0}'.format(j+1)).grid(row=S+C+3+i, column=1, pady=5) 167 self.label_lst.apppend(label) 168 169def main(): 170 root = Tk() 171 app = Application(master = root) 172 app.mainloop() 173 174if __name__ == '__main__': 175 main()
試したこと
検索した上位のサイトからframeやcanvas, scrollbarを用いたコードを何個か書いてみて、そこから援用しようと試みたのですが、私の理解が浅いことで自分のコードに上手く落とし込めず理想の形にすることができませんでした。
参考: https://kuroro.blog/python/vgx53M7D1d6C0R8ejp0V/
https://qiita.com/shinno1993/items/3ea14ffd7f17d8214961
https://blog.teclado.com/tkinter-scrollable-frames/
https://daeudaeu.com/scrollbar/
補足情報(FW/ツールのバージョンなど)
回答1件
あなたの回答
tips
プレビュー
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
2022/10/22 21:53
2022/10/23 05:41 編集