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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

Q&A

解決済

2回答

1940閲覧

Python3 Tkinter スクロールバーを使わずにスクロールしたい

person

総合スコア224

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

0グッド

0クリップ

投稿2021/04/05 15:20

TkinterのTreeviewで表を表示しています。

これをスクロールしたいです。ただ、諸事情によりスクロールバーを使わずボタンのみで実現したいです。

なんとなく次のように方法を考えました。

例えばウィンドウに5行表示されていて、次の行を表示したい場合、
表示されている最下行の次の行を取得して、次の行があれば次の行をウィンドウ上に表示されるようにtree.see()する。

ただ、この方法だとウィンドウに表示される行数列数が決まっている必要があり、適時取得できないと実現できないと思いました。

また、スクロールというよりは行列の位置を1行ずつまたは1列ずつ移動しているで、1クリックで大幅に表示位置が移動してしまうような気がしました。

ボタンでスクロールするいい方法があったら教えてほしいです。

下記のpush_button1(),push_button2(),push_button3(),push_button4()を押したときの処理について考えています。

Python

1from tkinter import ttk 2import tkinter as tk 3 4class App: 5 def __init__(self, win): 6 self.win = win 7 self.win.geometry("400x300") 8 self.create_view() 9 10 def create_view(self): 11 self.win.rowconfigure(tuple(range(2)), weight=1) 12 self.win.columnconfigure(tuple(range(2)), weight=1) 13 14 columns = 5 15 data = [] 16 for i in range(0, 100, 5): 17 data.append([i, i+1, i+2, i+3, i+4]) 18 self.tree = ttk.Treeview(self.win) 19 self.tree.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew", padx=5, pady=5) 20 self.tree["columns"] = tuple(range(1, columns + 1)) 21 self.tree["show"] = "headings" 22 w = self.win.winfo_width() 23 ww = int(w / 7) 24 for i in range(1, columns + 1): 25 self.tree.heading(i, text="Data"+str(i)) 26 self.tree.column(i, width=ww) 27 for i in data: 28 self.tree.insert("", "end", value=(i)) 29 30 self.button1 = tk.Button(self.win, text="▲", command=self.push_button1) 31 self.button1.grid(row=0, column=2, sticky="nsew") 32 self.button2 = tk.Button(self.win, text="▼", command=self.push_button2) 33 self.button2.grid(row=1, column=2, sticky="nsew") 34 self.button3 = tk.Button(self.win, text="◀", command=self.push_button3) 35 self.button3.grid(row=2, column=0, sticky="nsew") 36 self.button4 = tk.Button(self.win, text="▶", command=self.push_button4) 37 self.button4.grid(row=2, column=1, sticky="nsew") 38 39 def push_button1(self): 40 print("push_button1") 41 42 def push_button2(self): 43 print("push_button2") 44 45 def push_button3(self): 46 print("push_button3") 47 48 def push_button4(self): 49 print("push_button4") 50 51 52def main(): 53 win = tk.Tk() 54 App(win) 55 win.mainloop() 56 57if __name__ == "__main__": 58 main()

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

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

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

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

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

guest

回答2

0

ベストアンサー

Treeviewのxview/yview メソッド呼び出しで、
スクロールバーを操作した時の挙動を模倣する事が出来ます。

python

1 def push_button1(self): 2 self.tree.yview("scroll", -1, "units") 3 4 def push_button2(self): 5 self.tree.yview("scroll", +1, "units")

スクロールバーの挙動 y_scrollbar["command"] = tree.yview とした時
yview を、以下の引数で呼び出します

  • 両端のボタンを押したとき ... 行単位スクロール "scroll", 1, "units"
  • スライダーをドラッグした時 ... 指定位置に移動 "moveto"
  • その他の範囲を押したとき ... ページ単位スクロール "scroll", 1, "pages"

横スクロールも同様に xview メソッド呼び出しで可能ですが、
現状のレイアウトでは、スクロールしても表示の変化はありません。


1行ずつのスクロールでは、件数が大きくなってくると
ボタンの連打することになるので、あまり使い勝っては良くありません。
スムーズなスクロールを実装したい場合は、タイマーを使い対応します。

  • ボタンを押したときにタイマー起動、一定時間毎にスクロールを呼び出し
  • ボタンを離したときにタイマーを解除 (after_cancel)

投稿2021/04/06 01:23

teamikl

総合スコア8760

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

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

person

2021/04/06 13:30 編集

ありがとうございます。 > 横スクロールも同様に xview メソッド呼び出しで可能ですが、 > 現状のレイアウトでは、スクロールしても表示の変化はありません。 列幅を引き伸ばしてからボタンを押すとほんの少しだけ横に動きました("units"の場合)。 xとyで移動の仕方が違うんですかね?
teamikl

2021/04/06 17:26

ウィジェットのwidth, height に準拠しますが、 tkinter の場合、ウィジェットによっては、 文字数だったりピクセル数?だったりします。 挙動的には、yは1行単位、xはピクセル単位で動いてそうですね。 例えば、 > ウィンドウに表示される行数列数が決まっている必要があり、適時取得できないと実現できないと思いました。 height で表示行数を設定できますが、 width は表示カラム数という訳ではありません。 (列数は columns や displaycolums) self.tree.column(i, width=ww) で指定するwidth の幅なので、 均等にカラム幅が決まってるなら、 スクロールする値を ww "units" にすれば、1カラム分移動することになります。 (レイアウトが固定でない場合は、カラム幅はリサイズで変わるので、ww の値はその都度計算)
guest

0

コードにttk.Scrollbarを追加して、他のボータンがいらないです。

python

1from tkinter import ttk 2import tkinter as tk 3 4class App: 5 def __init__(self, win): 6 self.win = win 7 self.win.geometry("400x300") 8 self.create_view() 9 10 def create_view(self): 11 self.win.rowconfigure(tuple(range(2)), weight=1) 12 self.win.columnconfigure(tuple(range(2)), weight=1) 13 14 columns = 10 15 data = [] 16 for i in range(0, 100, 5): 17 data.append([i, i+1, i+2, i+3, i+4]) 18 self.tree = ttk.Treeview(self.win, selectmode='browse') 19 self.tree.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew", padx=5, pady=5) 20 self.tree["columns"] = tuple(range(1, columns + 1)) 21 self.tree["show"] = "headings" 22 w = self.win.winfo_width() 23 ww = int(w / 7) 24 for i in range(1, columns + 1): 25 self.tree.heading(i, text="Data"+str(i)) 26 self.tree.column(i, width=ww) 27 for i in data: 28 self.tree.insert("", "end", value=(i)) 29 self.verscrlbar = ttk.Scrollbar(self.win, 30 orient="vertical", 31 command=self.tree.yview) 32 self.verscrlbar.grid(row=0, column=2,rowspan=2, sticky="nsew") 33 self.hozscrlbar = ttk.Scrollbar(self.win, 34 orient="horizontal", 35 command=self.tree.xview) 36 self.hozscrlbar.grid(row=2, column=0, sticky="nsew") 37 self.tree.configure(yscrollcommand=self.verscrlbar.set, xscrollcommand=self.hozscrlbar.set) 38 39def main(): 40 win = tk.Tk() 41 App(win) 42 win.mainloop() 43 44if __name__ == "__main__": 45 main()

投稿2021/04/05 17:35

編集2021/04/05 17:43
FredericChang

総合スコア54

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問