Tkinter、Textの使い方

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

Python - Tkinter
2018年12月10日15:52に更新(約1日前)
2018年12月8日18:11に作成(約3日前)

旧ブログ移行記事です。

概要

Pythonに標準で付属しているGUIライブラリのTkinterにある、複数行文字列の入力・管理に便利なTextウィジェットの使い方を紹介します。

こんな感じの見た目です。

当然、文字を入力することができます。すぐあとで紹介しますが、プログラム上から文字を直接挿入することもできます。

テキストウィジェットを表示するには、単純にtk.Text()とします。

import tkinter as tk

root = tk.Tk()
root.title('Editor Test')

text_widget = tk.Text(root)
text_widget.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.E, tk.W))

root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
root.mainloop()

insert() 文章の挿入

Textウィジェットを使う上でまず理解するべきなのは、文字の位置を表す方法です。文章を指定位置に挿入するinsert()メソッドを使いながら、実際に見ていきましょう。

text_widget.insert('1.0', 'あいうえお\nかきくけこ\nさしすせそ')

上のコードは、次のように表示されます。

insert()メソッドは、第一引数に位置を、第二引数に挿入する文字を指定します

1.0が1行目0文字目を意味します。行番号は1から、文字は0から始まります。つまり、上のコードはTextウィジェットの一番最初に文章を挿入しろという指定です。

次のコードはどうでしょうか。

text_widget.insert('1.0', 'あいうえお\nかきくけこ\nさしすせそ')
text_widget.insert('2.0', '2行目に挿入されます\n')

ちゃんと2行目0文字目から挿入されましたね。

1行目の4文字目から文字を挿入してみましょう。0から数えるので、'1.3'のようにします。

text_widget.insert('1.0', 'あいうえお\nかきくけこ\nさしすせそ')
text_widget.insert('1.3', '★')

ちゃんと挿入されましたね。

今までは1.0のように指定していましたが、位置を表す特殊な文字列があります。まずよく使うのは、endです。

text_widget.insert('end', 'おわりです')

これは分かりやすいです。Textウィジェットの最後に文章を挿入します。

insertを指定すると、これはカーソル位置に文字列が挿入されます。

text_widget.insert('insert', 'カーソル位置に挿入されます')

get() 文章の取得

上で紹介した位置の指定は、他のメソッドでも同様です。Textウィジェット内の文字を取得するget()メソッドで試してみましょう。

例えば、次の画像のように入力されていたとします。

get()メソッドは、第一引数から第二引数までの文章を取得してくれます。なので、最初から最後まではなら1.0endを指定すればよさそうですが...

result = text_widget.get('1.0', 'end')

実はこれはちょっと違っていて、endではなくend -1cとする必要があります。

result = text_widget.get('1.0', 'end -1c')

-1cは-1 char の意味です。つまり-1文字ですね。このように位置情報の後につけれる文字も幾つかありますので、紹介しましょう。

-があるのですから、+もあります。例えばカーソル位置の次の文字を取得したいならば、次のように書けます。

result = text_widget.get('insert', 'insert +1c')

linestart, lineendというものもあります。それぞれ行の最初、最後を意味します。次のコードは、カーソルがある行のテキストを全て取得する例です。

result = text_widget.get('insert linestart', 'insert lineend')

カーソル位置までの現在行のテキストならばget('insert linestart', 'insert')ですし、カーソル位置移行の現在行のテキストならばget('insert', 'insert lineend')です。

delete() 文章の削除

もうおわかりですね。次のコードはTextウィジェットの全ての文章を削除します。

text_widget.delete('1.0', 'end')

index() 位置を返す

意外に使うのがindex()です。これは今までに指定してきたような、位置の文字列を取得できます。

具体例をあげると、現在のカーソル位置を知りたいならば次のように書けます。

pos = text_widget.index('insert')

1.0とかそういう文字列として帰ってくるので、他のメソッドにそのまま渡すことができます。

x, y座標→行・列

長い行のテキストを書いたとします。100行や200行になると全てを表示できなくなり、スクロールする必要があります。

スクロールをしたあと、一番上に表示されてるのは実際の行番号で言えばどこか?といったことを知りたいこともあるでしょう。実際、行番号付きのプログラミングエディタを作っていたらこの課題に直面しました。

下の画像は5行目なら5、と数字を入れていますが、この数字がなくなったらどう判別できるでしょうか。

@x,yのような書き方を使います。ドットではなくカンマです

pos = text_widget.index('@0,0')

これは、今見えているTextウィジェット内のx, y座標にある(最も近い)文字の位置を返します。@0.0とすると、画面左上の実際の行番号が取得できるという訳です。

タグ

次の画像は、ウィジェット内の文章を選択しています。

選択している開始位置、終了位置をしりたいかもしれません。次のように書くと2.03.5が取得できます。

start = text_widget.index('sel.first')
end = text_widget.index('sel.last')

Textウィジェットにはタグという機能があり、タグはウィジェット内の文章に自由に指定できます。色を変えたり、イベントと紐づけたり、何らかの状態を表すのに使います。

上のselはタグの名前で、選択状態時に適用されるタグです。これはTkinterに標準で用意されているタグなのですが、自分でタグを定義することもできます。

タグ名.firstタグ名.lastのようにすると、そのタグの最初や最後の文字位置を取得することもできます。

例えば、選択された部分のテキストは次のように取得できます。

sel_text = text_widget.get('sel.first', 'sel.last')

タグを追加するには、tag_add(タグ名, 開始位置, 終了位置)とします。次のコードは、全ての文章をプログラムで選択状態にします。Ctrl+Aでの動作ですね。

text_widget.tag_add('sel', '1.0', 'end')

タグを削除するには、tag_remove(タグ名, 開始位置, 終了位置)を使います。

ユーザー定義のタグ

タグを作ってみましょう。まず、タグの定義を作成します。backgroundは、そのタグの背景色ですね。文字色を変える場合は、foregroundを使います。

text_widget.tag_configure('Red', background='#ff0000')

後はtag_add()とするだけです。次のコードを適当なイベントに紐づけて実行すると、カーソルのある行が赤くなります。

text_widget.tag_add('Red', 'insert linestart', 'insert lineend')

この独自タグも当然Red.first のようにして位置として利用できます。ただ、そのタグが複数つけられていた場合に注意です。次の画像のような状態ですね。

この画像の例ならば、Red.firstは2.0で、Red,lastは5.3です。つまり、全体を通しての最初と最後が取得されるのです。飛び地みたいに別々の場所にタグがついているとして、それぞれの場所を知りたいのかもしれません。

このような場合、tag_ranges()が助けになります。次のように書くとタグの全ての開始位置と終了位置がわかります。

positions = text_widget.tag_ranges('Red')
for pos in positions:
    print(pos)
2.0
2.5
5.0
5.3

位置の書き方のサンプル

欲しい位置 書き方
1行目の最初の位置(文書の最初) '1.0'
1行目の最後の位置 '1.end' ('1.0 lineend'も同様)
最後の行の最後の位置 'end'
カーソル位置 'insert'
カーソル位置の同じ行で次の位置 'insert +1c'
カーソル位置の同じ行で前の位置 'insert -1c'
カーソル位置の同じ行で最初の位置 'insert linestart'
カーソル位置の同じ行で最後の位置 'insert lineend'
カーソル位置の次の行で同じ位置 'insert +1lines'
カーソル位置の前の行で同じ位置 'insert -1lines'
カーソル位置の次の行の最後 'insert +1lines lineend'
カーソル位置にある単語の最初の位置 'insert wordstart'
カーソル位置にある単語の最後の位置 'insert wordend'
以降、+1cやlinestart等のサンプルは省きます
マウスポインタの位置 'current'
選択した最初の位置 'sel.first'
選択した最後の位置 'sel.last'
そのタグの最初の位置 'タグ名.first'
そのタグの最後の位置 'タグ名.last'
タグがついた全ての位置 tag_ranges('タグ名') -> 位置を1つずつ返す
今見えているx, y座標に近い文字の位置 '@x,y'
Twitterでシェア FaceBookでシェア はてなブックマークでシェア

記事にコメントする