2025年8月2日 星期六

Open Data 動物認領養---Python TKinter

Open Data 動物認領養---Python TKinter

資料提供包括:動物的流水編號、動物的收容編號、動物所屬縣市代碼、動物所屬收容所代碼、動物的實際所在地、動物的類型、動物性別、動物體型、動物毛色、動物年紀、是否絕育、是否施打狂犬病疫苗、動物尋獲地、動物網頁標題、動物狀態、資料備註、其他說明、開放認養時間(起)、開放認養時間(迄)、動物資料異動時間、動物資料建立時間、動物所屬收容所名稱、圖片名稱、異動時間、資料更新時間、地址、聯絡電話、動物品種等欄位資訊。
<政府資料開放平臺資料使用規範>


import urllib.request

import json

import ssl

import tkinter as tk

from tkinter import ttk, messagebox


# 資料來源 URL

url = 'https://data.moa.gov.tw/Service/OpenData/TransService.aspx?UnitId=QcbUEzN6E6DL'


# 全域變數,用於儲存所有動物資料

all_animal_data = []


def get_animal_data():

    """從 URL 獲取所有動物認領養資料。"""

    try:

        context = ssl._create_unverified_context()

        with urllib.request.urlopen(url, context=context) as jsondata:

            data = json.loads(jsondata.read().decode())

        return data

    except Exception as e:

        messagebox.showerror("資料載入錯誤", f"無法獲取動物資料。\n錯誤訊息:{e}")

        return []


def populate_treeview(treeview, data):

    """清除並填充 Treeview 表格。"""

    # 清空舊資料

    for item in treeview.get_children():

        treeview.delete(item)

    

    # 插入新資料 (新增了三項資料)

    for item in data:

        treeview.insert('', 'end', values=(

            item.get('animal_kind', 'N/A'),

            item.get('animal_sex', 'N/A'),

            item.get('animal_colour', 'N/A'),

            item.get('animal_age', 'N/A'),

            item.get('shelter_name', 'N/A'),

            item.get('animal_bodytype', 'N/A'),

            item.get('animal_opendate', 'N/A'),

            item.get('shelter_tel', 'N/A')

        ))


def on_filter_change(event, treeview, status_label, kind_var):

    """下拉式選單選項改變時,篩選並更新表格。"""

    selected_kind = kind_var.get()

    

    if selected_kind == "所有種類":

        filtered_data = all_animal_data

    else:

        filtered_data = [item for item in all_animal_data if item.get('animal_kind') == selected_kind]


    populate_treeview(treeview, filtered_data)

    status_label.config(text=f"顯示 {len(filtered_data)} 筆動物資料")


def create_main_window():

    """建立 Tkinter 主視窗。"""

    global all_animal_data

    

    root = tk.Tk()

    root.title("動物認領養資訊查詢")

    root.geometry("1100x600") # 調整視窗寬度以容納更多欄位


    main_frame = ttk.Frame(root, padding="10")

    main_frame.pack(fill="both", expand=True)


    # 頂部篩選區

    filter_frame = ttk.Frame(main_frame)

    filter_frame.pack(fill="x", pady=5)

    

    ttk.Label(filter_frame, text="篩選動物種類:").pack(side="left", padx=(0, 5))

    

    # 取得動物種類清單

    kinds = sorted(list(set(item.get('animal_kind') for item in all_animal_data if item.get('animal_kind'))))

    kinds.insert(0, "所有種類")

    

    kind_var = tk.StringVar(value="所有種類")

    kind_combobox = ttk.Combobox(filter_frame, textvariable=kind_var, values=kinds, state="readonly")

    kind_combobox.pack(side="left", fill="x", expand=True)


    # 建立 Treeview 表格

    # 變動 1: 新增欄位識別名稱

    columns = ('kind', 'sex', 'colour', 'age', 'shelter', 'bodytype', 'opendate', 'shelter_tel')

    treeview = ttk.Treeview(main_frame, columns=columns, show='headings')

    

    treeview.heading('kind', text='動物種類')

    treeview.column('kind', width=100)

    treeview.heading('sex', text='性別')

    treeview.column('sex', width=50)

    treeview.heading('colour', text='毛色')

    treeview.column('colour', width=100)

    treeview.heading('age', text='年齡')

    treeview.column('age', width=50)

    treeview.heading('shelter', text='收容所')

    treeview.column('shelter', width=150)

    # 變動 2: 新增欄位標題與寬度

    treeview.heading('bodytype', text='體型')

    treeview.column('bodytype', width=70)

    treeview.heading('opendate', text='開放認養日')

    treeview.column('opendate', width=120)

    treeview.heading('shelter_tel', text='收容所電話')

    treeview.column('shelter_tel', width=120)


    # 加入滾動條

    scrollbar = ttk.Scrollbar(main_frame, orient="vertical", command=treeview.yview)

    treeview.configure(yscrollcommand=scrollbar.set)

    scrollbar.pack(side="right", fill="y")

    treeview.pack(fill="both", expand=True)

    

    # 狀態列

    status_label = ttk.Label(root, text="正在載入資料...", relief="sunken", anchor="w")

    status_label.pack(side="bottom", fill="x")


    # 繫結事件

    kind_combobox.bind("<<ComboboxSelected>>", lambda event: on_filter_change(event, treeview, status_label, kind_var))

    

    # 初始載入資料

    populate_treeview(treeview, all_animal_data)

    status_label.config(text=f"顯示 {len(all_animal_data)} 筆動物資料")


    root.mainloop()


if __name__ == "__main__":

    all_animal_data = get_animal_data()

    if all_animal_data:

        create_main_window()


沒有留言:

張貼留言

ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite

 ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite  ESP32 VS Code 程式 ; PlatformIO Project Configuration File ; ;   Build op...