Python

PythonのTkinterのTree内の表データの文字色/背景色を指定②【バグへの対応】

Python

前回に引き続き、TkinterのTreeでの見た目をよくする方法についてです。

前回はTree全体的なフォントやヘッダの色などを変更しましたが、今回は表のデータに当たる部分の文字色や背景を変更する方法について紹介いたします。

はじめに私のほうでTkinterでTreeの文字色の変更方法について調べたところ、様々な方法が出てきますが、試してもうまく文字色が変わらずにイラついてました。

調べた結果、Python(正確にはPythonのバージョンに紐づいて動作するTkiner)のバージョンが新しい(Ver3.7以降)場合にはバグがあって旧バージョン(Ver3.6)のやり方ではうまくいかないことが分かりました

バグの内容と対応方法については以下に記載があるとおりですが、結構この部分ではまる方もいそうなので対応方法について少しまとめてみました。

Issue 36468: Treeview: wrong color change - Python tracker

試した環境

・Windows 10 Pro v2004
・Python 3.8.5

TkinterのTree内の表データの文字色/背景色を指定する方法

作りたい画面

まずは画面からになりますが、最終的にはこんな感じで表のデータ部分に文字色や背景色を付けたいと思います。前回からの続きなので取り消し線などもついてます。

サンプルコード

最終的なコードは以下になります。

import tkinter as tk
import tkinter.ttk as ttk

# ★バグ対応用の関数を追加
def fixed_map(option):
    return [elm for elm in style.map('Treeview', query_opt=option) if
            elm[:2] != ('!disabled', '!selected')]

root = tk.Tk()
root.title("自由なタイトル")
root.geometry("400x200")

tree = ttk.Treeview(root)

style = ttk.Style()
style.configure("Treeview.Heading", font=("YU Mincho", 12, "bold", "italic", "underline" ), rowheight=100, foreground="blue")
style.configure("Treeview", font=("Arial", 10, "overstrike"), rowheight=50)

# ★バグ対応を処理
style.map('Treeview', foreground=fixed_map('foreground'), background=fixed_map('background'))

# 列を3列作る
tree["column"] = (1, 2, 3)
tree["show"] = "headings"
# ヘッダーテキスト
tree.heading(1, text="列1")
tree.heading(2, text="列2")
tree.heading(3, text="列3")
# 列の幅
tree.column(1, width=100)
tree.column(2, width=200)
tree.column(3, width=100)

# データ挿入 ★tagsを追加
tree.insert("", "end", values=("1", "あいうえお", "abcde"), tags="red")
tree.insert("", "end", values=("2", "かきくけこ", "fghijk"), tags="green")
tree.insert("", "end", values=("3", "さしすせそ", "lmnop"), tags="blue")

# ★tagsで文字色や背景色を指定
tree.tag_configure("red", foreground='red')
tree.tag_configure("green", background='green')
tree.tag_configure("blue", foreground='blue')

tree.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

root.mainloop()
import tkinter.font as tkFont
print(list(tkFont.families()))

解説

前回のコードをベースとして、修正部分について解説します。(変更部分は★でコメントしている部分です)

通常は以下のようにtagsを追加することで色を指定することができますが、先ほども記載した通りPython3.7以降の場合にはTkinterのバグがあって動作しません。

# データ挿入 ★tagsを追加
tree.insert("", "end", values=("1", "あいうえお", "abcde"), tags="red")
tree.insert("", "end", values=("2", "かきくけこ", "fghijk"), tags="green")
tree.insert("", "end", values=("3", "さしすせそ", "lmnop"), tags="blue")

# ★tagsで文字色や背景色を指定
tree.tag_configure("red", foreground='red')
tree.tag_configure("green", background='green')
tree.tag_configure("blue", foreground='blue')

対応方法として色を指定してるけど反映されないバグ対応のために以下のコードを追加します。

バグのある設定部分を上書きして正常動作するようにしているようです。

# ★バグ対応用の関数を追加
def fixed_map(option):
    return [elm for elm in style.map('Treeview', query_opt=option) if
            elm[:2] != ('!disabled', '!selected')]
・
(省略)
・
# ★バグ対応を処理
style.map('Treeview', foreground=fixed_map('foreground'), background=fixed_map('background'))

まとめ

今回はTkinterでTreeの表データ部分の文字色の変更方法について説明しました。プログラミングをしていると思わぬバグに遭遇することは多くあります。

バグに対して文句を言うよりも、どのような対応方法があるかを見極めて的確に対応することが必要となります。

今回は以上となります。

コメント