このページでは、Tkinter の「スクロールバー」ウィジェットの作成方法および設定方法について説明していきたいと思います。
スクロールバーとは
まずは、今回解説する「スクロールバー」がどのようなものであるかを簡単に説明していきます。
スクロールバーは表示領域を変化させるウィジェット
スクロールバーは、ウィジェットをスクロールさせて「表示領域」を変化させるためのウィジェットになります。
下の図は tkinter で作成したスクロールバー付きのキャンバスになります。
スクロールバーのスライダー(つまみ)を移動させることで、キャンバスの表示領域が変化し、最初見えなかった図形が見えるようになるのが確認できると思います。
こんな感じで、小さなウィジェットであっても、スクロールバーを利用すれば大きなウィジェットのように扱うことが可能になります。
スポンサーリンク
スクロールバーと他のウィジェットとの大きな違い
スクロールバーのポイントは、スクロールバーのメイン機能の「スクロール」が他のウィジェットに作用するものである点です。
つまり、スクロールバー単体では意味のないウィジェットで、他のウィジェットをスクロールさせるようにすることで初めて意味のあるウィジェットになります。
ここが他のウィジェットとの決定的な違いになります。
そのため、このスクロールバーを作成していく上では、「いかにして他のウィジェットをスクロールさせるのか」という点がポイントになってきます。
ということで、このページでは単にスクロールバーを作成するものではなく、「スクロールバー付きのウィジェット」を作成するスクリプトを紹介し、そのスクリプトを確認しながらスクロールバーを作成するために必要な処理を解説していきたいと思います。
スクロール可能なウィジェット
スクロールバーがスクロールさせることができるウィジェットは(私が確認した限りでは)下記の5つになります。
- キャンバス(
Canvas
) - リストボックス(
Listbox
) - エントリー(
Entry
) - スピンボックス(
Spinbox
) - テキストボックス(
Text
)
まずは、「スクロールバー付きのキャンバス」を例に、スクロールバーの作成や配置、さらにはキャンバスをスクロールさせる方法について解説していきたいと思います。
その後、リストボックス・エントリー・スピンボックス・テキストボックスそれぞれに対するスクロールバーの作り方を、スクロールバー付きのウィジェットの作成(キャンバス以外)で解説していきたいと思います。
といっても、キャンバスとその他のウィジェットでは、スクロールバーの作り方は “ほぼ” 同じです。
ですので、重要な内容は全て、次の「スクロールバー付きのキャンバス」で解説し、その他のウィジェットにおけるスクロールバーの作成については、スクリプトの紹介のみを行う形で解説していきたいと思います。
スクロールバー付きのキャンバス
それでは、まずは「スクロールバー付きのキャンバス」を作成するスクリプトを紹介し、その中でスクロールバーの作成方法を解説していきたいと思います。
スクロールバーを作成する上でポイントになるのは下記の3つになります。
- スクロールバーの作成
- スクロールバーの配置
- キャンバスをスクロールするための設定
この辺りに注目しながらスクリプトに目を通してみていただくと、スクロールバー作成に必要な処理が分かりやすくなると思います。
スポンサーリンク
スクロールバー付きのキャンバスのスクリプト
「スクロールバー付きのキャンバス」を作成するスクリプト例は下記のようになります。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウの作成
app = tkinter.Tk()
# キャンバスの作成と配置
canvas = tkinter.Canvas(
app,
width=400,
height=300,
scrollregion=(-200, -100, 800, 600)
)
canvas.grid(row=0, column=0)
# 楕円をキャンバスからはみ出るように描画
canvas.create_oval(
300, 250,
500, 350,
fill="blue"
)
# 楕円をキャンバスの外に描画
canvas.create_oval(
700, 0,
800, 200,
fill="red"
)
# 長方形をキャンバスの外に描画
canvas.create_rectangle(
600, 400,
800, 500,
fill="green"
)
# 長方形をキャンバスの外に描画
canvas.create_rectangle(
-200, -100,
0, 0,
fill="purple"
)
# 水平方向のスクロールバーを作成
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
)
# 垂直方向のスクロールバーを作成
ybar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.VERTICAL, # バーの方向
)
# キャンバスの下に水平方向のスクロールバーを配置
xbar.grid(
row=1, column=0, # キャンバスの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
# キャンバスの右に垂直方向のスクロールバーを配置
ybar.grid(
row=0, column=1, # キャンバスの右の位置を指定
sticky=tkinter.N + tkinter.S # 上下いっぱいに引き伸ばす
)
# キャンバスをスクロールするための設定
# スクロールバーのスライダーが動かされた時に実行する処理を設定
xbar.config(
command=canvas.xview
)
ybar.config(
command=canvas.yview
)
# キャンバススクロール時に実行する処理を設定
canvas.config(
xscrollcommand=xbar.set
)
canvas.config(
yscrollcommand=ybar.set
)
# メインループ
app.mainloop()
実行すると下の図のようにメインウィンドウの中に「スクロールバー付きのキャンバス」が表示されます。
さらに、スクロールバーのスライダー(つまみ)をマウスでクリックしながら動かすと、今まで見えなかったキャンバス上の図形が見えるようになることが確認できると思います。
上記のスクリプトの中で、「スクロールバー付きのキャンバス」を作るためにどのような処理を行なっているのかについて、ここから解説していきたいと思います。
メインウィンドウの作成とメインループ
この辺りは他のウィジェットと同様ですね!
まず、下記でメインウィンドウの作成及びメインループの実行を行なっています。
# -*- coding:utf-8 -*-
import tkinter
app = tkinter.Tk()
# 略
app.mainloop()
メインウィンドウが何かわからない方は、下記ページで解説していますのでコチラも読んでみてください。
Tkinterの使い方:メインウィンドウを作成するまた、メインループについては下記ページで解説しています。
【Python】tkinterのmainloopについて解説キャンバスの作成とキャンバスへの図形描画
続いて “スクロールバーなし” の状態のキャンバスを作成し、さらにメインウィンドウ上に配置していきます。
キャンバスの作成と配置
まず、キャンバスの作成と配置を行なっているのは下記部分になります。
# キャンバスの作成と配置
canvas = tkinter.Canvas(
app,
width=400,
height=300,
scrollregion=(-200, -100, 800, 600)
)
canvas.grid(row=0, column=0)
キャンバスの作成については下記ページで解説していますので、詳しく知りたい方はこちらを参考にしていただければと思います。
Tkinterの使い方:キャンバスウィジェットの作り方スクロールバー付きのキャンバスを作成する上でポイントになるのが scrollregion
の設定です。
スクロールバーは、スクロールにより画面に表示されていない部分を表示できるようにするものです。
画面に表示されるキャンバスのサイズを指定するのが、width
と height
になります。
一方で、画面に表示されていない部分のサイズを指定するのが、この scrollregion
になります。要はスクロール可能なサイズですね!
scrollregion
で指定するのは、キャンバスの左上の位置からの距離で、下の図のように4つのパラメータを指定します。
この scrollregion
の指定により、実際に表示されているキャンバスからどれだけスクロールできるかが決まります。
また、最初の2つ、つまり上の図における w
と n
に負の値を設定すれば、キャンバスの左上方向にもスクロールできるようになります。
キャンバスへの図形の描画
キャンバスの作成と配置の後に行っているのが図形の描画です。これはスクロールバーの動作確認をするための処理で、スクロールバーを作成するための必須の処理ではないです。
# 楕円をキャンバスからはみ出るように描画
canvas.create_oval(
300, 250,
500, 350,
fill="blue"
)
# 楕円をキャンバスの外に描画
canvas.create_oval(
700, 0,
800, 200,
fill="red"
)
# 長方形をキャンバスの外に描画
canvas.create_rectangle(
600, 400,
800, 500,
fill="green"
)
# 長方形をキャンバスの外に描画
canvas.create_rectangle(
-200, -100,
0, 0,
fill="purple"
)
図形の描画に関しては下記ページで詳しく説明していますので、各メソッドや引数の意味を知りたい場合はこちらを読んでみてください。
Tkinterの使い方:Canvasクラスで図形を描画するここでのポイントは、キャンバスからはみ出るように、もしくはキャンバス外に各図形を描画してるところです。
このように描画しているので、このままでアプリを起動してもほとんど描画した図形が見れない状態です。
ただし、これらは前述の scrollregion
内に描画しているので、スクロールバーのスクロールにより図形が見えるようになります。
スポンサーリンク
スクロールバーの作成
いよいよ本題のスクロールバーの作成について解説していきます。
実際にスクロールバーを作成しているのが下記になります。
水平方向のスクロール用のスクロールバー xbar
と、垂直方向のスクロール用のスクロールバー ybar
の2つを作成しています。
# 水平方向のスクロールバーを作成
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
)
# 垂直方向のスクロールバーを作成
ybar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.VERTICAL, # バーの方向
)
スクロールバーは Scrollbar
クラスのコンストラクタを実行することで作成することができます。
tkinter.Scrollbar()
コンストラクタの第1引数で指定するのがスクロールバーを配置する親ウィジェットです。
今回はスクロールバーをメインウィンドウ上に配置するので、親ウィジェットにはメインウィンドウのオブジェクトである app
を指定しています。
また、orient
引数で指定するのはスクロールバーの方向です。orient
には、作成するスクロールバーの方向に応じて下記のどちらかを指定します。
tkinter.HORIZONTAL
:水平方向のスクロールバーtkinter.VERTICAL
:垂直方向のスクロールバー
スクロールバーの配置
スクロールバーも、他のウィジェット同様に配置を行う必要があります。
スクロールバーの場合、下の図のように、水平方向のスクロールバーはウィジェットの下側に、垂直方向のスクロールバーはウィジェットの右側に、ウィジェットにくっつく様に配置されるのが一般的だと思います。
さらに、これらのスクロールバーのサイズ(水平方向のスクロールバーであれば横方向のサイズ、垂直方向のスクロールバーであれば縦方向のサイズ)は、ウィジェットいっぱいに広がるように設定されているのが一般的だと思います。
ただし、tkinter でスクロールバーを上記のような配置を行うためには、プログラマーがこのような配置になるようにスクロールバーを配置するスクリプトを記述してやる必要があります(自動的に上記のような配置が行われるわけではない)。
この配置を行なっているのは下記になります。
# キャンバスの下に水平方向のスクロールバーを配置
xbar.grid(
row=1, column=0, # キャンバスの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
# キャンバスの右に垂直方向のスクロールバーを配置
ybar.grid(
row=0, column=1, # キャンバスの右の位置を指定
sticky=tkinter.N + tkinter.S # 上下いっぱいに引き伸ばす
)
スクロールバーをウィジェットの下、もしくはウィジェットの右に配置するのは grid
メソッドで配置を行うのが簡単です。
キャンバスを配置しているのは下記の通り row=0
、column=0
の位置です。
canvas.grid(row=0, column=0)
したがって、水平方向のスクロールバーを row=1
、column=0
の位置に grid
で配置すればキャンバスの下側に、垂直方向のスクロールバーを row=0
、column=1
の位置に grid
で配置すればキャンバスの右側にそれぞれ配置することができます。
さらに、スクロールバーをキャンバスのサイズに合わせて引き伸ばすために、grid
メソッドの引数に sticky
を指定しています。
sticky
は grid
で分割された領域に対してどの方向に寄せて配置するかを指定する設定になります。
この sticky
に2つの方向を指定すれば、その2方向に対して目一杯に引き伸ばしたウィジェットを配置することができます。
水平方向のスクロールバーは横方向に、垂直方向のスクロールバーは縦方向にそれぞれ目一杯に引き伸ばして配置するため、sticky
には下記を指定するようにしています。
- 水平方向のスクロールバー:
tkinter.W+tkinter.E
(左端から右端に引き伸ばす) - 垂直方向のスクロールバー:
tkinter.N+tkinter.S
(上端から下端に引き伸ばす)
以上のように grid
で配置することで、最初にお見せした図のようにスクロールバーの配置を実現することができます。
「ウィジェットの配置」については下記ページで解説していますので、詳しく知りたい方はこちらのページ参考にしていただければと思います。上記の sticky
についても解説しています。
キャンバスをスクロールするための設定
ここまででウィジェットの作成と配置が完了し、見た目としてはスクロールバー付きのキャンバスが作成されたことになります。
ただし、見た目として出来上がっただけで、まだスクロールバーのスライダーの移動やキャンバスのスクロールができないので、これらができるように設定を行なっていきます。
具体的には下記の2つの設定を行います。
- スクロールバーのスライダーが動かされた時に実行する処理を設定
- キャンバススクロール時に実行する処理を設定
スクロールバーのスライダーが動かされた時に実行する処理を設定
まずは「スクロールバーのスライダーが動かされたときに実行する処理を設定」をしていきます。
より具体的には、スクロールバーのスライダーが動かされたときに、”キャンバスの表示領域を変化させる処理” が実行されるように設定を行います。
この設定は下記で行っています。ここで使用している config
は、各ウィジェットに用意された “ウィジェットの設定を行うメソッド” になります。
# スクロールバーのスライダーが動かされた時に実行する処理を設定
xbar.config(
command=canvas.xview
)
ybar.config(
command=canvas.yview
)
スクロールバーの command
を設定することにより、スクロールバーのスライダーが動かされたときに実行したい関数(メソッド)を設定することができます。
つまり、command
に “キャンバスの表示領域を変化させるような関数 or メソッド” を指定してやれば、スクロールバーのスライダーが動かされた時に、キャンバスの表示領域が自動的に変化するようになります。
表示領域の変更を行うための関数やメソッドを自作するとなると難易度は高いですが、表示領域を変更するためのメソッドとして、いくつかのウィジェット(のクラス)には xview
と yview
があらかじめ用意されています。
xview
:水平方向の表示領域を変化させるメソッドyview
:垂直方向の表示領域を変化させるメソッド
Canvas
クラスにも、この xview
と yview
メソッドが用意されています。
ですので、作成したキャンバス canvas
の canvas.xview
と canvas.yview
を、それぞれのスクロールバーの command
に設定してやれば、スクロールバーが動いたときにキャンバスの “表示領域” が自動的に変更されるようになります。
キャンバススクロール時に実行する処理を設定
前述の「スクロールバーのスライダーが動かされた時に実行する処理を設定」により、キャンバスのスクロールが行えるようになったようにも思えますが、まだ不十分です。
実は、上記の設定だけだと、スクロールバーのスライダーがまだ動かせない状態です(実際に試してみるとこの様子が確認できると思います)。
このスライダーを動かすために行うのが、ここで説明する「キャンバススクロール時に実行する処理を設定」になります。
より具体的には、キャンバスがスクロールされた時に、つまりキャンバスの表示領域が変わったときに、その表示している領域に合わせて “スクロールバーのスライダーの位置を設定する処理” が実行されるように設定を行います。
これを行っているのは下記になります。
# キャンバススクロール時に実行する処理を設定
canvas.config(
xscrollcommand=xbar.set
)
canvas.config(
yscrollcommand=ybar.set
)
キャンバスの xscrollcommand
と yscrollcommand
の指定により、キャンバスがスクロールされたとき(キャンバスの表示領域が変化したとき)に実行される処理を設定することができます。
前述の通り、キャンバスがスクロールされたときに実行されるようにしたいのは、キャンバスの表示領域に応じてスクロールバーのスライダーの位置を設定する処理です。
このスライダーの位置を設定するメソッドとして、Scrollbar
クラスには set
メソッドが用意されています。
ですので、xscrollcommand
と yscrollcommand
それぞれに対して、水平方向のスクロールバーオブジェクトの set
メソッドと垂直方向のスクロールバーオブジェクトの set
メソッドを設定してやれば、キャンバスがスクロールされたときに表示領域に合わせて自動的にスライダーの位置が設定されるようになります。
2つの設定によりスクロールとスライドバーの位置設定が連動する
以上の2つの設定を行うことで、スクロールバーとキャンバスが関連付けられ、下記のように「キャンバスのスクロール」と「スクロールバーのスライダー」が “連動して” 動作するようになります。
- ユーザーがスクロールバーのスライダーを動かす
- スライダーが動いたので、スクロールバーの
command
に設定したxview
とyview
が実行される - キャンバスがスクロールされる(キャンバスの表示領域が変化する)
- キャンバスがスクロールされたので、キャンバスの
xscrollcommand
とyscrollcommand
実行される - スクロールバーのスライダーの位置がキャンバスのスクロール位置に合わせて設定される
実はこの辺りの解説は、実際にソースコードを読んで確認したわけではなく、動作から推測したものになります…
もしかしたら動作の詳細が間違っている部分もあるかもしれませんが、とりあえずスクロールバー付きのキャンバスを作成するために下記の2つが必要なのは確かです
- スクロールバーのスライダーが動かされた時に実行する処理を設定
- キャンバススクロール時に実行する処理を設定
スポンサーリンク
スクロールバー付きのキャンバスの作り方のまとめ
特に最後の「キャンバスをスクロールするための設定」の仕組みは難しいかもしれませんが、要は下記を実行すれば、キャンバスをスクロールさせることができるようになります。
# スクロールバーのスライダーが動かされた時に実行する処理を設定
xbar.config(
command=canvas.xview
)
ybar.config(
command=canvas.yview
)
# キャンバススクロール時に実行する処理を設定
canvas.config(
xscrollcommand=xbar.set
)
canvas.config(
yscrollcommand=ybar.set
)
さらに、キャンバスの場合は、どこまでの領域をスクロールできるようにするかを、キャンバスに scrollregion
で設定する必要があります。
# キャンバスの作成と配置
canvas = tkinter.Canvas(
# 略
scrollregion=(-200, -100, 800, 600),
)
以上の設定により、スクロールバー付きのキャンバスを実現することができます。
また、見た目としてウィジェットにスクロールバーがくっついているようにする場合は、grid
が便利です。
# キャンバスの下に水平方向のスクロールバーを配置
xbar.grid(
row=1, column=0, # キャンバスの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
# キャンバスの右に垂直方向のスクロールバーを配置
ybar.grid(
row=0, column=1, # キャンバスの右の位置を指定
sticky=tkinter.N + tkinter.S # 上下いっぱいに引き伸ばす
)
キャンバス上の座標の扱いの注意点
スクロール可能なキャンバスを作成した際に注意点となるのが座標です。
スクロール可能なキャンバスを扱う際には、2つの種類の座標を区別して扱う必要があります。具体的には下記の2つです。
- 表示されている領域の左上座標を原点とする座標
scrollregion
の(0, 0)
座標を原点とする座標
例えば、マウスイベントなどが発生した際にはマウスの現在座標を引数から取得することが可能ですが、その座標は前者の表示領域の左上座標を原点とする座標となります。
それに対し、キャンバスのメソッドに指定する必要があるのは後者の scrollregion
の (0, 0)
座標を原点とする座標となります。
ですのでマウスの現在座標をキャンバスのメソッドにそのまま指定してしまうと、本来指定すべき後者の座標ではなく、前者の座標を指定することになり、その結果アプリの動作がうまくいかない可能性があるので注意してください。
例えば下記は、マウスでクリックした位置に描画した正方形を移動させるスクリプトの良くない例になります。bind
メソッドによりマウスクリック時に push
関数が実行されるよう設定されており、この push
が実行された際には、マウスクリック時の座標を引数 event
から得ることができます(event.x
と event.y
)。
ただし、この座標は上記における前者の座標です。にも関わらず、得られた座標を利用してキャンバスのメソッド coords
を実行しているため、スクロールバーでスクロールを行った後にマウスクリックをしても、クリックした位置に正方形が移動しません。
import tkinter
def push(event):
x = event.x
y = event.y
canvas.coords(
rect,
x - 25, y - 25,
x + 25, y + 25
)
app = tkinter.Tk()
canvas = tkinter.Canvas(
app,
width=500, height=500,
scrollregion=(-300, 0, 1000, 500),
highlightthickness=0,
bg="gray",
)
canvas.grid(row=0, column=0)
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
)
xbar.grid(
row=1, column=0, # キャンバスの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
xbar.config(
command=canvas.xview
)
canvas.config(
xscrollcommand=xbar.set
)
rect = canvas.create_rectangle(
0, 0, 50, 50,
fill="blue",
)
canvas.bind("<ButtonPress>", push)
app.mainloop()
この例のように、スクロール可能なキャンバスを扱い、さらにキャンバスのメソッドに座標を指定する際には、下記の後者の座標を指定しないとアプリが意図した通りに動作してくれません。この点に注意が必要です。
- 表示されている領域の左上座標を原点とする座標
scrollregion
の(0, 0)
座標を原点とする座標
もし、前者の座標から後者の座標に変換したい場合は、キャンバスの canvasx
メソッドと canvasy
メソッドを利用すると良いです。
canvasx
メソッドの引数に前者の x
座標を指定して実行すれば、後者の x
座標に変換した結果を得ることができます。canvasy
メソッドも同様に、引数に前者の y
座標を指定して実行すれば、後者の y
座標に変換した結果を得ることができます。
例えば先程の例のスクリプトであれば、push
関数が実行された際に得られるマウスの座標(event.x
と event.y
)を canvasx
メソッドと canvasy
メソッドにより変換し、変換後の座標を利用してキャンバスのメソッド coords
を実行するようにすることで、スクロール後もクリックした位置に正方形が移動するようにすることができます。
import tkinter
def push(event):
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
canvas.coords(
rect,
x - 25, y - 25,
x + 25, y + 25
)
今回の例だと縦方向のスクロールバーは付けていないので canvasy
メソッドで変換しなくても良いといえば良いのですが、特にスクロールバーを利用する際は、マウスの座標をキャンバスのメソッドに指定する前には、canvasx
と canvasy
で座標の変換を行うようにした方が無難だと思います。
スクロールバー付きのウィジェットの作り方(キャンバス以外)
次は、キャンバス以外のスクロールバー付きのウィジェットの作り方について紹介していきたいと思います。
スポンサーリンク
作り方はキャンバスの時とほぼ同じ
結論を言うと、作り方は “ほぼ” キャンバスの時と同じです。
要は、作成したスクロールバーとウィジェットに対して下記を行えば良いです。
# widgetは各種ウィジェットのオブジェクト
# xbarは水平方向のスクロールバーオブジェクト
# ybarは垂直方向のスクロールバーオブジェクト
# スクロールバーのスライダーが動かされた時に実行する処理を設定
xbar.config(
command=widget.xview
)
ybar.config(
command=widget.yview
)
# ウィジェットスクロール時に実行する処理を設定
widget.config(
xscrollcommand=xbar.set
)
widget.config(
yscrollcommand=ybar.set
)
また、スクロールバーの配置も同様に行うことができます。
# widgetは各種ウィジェットのオブジェクト
# xbarは水平方向のスクロールバーオブジェクト
# ybarは垂直方向のスクロールバーオブジェクト
# ウィジェットの配置(rとcは配置したい位置に応じて変更)
widget.grid(row=r, column=c)
# ウィジェットの下に水平方向のスクロールバーを配置
xbar.grid(
row=r+1, column=c, # ウィジェットの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
# ウィジェットの右に垂直方向のスクロールバーを配置
ybar.grid(
row=r, column=c+1, # ウィジェットの右の位置を指定
sticky=tkinter.N + tkinter.S # 上下いっぱいに引き伸ばす
)
ただし、キャンバスとは異なり、scrollregion
の設定は不要です。
キャンバスの場合は scrollregion
でスクロール可能な領域を設定する必要がありましたが、他のウィジェットに関しては、入力されている文字列(はみ出している文字列)からスクロール可能な領域を勝手に tkinter が判断してくれるようです。
xview
/ yview
メソッドを持つウィジェット
で、上記の設定を行うためには、xview
や yview
メソッドが必要です。
つまり、基本的には、このメソッドが用意されているウィジェットにしかスクロールバーは付けることができません(付けたとしても連動して動作させることができません)。
これらのメソッドが用意されているウィジェットは、キャンバスを除くと私が知っているのは下記の4つになります。
- リストボックス(
Listbox
) - エントリー(
Entry
)xview
のみ
- スピンボックス(
Spinbox
)xview
のみ
- テキストボックス(
Text
)
エントリーとスピンボックスに関しては、そもそも “1行分のテキストのみ” を入力するためのウィジェットなので、垂直方向のスクロールバーには対応していないようです(yview
メソッドが用意されていない)。
また、これは他の環境では動作が異なるかもしれませんが、テキストボックスの場合は水平方向のスクロールバーを付けても動作はしませんでした(入力した文字列がテキストボックスの横方向のサイズを超える場合では、勝手に折り返される)。
以上を踏まえて、「スクロールバー付きのリストボックス」、「スクロールバー付きのエントリー」、「スクロールバー付きのスピンボックス」、「スクロールバー付きのテキストボックス」それぞれを作成するスクリプトを下記で紹介していきます。
スクロールバー付きのリストボックス
スクロールバー付きのリストボックスを作成するスクリプトの例は下記のようになります。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウの作成
app = tkinter.Tk()
# リストボックスの作成と配置
N = 5
contents = (
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"MondayTuesdayWednesday",
"ThursdayFridaySaturdaySunday"
"JanuaryFebruaryMarchAprilMayJune",
"JulyAugustSeptemberOctoberNovemberDecember",
"sin",
"cos",
"tan",
)
listbox = tkinter.Listbox(
app,
width=20,
height=5,
font=("", 40),
listvariable=tkinter.StringVar(value=contents),
)
listbox.grid(row=0, column=0)
# 水平方向のスクロールバーを作成
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
)
# 垂直方向のスクロールバーを作成
ybar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.VERTICAL, # バーの方向
)
# リストボックスの下に水平方向のスクロールバーを配置
xbar.grid(
row=1, column=0, # リストボックスの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
# リストボックスの右に垂直方向のスクロールバーを配置
ybar.grid(
row=0, column=1, # リストボックスの右の位置を指定
sticky=tkinter.N + tkinter.S # 上下いっぱいに引き伸ばす
)
# リストボックスをスクロールするための設定
# スクロールバーのスライダーが動かされた時に実行する処理を設定
xbar.config(
command=listbox.xview
)
ybar.config(
command=listbox.yview
)
# リストボックススクロール時に実行する処理を設定
listbox.config(
xscrollcommand=xbar.set
)
listbox.config(
yscrollcommand=ybar.set
)
# メインループ
app.mainloop()
実行すると下のアニメーションのように、スクロールバーを動かすことでリストボックス内がスクロールされます。
スポンサーリンク
スクロールバー付きのエントリー
スクロールバー付きのエントリーを作成するスクリプトの例は下記のようになります。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウの作成
app = tkinter.Tk()
# エントリーの作成と配置
entry = tkinter.Entry(
app,
width=10,
font=("", 150)
)
entry.grid(row=0, column=0)
# 水平方向のスクロールバーを作成
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
)
# エントリーの下に水平方向のスクロールバーを配置
xbar.grid(
row=1, column=0, # エントリーの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
# エントリーをスクロールするための設定
# スクロールバーのスライダーが動かされた時に実行する処理を設定
xbar.config(
command=entry.xview
)
# エントリースクロール時に実行する処理を設定
entry.config(
xscrollcommand=xbar.set
)
# メインループ
app.mainloop()
実行すると下のアニメーションのように、スクロールバーを動かすことでエントリー内がスクロールされます。
スクロールバー付きのスピンボックス
スクロールバー付きのスピンボックスを作成するスクリプトの例は下記のようになります。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウの作成
app = tkinter.Tk()
# スピンボックスの作成と配置
spinbox= tkinter.Spinbox(
app,
width=10,
font=("", 150)
)
spinbox.grid(row=0, column=0)
# 水平方向のスクロールバーを作成
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
)
# スピンボックスの下に水平方向のスクロールバーを配置
xbar.grid(
row=1, column=0, # スピンボックスーの下の位置を指定
sticky=tkinter.W + tkinter.E # 左右いっぱいに引き伸ばす
)
# スピンボックスをスクロールするための設定
# スクロールバーのスライダーが動かされた時に実行する処理を設定
xbar.config(
command=spinbox.xview
)
# スピンボックススクロール時に実行する処理を設定
spinbox.config(
xscrollcommand=xbar.set
)
# メインループ
app.mainloop()
実行すると下のアニメーションのように、スクロールバーを動かすことでスピンボックス内がスクロールされます。
スクロールバー付きのテキストボックス
スクロールバー付きのテキストボックスを作成するスクリプトの例は下記のようになります。
# -*- coding:utf-8 -*-
import tkinter
# メインウィンドウの作成
app = tkinter.Tk()
# テキストボックスの作成と配置
textbox = tkinter.Text(
app,
width=10,
height=5,
font=("", 40)
)
textbox.grid(row=0, column=0)
# 垂直方向のスクロールバーを作成
ybar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.VERTICAL, # バーの方向
)
# テキストボックスの右に垂直方向のスクロールバーを配置
ybar.grid(
row=0, column=1, # テキストの右の位置を指定
sticky=tkinter.N + tkinter.S # 上下いっぱいに引き伸ばす
)
# テキストボックスをスクロールするための設定
# スクロールバーのスライダーが動かされた時に実行する処理を設定
ybar.config(
command=textbox.yview
)
# テキストボックススクロール時に実行する処理を設定
textbox.config(
yscrollcommand=ybar.set
)
# メインループ
app.mainloop()
実行すると下のアニメーションのように、スクロールバーを動かすことでテキストボックス内がスクロールされます。
スポンサーリンク
スクロールバーの設定
ここからはスクロールバーの作成時(tkinter.Scrollbar()
実行時)や config
メソッド実行時にキーワード引数で指定する「スクロールバーの設定」について解説していきます。
設定できる全てのキーワードは下記により確認することができます。
# barはScrollbarのインスタンス
print(bar.keys())
ここでは私がよく使うもの・動作を理解しているものをピックアップして説明していきたいと思います。といっても、スクロールバーで特に重要な設定は下記の3つくらいだと思います。
orient
command
width
私の下記環境での実行結果をもとに説明していますが、環境によっては動きが異なるかもしれません
実際にご自身の環境で実行結果を確認していただくと、より確実に設定の効果を理解することができると思います
- OS:macOS Big Sur(11.2.3)
- Python:3.8
- Tkinter:8.6
orient
orient
キーワード引数により、そのスクロールバーを「水平方向のスクロールバー」か「垂直方向のスクロールバー」のどちらにするかをを設定することができます。
具体的に orient
に指定するパラメータは下記のようになります。
- 水平方向のスクロールバー:
tkinter.HORIZONTAL
- 垂直方向のスクロールバー:
tkinter.VERTICAL
orient
を指定しなかった場合は、デフォルトの tkinter.VERTICAL
が適用されます。
command
command
キーワード引数を指定することで、スクロールバーが動かされたときに実行される処理を設定することができます。
基本的には、この command
に設定するパラメータは下記になります(widget
は各ウィジェットのオブジェクト)。
- 水平方向のスクロールバー:
widget.xview
- 垂直方向のスクロールバー:
widget.yview
スクロールバー付きのキャンバスの作り方でも説明しましたが、これらを設定することにより、スクロールバーを動かしたときにウィジェットの表示領域が自動的に変化するようになります。
必ず xview
や yview
を設定しなければならないということもないですが、スクロールバーとウィジェットを連動させるためには、これらを指定するのが一般的だと思います。
スポンサーリンク
width
width
キーワード引数を指定することで、スクロールバーの幅を設定することができます。どの方向に対する “幅” であるかは、スクロールバーの方向(orient
設定)によって変わります。
- 水平方向のスクロールバー:縦方向の幅
- 垂直方向のスクロールバー:横方向の幅
width
では、上記とは異なる方向の幅は設定できませんので、配置するときにサイズを調整するのが良いと思います。
例えばスクロールバー付きのキャンバスの作り方では、ウィジェットのサイズに合わせてスクロールバーを引き伸ばすために、grid
メソッドに sticky
を指定して配置を行うようにしています。
jump
jump
キーワード引数を指定することで、ウィジェットのスクロールが行われるタイミングを変更することができます。
通常は、マウスでスライダーをクリックし、クリックしたままスライダーを動かすと、即座にスクロールが行われます。
一方で jump=1
を指定すれば、マウスのクリックを離したタイミングで、スライダーの位置に合わせてスクロールが行われるようになります。
デフォルト設定は jump=0
になります。
repeatdelay
・repeatinterval
スクロールバーでは、スライダー自身をマウスで動かすだけでなく、スライダーの周りの窪みをクリックすることでもスライダーを動かすことができます。
この時、スライダーの周りの窪みをクリックし続けた(押し続けた)場合には、繰り返しクリックしたかのように、一定間隔でスライダーが動き続けます。
この時の間隔を設定するのが repeatdelay
・repeatinterval
になります。
クリックし続けて最初にスライダーが動作するまでの時間を repeatdelay
で、その後スライダーが動作する間隔を repeatinterval
で設定可能です。
例えば下記のように設定した場合、
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
repeatdelay=2000,
repeatinterval=100
)
窪みをクリックし続けると、クリックし続けてから 2000
ms 経過したタイミングでスライダーが移動し、その後は 100
ms 間隔でスライダーが移動し続けます。
実際に窪みをクリックし続けてスライダーを移動させた時の様子が下のアニメーションになります(ちょっとわかりにくいかな…)。
スポンサーリンク
takefocus
takefocus
キーワード引数を指定することで、タブキーによるフォーカスの有効無効を設定することができます。
フォーカスがあてられたスクロールバーは、水平方向のスクロールバーの場合は左右キーで、垂直方向のスクロールバーの場合は上下キーでスライダーを移動させることができるようになります。
このフォーカスをあてられるかどうかを、takefocus
に下記のように指定すること設定することができます。
takefocus=0
:フォーカスがあてられないtakefocus=1
:フォーカスがあてられる
デフォルト設定は takefocus=1
になります。
bd(borderwidth)
bd(borderwidth)
の指定により、スクロールバーの枠線の太さを設定することができます。
例えば下記のように bd
を設定すれば、スクロールバーの枠線の太さが 20
px になります。
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
bd=20,
)
ただし、bd
を大きくするとスクロールバーのスライダーの位置が若干狂うようでした。私の環境だけかもしれませんが、bd
は大きく設定しない方が無難だと思います。
bg(background)
bg(background)
の指定により、スクロールバーの枠線の色を設定することができます。
これは私が試した環境での動作結果になります
もしかしたら環境によっては、bg
の指定で色が変わるのは “スライダーの色” になるかもしれません
例えば下記のように bg
を設定すれば、スクロールバーの枠線の色が "green"
になります。
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
bd=20,
bg="green",
)
上記で作成したスクロールバーを配置したアプリを起動すると下の図のような画面が表示されます。
スポンサーリンク
relief
relief
の指定により、スクロールバーの見た目を設定することができます。
これは私が試した環境での動作結果になります
もしかしたら環境によっては、relief
の指定で見た目が変わるのは “スライダー” になるかもしれません
relief
に指定できるのは下記の6つになります(デフォルトは tkinter.SUNKEN
)。
tkinter.RAISED
tkinter.SUNKEN
tkinter.FLAT
tkinter.RIDGE
tkinter.GROOVE
tkinter.SOLID
例えば下記のように relief
を設定すれば、スクロールバーが “浮き出る” ような見た目なります。
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
bd=20,
bg="green",
relief=tkinter.RAISED,
)
上記で作成したスクロールバーを配置したアプリを起動すると下の図のような画面が表示されます。
スクロールバーの枠線が細いと(つまり bd
の値が小さいと)、この relief
の指定による見た目の変化がわかりにくいので注意してください。
highlightcolor
・highlightbackground
・highlightthickness
highlightcolor
・highlightbackground
・highlightthickness
の指定により、スクロールバーにフォーカスがあてられた時&フォーカスが外れた時のスクロールバーの囲い線の設定が可能です。
highlightcolor
:フォーカスがあてられた時の囲い線の色highlightbackground
:フォーカスが外れた時の囲い線の色highlightthickness
:囲い線の太さ(px)
下記はこれらのキーワードを指定する例になります。
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
orient=tkinter.HORIZONTAL, # バーの方向
highlightbackground="green",
highlightthickness=10,
highlightcolor="red",
)
上記で作成したスクロールバーを配置したアプリを起動すると下の図のような画面が表示されます。
下側の水平方向のスクロールバーの緑色の線が、フォーカスに対する囲い線になります。この囲い線の太さが、highlightthickness
で指定している 10
px になります。
また、現状このスクロールバーにフォーカスが当たっていないので、この囲い線の色は highlightbackground
で指定している "green"
になります。
この状態でタブキーを押してスクロールバーにフォーカスをあてると、今度はこの囲い線の色が highlightcolor
で指定している "red"
に変化します。
cursor
cursor
キーワード引数を指定することで、スクロールバー上でのマウスカーソルの見た目(アイコン)を変更することができます。
例えば私の環境では、"hand"
を設定すれば、スクロールバー上にマウスカーソルを合わせるとカーソルの見た目が “手” に変わります。
xbar = tkinter.Scrollbar(
app, # 親ウィジェット
cursor="hand", # カーソルのアイコンを変更
)
MacOSX の場合は、cursor
に下記のようなパラメータを設定することが可能です。おそらく設定可能なパラメータは OS 等によって異なるので注意してください。
"hand"
"ibeam"
"wait"
"poof"
スポンサーリンク
Scrollbar
クラスのメソッド
最後に Scrollbar
クラスに用意されたメソッドについて紹介していきたいと思います。
全ウィジェットで共通のメソッドについては省略し、Scrollbar
クラス特有のメソッドを紹介していきたいと思います。
get
get
はスクロールバーのスライダーの現在位置を取得するメソッドになります。
# barはスクロールバーのオブジェクト
start, end = bar.get()
スライダーの位置は「開始位置」と「終了位置」の2つによって決まります。get
メソッドの戻り値もこの2つになります。
また、この「開始位置」と「終了位置」は 0
〜 1
の値になります。
この値の意味は、スクロールバーの左端(上端)を 0
、右端(下端)を 1
とした時の、それぞれの相対的な位置になります。
ちなみに、スライダーの幅(つまり 終了位置 - 開始位置
の値)は表示されている領域のサイズとスクロール可能な領域のサイズから自動的に tkinter によって設定されます。
set
set
はスクロールバーのスライダーの位置を設定するメソッドになります。
# barはスクロールバーのオブジェクト
bar.set(start, end)
set
メソッドの引数は下記の2つになります。
start
:スライダーの開始位置(0
〜1
)end
:スライダーの終了位置(0
〜1
)
開始位置、終了位置ともに、get
メソッド同様に、スクロールバーの左端(上端)を 0
、右端(下端)を 1
とした時の、それぞれの相対的な位置を指定します。
スポンサーリンク
fraction
get
メソッドの解説時にも説明しましたが、スクロールバー上の位置は左端(上端)を 0
、右端(下端)を 1
とした 0
〜 1
の値で表現されます。
fraction
は、ピクセル単位の座標をこのスクロールバー上の位置に変換するメソッドです。
# barはスクロールバーのオブジェクト
pos = bar.fraction(x, y)
fraction
メソッドの引数は下記の2つになります。
x
:横方向の座標y
:縦方向の座標
delta
fraction
が単なる座標をスクロールバー上の位置に変換するメソッドであるのに対し、delta
はピクセル単位の横方向と縦方向それぞれの移動量を、スクロールバー上の位置で考えた時の移動量に変換するメソッドになります。
移動量なので、負の値の設定も可能であり、その場合は delta
メソッドも負の値を返却します。負の値の場合は、水平方向のスクロールバーの場合は左方向に、垂直方向のスクロールバーの場合は上方向に移動したことを表します。
# barはスクロールバーのオブジェクト
pos = bar.delta(dx, dy)
delta
メソッドの引数は下記の2つになります。
dx
:横方向の移動量dy
:縦方向の移動量
まとめ
このページでは、Tkinter でスクロールバーを作成する方法・設定の詳細・スクロールバーに用意されたメソッドについて解説しました。
スクロールバーのメイン機能は他のウィジェットをスクロールさせることです。
そのため、スクロールバーは単に作成するだけでなく、他のウィジェットをスクロールするための設定を行う必要があります。この辺りがスクロールバーウィジェット特有のポイントになります。
是非ご自身でスクロールバー付きのウィジェットを作成し、その動きを確認しながらスクロールバーウィジェットへの理解を深めてみてください!
オススメ参考書(PR)
Tkinter に興味がある方には下記のPythonでつくる ゲーム開発 入門講座がオススメです。
Tkinter をゲーム開発を通して「楽しく学ぶ」ことができます。Python 入門者、Tkinter 入門者の方にオススメです。