Python + PySimpleGUI でMySQLテーブル表示②

目次

テーブルの外観バリエーション例

Table エレメント

今回からはパーツを”ウィジェット”ではなく、公式HPに準じて”エレメント”と呼称を統一する。Table エレメントは PySimpleGUI でのテーブルデータ(表形式)表示機能で最も安直な方法である。
見た目とスタイルはリストボックスとほとんど変わらないし、スタイリッシュでもクールでもない。PySimpleGUI のエレメントデザインは全般的にクラシカルなイメージ。
しかし、今は外見にこだわって良い段階ではないのでデータ処理優先である。
とつぶやきつつ、オプション指定だけで雰囲気を変えることは出来るので一例だけやってみた。

化粧直し後
念のためオプションてんこ盛りテーブルのコードも残しておこう。
    [SG.Table(key="-リスト-",values=list(DATA),headings= 見出,col_widths=列幅,justification="left",
      row_height=24,font=("Helvetica",11),background_color="white",alternating_row_color="lightsteelblue",
      header_text_color="white", header_background_color="navy",header_relief ="RELIEF_SOLID",
      header_font=("Helvetica",11,"bold"),
      selected_row_colors =("white","red"),num_rows=12,auto_size_columns=False,enable_click_events=True)
     ],

Table 基本コード

headings と col_widths 見出と列幅設定

テーブル内容の表示は values=list(リスト型文字列) で実行されるがそれだけでは実用にならない。
レイアウトの前にテーブルの見出(ヘッダー)の設定を行うのでリスト型変数を準備しておく。
レイアウト部に直接書くより可読性が良くなるし、メンテナンスがしやすい。
列幅は指定しなくても自動調整はされるが、意図したような結果にならない場合が多いので、SQL文に合わせて適切に設定するべきである。

見出 = ['ID','名前','電話番号','メルアド']
列幅 = [4,12,12,30]

auto_size_columnsとjustification : 列幅定義の有効化と列内の文字配置

コードで列幅設定しても auto_size_columns=False で自動調整を無効にしないと反映されない。
また、デフォルトではカラム内右寄せで表示されるので justification=”left” で左寄せにする。
num_rows=20 はテーブルの表示行数設定。

L=[
    [SG.Table(key="-リスト-",values=list(DATA),headings= 見出,col_widths=列幅,justification="left",
              num_rows=20,auto_size_columns=False,enable_click_events=True)],    
    [SG.Text("選択した項目:"),SG.Text(key="-選択値-",size=40,font=("Helvetica",11,"bold"),
                                   text_color="blue",background_color="lightyellow")],
    [SG.Button("OK",key="OK"),SG.Button("閉じる",key="Cancel")],
]

enable_click_events : クリックイベントを発生させてセル(行と列)を特定

初期状態ではテーブル内をクリックしてもイベントが発生しないので enable 設定が必要。
もっとも重要なオプション引数が行と列の位置を特定出来る enable_click_events=True
enable_events という紛らわしいオプションもあるが、これは行数しか取得出来ないのでほぼ使い道がない。

+CLICKED+ : テーブルクリックイベントを検知

これにたどり着くまでどれほど時間とエネルギーを費やしたことか・・・( ;´・ω・`)
心が折れなくて良かった。二度と忘れないようしっかりメモしておこう。
window メインループの中でイベントを検知するのはこれまで通り。イベントは”+CLICKED+“だけでも動作はするが、ウィンドウ内にテーブルが1個とは限らないので条件式を複数キー名の組み合わせとしている。
つまり、サンプル程度のプログラムであれば条件式は if event==”+CLICKED+”: でも問題なく検出出来る。
ついでに文字列演習のため、in(演算子?)と and も使ってみた。
“-リスト-” in event のように、ある文字列が検索対象文字列内に存在していれば True を返す。

    if "-リスト-" in event and "+CLICKED+" in event:
        カラム名=見出[列番]
        列番=event[2][1]
        選択行=event[2][0]
        選択項目値=DATA[選択行][列番]
        window["-選択値-"].update(カラム名 +" : "+ str(選択項目値))      

イベントを検知したら、あとはリスト型変数から取得した値でテキストボックスを更新すれば選択したセルの値が表示される。リスト型変数を少し真面目に勉強した成果である。

イベント処理の仕組み

しかし。ここで 列番=event[2][1]選択行=event[2][0] の意味は何なんだとの疑問も発生するはず。
今なら説明出来る。(;`ー´)
プログラムのメインループ開始直後に呪文のように書いているイベント取得コードの内容を print 文でエディタのターミナルで確認してみると、アプリ起動直後には何も表示されず、何らかのイベントが発生した場合のみ内容を表示する。

while True:
    event,values=window.read()
    print(event,values)

event : イベント変数の正体

テーブルをクリックした時に window.read() 直後に返される event,values は次のような文字列になる。
event はタプル型の入れ子だが、後半のValues は {キー名 : [値] } 形式の辞書とされる型。
リアルタイムで値が反映されないため今回は使い道がないので無視している。
タプル型の値参照方法は、グループ文字列のインデックス番号を [ ] で指定する。

event の構造は タプル型変数(要素0,要素1,要素2,要素3 ・・・)
なので、2番目の要素であるテーブル行列値を参照するには次のサンプルコードの場合 event[2] となる。
しかも、テーブルから返る値も行と列のタプル型のため、さらに [ ] が必要で、行の参照には event[2,0] であり 列の参照は event[2][1] というややこしい書式になる。慣れれば良いだけなのだが、解明するまでに心が折れかけた。( ≧Д≦)
  [0]         [1]     [2][0], [2][1]     辞書型
('-リスト-', '+CLICKED+', (29  ,  2))       {'-リスト-': []}

ループ内で if “-リスト-” in event and “+CLICKED+” in event: という条件式にしているのは文字列演算の演習が目的だったためで、必要以上に複雑になってしまった。

そんなわけで、今回のプログラムはテーブル 1個だけのため、シンプルな条件式で
if event[0]==”-リスト-“:
if event[1]==”+CLICKED+”:
いずれも問題なく正常に動作することも確認できた。

イベント発生時の event の値は上記前半の (キー名,イベント名,(キーの値)) になる。
実行中にテーブルのどこかのセルをクリックして if 文で検知された場合の event 値はどうなるか。
テーブルの28行目の3列目をクリックした場合は、キー名が”-リスト-“、イベント名が”+CLICKED+“。
返り値はゼロで始まるので(29, 2) である。
テーブルクリックイベントで返される値が二次元配列のためその値が (行,列) を表す2個の数値になる。
ちなみにキー名だけが必要なら event[0]、イベント名だけなら event[1] とする。行列の値になるのは3番目の( )内なので、行の値が event[2][0]、列の値が event[2][1] になるのだった。アタマの体操になるな。( ゚∀゚)

プログラム実行終了時の event,values の内容。values に行数が格納されていることが分かる。
if 文処理時には空値のままなので、ちょっと意味が分からない。

('-リスト-', '+CLICKED+', (29, 2)) {'-リスト-': [29]}

今だからいえる「答えを知ればカンタン」( ゚∀゚)
難題をクリア出来たときは「楽しいプログラミング」になるのはムカシと変わらない。
しかし、まだまだ課題は山積みなので当分このシリーズは終われそうにないな。
サンプルコードの全容は前々回の記事に掲載してあるので省略する。
今日はこれでおしまい。( ´ー`)

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次