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

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

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

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

Python

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

Q&A

解決済

4回答

291閲覧

Pythonスクロールバーが機能しない。

probably

総合スコア1

Tkinter

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

Python

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

1グッド

0クリップ

投稿2025/01/21 13:13

実現したいこと

TkinterのGUIを作成しています。TreeViewを使用し、表のウィンドウをGUIに表示しています。そのウィンドウに横スクロール、縦スクロールできるようにスクロールバーをつけたいです。

発生している問題・分からないこと

スクロールバーらしきものは表示されるのですが、機能しません。どうか教えていただけますと幸いです。

該当のソースコード

Python

1import tkinter as tk 2from tkinter import ttk, filedialog, messagebox 3import pandas as pd 4import os 5import subprocess 6 7class SearchApp: 8 def __init__(self, root): 9 self.root = root 10 self.root.title("顧客検索システム") 11 12 # デフォルトのCSVデータファイル(仮) 13 self.default_db_path = r"C:\\Users\\proba\\Desktop\\animal_hospital_index\\animal_customer_db.csv" 14 15 # CSVデータを格納するDataFrame 16 self.df = None # 仮に空のデータフレームで初期化(後で実際のデータを読み込む) 17 self.load_default_database() # データベースをロード 18 19 # メインフレーム 20 self.main_frame = ttk.Frame(root) 21 self.main_frame.grid(row=0, column=0, padx=10, pady=10) 22 23 # 検索条件の入力フィールド 24 self.name_label = ttk.Label(self.main_frame, text="顧客名(カタカナ)") 25 self.name_label.grid(row=0, column=0, padx=5, pady=5, sticky="e") 26 self.name_entry = ttk.Entry(self.main_frame) 27 self.name_entry.grid(row=0, column=1, padx=5, pady=5) 28 29 self.pet_name_label = ttk.Label(self.main_frame, text="ペット名(カタカナ)") 30 self.pet_name_label.grid(row=1, column=0, padx=5, pady=5, sticky="e") 31 self.pet_name_entry = ttk.Entry(self.main_frame) 32 self.pet_name_entry.grid(row=1, column=1, padx=5, pady=5) 33 34 self.phone_label = ttk.Label(self.main_frame, text="電話番号の下四桁") 35 self.phone_label.grid(row=2, column=0, padx=5, pady=5, sticky="e") 36 self.phone_entry = ttk.Entry(self.main_frame) 37 self.phone_entry.grid(row=2, column=1, padx=5, pady=5) 38 39 # 検索ボタン 40 self.search_button = ttk.Button(self.main_frame, text="検索", command=self.search) 41 self.search_button.grid(row=3, column=0, columnspan=2, pady=10) 42 43 # Treeviewフレーム 44 self.tree_frame = ttk.Frame(root, width=800, height=300) # フレームのサイズを調整 45 self.tree_frame.grid(row=1, column=0, padx=10, pady=10, sticky="nsew") 46 47 # 横スクロールバー 48 self.tree_scroll_x = ttk.Scrollbar(self.tree_frame, orient="horizontal") 49 self.tree_scroll_x.pack(side="bottom", fill="x") 50 51 # 縦スクロールバー 52 self.tree_scroll_y = ttk.Scrollbar(self.tree_frame, orient="vertical") 53 self.tree_scroll_y.pack(side="right", fill="y") 54 55 # Treeviewウィジェットの作成(固定高さ・幅) 56 self.tree = ttk.Treeview(self.tree_frame, columns=("customer_id", "name_kanji", "name_katakana", "pet_kind", "pet_name", "pet_name_katakana", "pet_birth", "pet_sex", "telephone_number", "cellphone_number", "adress"), 57 show='headings', xscrollcommand=self.tree_scroll_x.set, yscrollcommand=self.tree_scroll_y.set, 58 height=15) # 高さを15行に設定(適宜調整) 59 60 self.tree.pack(side="left", fill="both", expand=True) 61 62 # スクロールバーとTreeviewの連携 63 self.tree_scroll_x.config(command=self.tree.xview) 64 self.tree_scroll_y.config(command=self.tree.yview) 65 66 # カラムの設定 67 columns = ["customer_id", "name_kanji", "name_katakana", "pet_kind", "pet_name", "pet_name_katakana", "pet_birth", "pet_sex", "telephone_number", "cellphone_number", "adress"] 68 for col in columns: 69 self.tree.heading(col, text=col) 70 self.tree.column(col, width=100, anchor="center") # 列の幅を設定 71 72 # ソースボタン 73 self.source_button = ttk.Button(root, text="ソース", command=self.open_source) 74 self.source_button.grid(row=2, column=0, pady=10) 75 76 def load_default_database(self): 77 """デフォルトのデータベースを読み込む""" 78 try: 79 self.df = pd.read_csv(self.default_db_path, encoding='utf-8') 80 except Exception as e: 81 print(f"デフォルトのデータベースを読み込む際にエラーが発生しました:\n{e}") 82 83 def open_source(self): 84 """CSVファイルを開く""" 85 try: 86 if os.path.exists(self.default_db_path): 87 subprocess.Popen(["notepad", self.default_db_path]) 88 else: 89 messagebox.showerror("エラー", "データベースファイルが存在しません。") 90 except Exception as e: 91 messagebox.showerror("エラー", f"CSVファイルを開く際にエラーが発生しました:\n{e}") 92 93 def search(self): 94 """検索機能の実装""" 95 if self.df is None: 96 print("データベースが読み込まれていません。") 97 return 98 99 name_katakana = self.name_entry.get() 100 pet_name_katakana = self.pet_name_entry.get() 101 phone_last4 = self.phone_entry.get() 102 103 # 条件を動的に構築 104 conditions = [] 105 if name_katakana: 106 conditions.append(self.df['name_katakana'].str.contains(name_katakana, na=False)) 107 if pet_name_katakana: 108 conditions.append(self.df['pet_name_katakana'].str.contains(pet_name_katakana, na=False)) 109 if phone_last4: 110 conditions.append((self.df['telephone_number'].astype(str).str[-4:].str.contains(phone_last4, na=False)) | 111 (self.df['cellphone_number'].astype(str).str[-4:].str.contains(phone_last4, na=False))) 112 113 # 条件が1つ以上ある場合にフィルタリング 114 if conditions: 115 result_df = self.df[conditions[0]] 116 for condition in conditions[1:]: 117 result_df = result_df[condition] 118 else: 119 result_df = self.df # 条件がない場合は全データ 120 121 # Treeviewウィジェットのクリア 122 for i in self.tree.get_children(): 123 self.tree.delete(i) 124 125 # 結果をTreeviewに表示 126 for _, row in result_df.iterrows(): 127 self.tree.insert("", "end", values=list(row)) 128 129# アプリケーションの実行 130if __name__ == "__main__": 131 root = tk.Tk() 132 app = SearchApp(root) 133 root.mainloop() 134

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

横スクロールを試している方の投稿を見たのですが、解決できませんでした。

補足

特になし

melian👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

Treeview 用の frame は grid() メソッドで配置していますが、TreeviewScrollbarpack() メソッドを使用しています。なので、self.tree_frame.pack_propagate(False) を追加するとよいかと思います。

python

1 # Treeviewフレーム 2 self.tree_frame = ttk.Frame(root, width=800, height=300) # フレームのサイズを調整 3 self.tree_frame.grid(row=1, column=0, padx=10, pady=10, sticky="nsew") 4 # 追加 5 self.tree_frame.pack_propagate(False)

それから、self.tree.column()stretch=False を追加します。これは、列の幅を変更した際に横スクロールバーの幅が frame の幅に合わせられてしまうのを防ぐためです。

python

1 # カラムの設定 2 columns = ["customer_id", "name_kanji", "name_katakana", "pet_kind", "pet_name", "pet_name_katakana", "pet_birth", "pet_sex", "telephone_number", "cellphone_number", "adress"] 3 for col in columns: 4 self.tree.heading(col, text=col) 5 # stretch=False を追加 6 self.tree.column(col, width=100, anchor="center", stretch=False) # 列の幅を設定

イメージ説明

投稿2025/01/21 18:05

編集2025/01/21 18:52
melian

総合スコア20905

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

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

teamikl

2025/01/22 02:18

問題の原因を把握しないと、スクロールバーが機能しても その後にレイアウトを調整したい時に困る事になると思ったので こちら情報補足させて貰います。 stretch=False の情報に +1 ==== スクロールバーは、表示幅が足りてるときには機能しません。 その為、イベントハンドラ等の設定に問題がなくても、 レイアウト次第で機能しないことがあります。 例えば、リサイズ時の挙動で違いが出るのではないかな、 カラム幅を固定したままグリッド全体は伸縮可能にしたいといった場合 こちらの解決策を取った場合のコードからだと root.grid_columnconfigure(0, weight=1) を追加したとき 目的のレイアウト次第ですが、ウィジェット構成 外側 root(grid) 内側 tree_frame(pack) という状況で 外側の propagate を False にすると内側迄サイズ変更が伝達されなくなります。 スクロールの機能自体は問題ありませんが、 レイアウト的には 内側の propagateだけ設定する方が、他への影響が最小限です。
probably

2025/01/22 09:40

解決いたしました。 無事スクロールを機能させることができました。 どの部分にどんなコードを入れるのかとても分かりやすいです。 もし自分が解決策を渡す立場になった時の参考にさせていただきます。 根本解決のため、strech=Falseについても深堀していただきありがとうございました。
guest

0

重要な要素のみ引き抜いて実装しています。
下記のようにgrid_propagateなどの設定をした際には正常にスクロールバーが適用されていました。
個人的な書き癖があるので、適宜変更しながら適用してみてください。

python

1import tkinter as tk 2 3from tkinter import ttk 4from typing import Self 5 6class Application (): 7 def __init__ (self: Self) -> None: 8 """インスタンスの初期化処理 9 """ 10 self._build_gui() 11 12 def _build_gui (self: Self) -> None: 13 """GUIの構築 14 """ 15 16 """ルート領域 17 """ 18 root: tk.Tk = tk.Tk() 19 root.title(u'顧客検索システム') 20 21 """メインフレーム 22 """ 23 main_frame: ttk.Frame = ttk.Frame(root) 24 main_frame.grid(column = 0, padx = 10, pady = 10, row = 0) 25 26 """TreeViewのフレーム 27 """ 28 tree_frame: ttk.Frame = ttk.Frame(main_frame, height = 300, width = 800) 29 tree_frame.grid(column = 0, row = 0, sticky = tk.NSEW) 30 tree_frame.columnconfigure(0, weight = 1) 31 tree_frame.rowconfigure(0, weight = 1) 32 tree_frame.grid_propagate(False) 33 34 """後で使うヘッダー 35 """ 36 column_headers: list[str] = ['customer_id', 'name_kanji', 'name_katakana', 'pet_kind', 'pet_name', 'pet_name_katakana', 'pet_birth', 'pet_sex', 'telephone_number', 'cellphone_number', 'adress'] 37 38 """TreeViewの設置 39 """ 40 treeview: ttk.Treeview = ttk.Treeview(tree_frame, columns = column_headers, height = 15, show = 'headings') 41 treeview.grid(column= 0, row = 0) 42 43 """横方向スクロールバーの設置 44 """ 45 scrollbar_x: ttk.Scrollbar = ttk.Scrollbar(tree_frame, orient = tk.HORIZONTAL) 46 scrollbar_x.config(command = treeview.xview) 47 scrollbar_x.grid(column = 0, row = 1, sticky = tk.EW) 48 49 """縦方向スクロールバーの設置 50 """ 51 scrollbar_y: ttk.Scrollbar = ttk.Scrollbar(tree_frame, orient = tk.VERTICAL) 52 scrollbar_y.config(command = treeview.yview) 53 scrollbar_y.grid(column = 1, row = 0, sticky = tk.NS) 54 55 """スクロールバーの関連付け 56 """ 57 treeview.configure(xscrollcommand = scrollbar_x.set, yscrollcommand = scrollbar_y.set) 58 59 """カラムの設定 60 """ 61 column_text: str 62 for column_text in column_headers: 63 treeview.heading(column_text, text = column_text) 64 treeview.column(column_text, anchor = tk.CENTER, width = 150) 65 66 """サンプルデータ書き込み 67 """ 68 for i in range(10): 69 treeview.insert('', tk.END, values = [i, i, i, i, i]) 70 71 """変数の関連付け 72 """ 73 self._root = root 74 self._main_frame = main_frame 75 self._tree_frame = tree_frame 76 self._treeview = treeview 77 self._scrollbar_x = scrollbar_x 78 self._scrollbar_y = scrollbar_y 79 80 def show (self: Self) -> None: 81 """ウィンドウの表示 82 """ 83 self._root.mainloop() 84 85 @staticmethod 86 def launch () -> None: 87 """起動処理 88 """ 89 app: Application = Application() 90 app.show() 91 92if __name__ == '__main__': 93 Application.launch()

投稿2025/01/21 15:37

Refrain

総合スコア646

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

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

0

投稿2025/01/21 14:06

Refrain

総合スコア646

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

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

probably

2025/01/21 14:21

とても早くご回答いただけて驚いています。 ありがとうございます。 リンク済ませていただきました。 _InFrame_.grid_propagate(False) このコードを参考に # メインフレーム self.main_frame = ttk.Frame(root)   self.grid_propagate(False) self.main_frame.grid(row=0, column=0, padx=10, pady=10) とすれば、良いのでしょうか。 Treeviewでの編集はしない予定です。 明日試そうと思います。
Refrain

2025/01/21 15:37

<pre>を使いたいため、改めて回答に入れさせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.33%

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

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

質問する

関連した質問