PythonでMySQLに接続(GUI-Tkinter編)
- 2023.04.05
- Tkinter
PythonでMySQLに接続してデータを取得し、グラフィカルベース(GUI)でデータを表示する。GUIの作成には、Pythonの標準GUI作成ツールであるTkinterを使用する。
使用したMySQLサーバーとリモートPCの諸元は次の通りである。
MySQLサーバー | リモートPC |
PC:HP630 (Celeron T3500, 2.1GHz/2コア) OS:Ubuntu MATE 18.04.6 64ビット メモリー:6GB システム媒体:SSD 64GB IPアドレス:192 . 168 . (abc) . (xyz) MySQL Community Server 5.7.41 | PC:Mate ML-D (Intel Core i5 2400S 2.5GHz) OS:Windows10 64ビット メモリー:12GB システム媒体:HDD 250GB Python 3.9.13 64-bit Anaconda3 2022.10 (Python 3.9.13 64-bit) PyCharm Community Edition 2022.3.2 |
- Ubuntu MATEへのMySQLのインストールについては、「Ubuntu MATEでMySQLを使う」を参照のこと。
MySQLサーバー側の設定
MySQL側の設定については、「PythonでMySQLに接続(CUI)」を参照のこと。
リモートPC側の設定(mysql-connector-pythonのインストール)
PythonからMySQLに接続するためには、接続モジュールのインストールが必要となる。このサイトでは、MySQL開発元のOracle社が公式ライブラリとして公開している’mysql-connector-python’を使う。
リモートPC側の設定については、「PythonでMySQLに接続(CUI)」を参照のこと。
実行結果のスナップショット
先に実行結果のスナップショットを示す。
画面のレイアウトは、以前紹介した「JavaからのDBアクセス(SWTによる表示)」と同様である。
◎ 指定した年号の一部の文字列に対して、3種類の検索条件を指定できる。
![](https://yoshitsune1.fc2.page/wordpress/wp-content/uploads/2023/04/ss_mysqltk_1.png)
◎ 検索したい年号(元号)の一部に“義”を指定して、“義”を「任意の位置に含む」年号を検索する。
そのような年号は存在しないので、データがない旨のダイアログが表示される。
![](https://yoshitsune1.fc2.page/wordpress/wp-content/uploads/2023/04/ss_mysqltk_2.png)
◎ 大河ドラマ・アンコールで「篤姫」が再放送されている。幕末のキーワード:嘉永の“嘉”を
「先頭に含む」年号を検索する。該当する年号のレコードが表形式で表示され、最下行の
ステータスバーには、「該当するレコードが11件あった」ことが表示される。
![](https://yoshitsune1.fc2.page/wordpress/wp-content/uploads/2023/04/ss_mysqltk_3.png)
ソースプログラム
GUIプログラムの作成にはTkinterモジュールを使用する。TkinterはPythonの標準モジュールなのでインストールの必要はない。importすることですぐに利用が可能である。
ソースプログラムと簡単な説明を以下に示す。なお、プログラムはIDLE、PyCharmのどちらのIDEからでも実行可能である。(各IDEの環境設定については、「PythonでMySQLに接続(CUI)」を参照のこと。)
import mysql.connector
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
col_list = [''] * 5
def msg_box(msg):
if msg == 'no_key':
tk.messagebox.showinfo(title='インフォメーション',
message='検索する文字(列)や位置の\n'
+ '指定を行ってください!!')
elif msg == 'no_data':
tk.messagebox.showinfo(title='インフォメーション',
message='該当するデータがありません!!')
elif msg == 'err_msg':
tk.messagebox.showerror(title='接続エラー',
message='データベースに接続できません!!\n'
+ 'ネットワーク周りを確認してください')
def db_search():
tree.delete(*tree.get_children())
stat_text.set('')
if not entry.get() or combobox.get() == '選択してください':
msg_box('no_key')
else:
if combobox.get() == 'を先頭に含む':
sqlKeyWord = "'" + entry.get() + "%'"
elif combobox.get() == 'を任意の位置に含む':
sqlKeyWord = "'%" + entry.get() + "%'"
elif combobox.get() == 'を末尾に含む':
sqlKeyWord = "'%" + entry.get() + "'"
try:
conn = mysql.connector.connect(
host='192.168.*.***',
user='myuser',
password='********',
database='gengo'
)
cursor = conn.cursor()
# データを取得
sql = 'select * from main where nengo like ' + sqlKeyWord # SQL文を指定
cursor.execute(sql)
rows = cursor.fetchall()
if not cursor.rowcount:
# コネクションを閉じる
cursor.close()
conn.close()
msg_box('no_data')
return
stat_text.set('該当するレコードは' + str(cursor.rowcount) + '件でした')
# 要素の切り出しと表への埋め込み
for row in range(cursor.rowcount):
for col in range(5):
col_list[col] = rows[row][col + 1]
if col == 4:
tree.insert(parent='',
index='end',
values=(col_list))
# コネクションを閉じる
cursor.close()
conn.close()
except:
msg_box('err_msg')
return
# ★バグ対応用の関数 - Python 3.7.3以降で不具合
def fixed_map(option):
return [elm for elm in style.map('Treeview.Heading', query_opt=option) if
elm[:2] != ('!disabled', '!selected')]
# メインウィンドウの設定
root = tk.Tk()
root.resizable(False, False)
root.title('元号DBの検索')
root.geometry('395x400')
### menubarの作成と設置 ###
# menubarの大元(コンテナ)の作成と設置
menubar = tk.Menu(root)
root.config(menu=menubar)
# menubarを親としてファイルメニュを作成・表示
set_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label='ファイル', menu=set_menu)
# ファイルメニュにプルダウンメニュを追加
set_menu.add_command(label='終了', command = root.destroy)
### menubarの終了 ###
# メインフレームの作成と設置
frame = ttk.Frame(root)
frame.grid(column=0, row=0, padx=5, pady=2, sticky=tk.NSEW)
# StringVarのインスタンスを格納するウィジェット変数stat_text - ステータスバーに表示
stat_text = tk.StringVar(frame)
stat_text.set('')
# 各種ウィジェットの作成
label = ttk.Label(frame, text='検索したい年号(元号)の一部を指定してください')
entry = ttk.Entry(frame, width=18)
combobox = ttk.Combobox(frame, state='readonly', values=[
'を先頭に含む',
'を任意の位置に含む',
'を末尾に含む'])
combobox.set('選択してください')
button = ttk.Button(frame, text='検索', command=db_search)
# 列の識別名を指定
column = ('年号', 'よみ', '開始年', '終了年', '時代')
# Treeviewの生成
tree = ttk.Treeview(frame, padding=(5, 5, 5, 5), height=14, columns=column)
# 見出しのスタイルを指定
style = ttk.Style()
style.configure("Treeview.Heading", foreground="blue")
# ★バグ対応を処理 - Python 3.7.3以降で不具合
style.map('Treeview.Heading', foreground=fixed_map('foreground'))
# 列の設定
tree["columns"] = (1, 2, 3, 4, 5)
tree["show"] = "headings"
tree.column(1, anchor='e', width=60)
tree.column(2,anchor='e', width=110)
tree.column(3, anchor='e', width=55)
tree.column(4, anchor='e', width=55)
tree.column(5, anchor='e', width=60)
# 列の見出し設定
tree.heading(1, text='年号', anchor='e')
tree.heading(2, text='よみ', anchor='e')
tree.heading(3,text='開始年', anchor='e')
tree.heading(4, text='終了年', anchor='e')
tree.heading(5, text='時代', anchor='e')
# スクロールバーの追加
scrollbar = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=tree.yview)
tree["yscrollcommand"] = scrollbar.set
# Labelをステータスバーに使用
statusbar = ttk.Label(frame,
textvariable=stat_text,
font=('',12,'bold'),
foreground='DarkOrange',
relief=tk.GROOVE,
anchor='w')
# 各種ウィジェットの設置
label.grid(row=0, column=0, padx=10, stick=tk.W)
entry.grid(row=1, column=0, padx=12, sticky=tk.W)
combobox.grid(row=1, column=0, padx=(132, 0), sticky=tk.W)
button.grid(row=1, column=0, padx=(285,0), sticky=tk.W)
tree.grid(row=2, column=0, padx=(10,0), pady=(3,0), sticky=tk.W)
scrollbar.grid(row=2, column=1, padx=0, sticky=(tk.NS))
statusbar.grid(row=3, column=0, padx=(10,0), pady=(0,0), sticky=tk.EW)
root.mainloop()
- 26~32行目
sql文の検索条件部(like以下)の文字列を作成する。
- 45行目
select部と検索条件部をつないでsql文を作成する。
- 61~67行目
検索結果は、recordとfieldの二次元のリスト’rows[row][col]’に返ってくるので、1recordずつ各fieldを切り出してTreeviewウイジェットのinsert文で表に埋め込む。
ここで、先頭の’id’ fieldは表示させないので、リストの第二要素から切り出す。(rows[row][col + 1]) - 78~80、125行目
Python3.7.3(正確には、TkinterモジュールのVersion8.6.9以降。)にはTkinterモジュールのTreeviewウイジェットの色表示に不具合があるので、これを回避する。 - 144行目
Tkinterにはステータスバーの機能がないので、Labelウイジェットで代用する。
参考URL
・ OFFICE54 Pythonの基本
・ CTC教育サービス ゼロから歩くPythonの道
・ SyachikuLOG PythonのTkinterのTree内の表データの文字色/背景色を指定②【バグへの対応】
-
前の記事
PythonでMySQLに接続(CUI) 2023.03.15
-
次の記事
挿し木のクレマチスが早くも咲いた!! 2023.04.09