# -*- coding: utf-8 -*-
"""
五柱十字干支万年历 v1.0
基于 sxtwl 库精确计算,修正刻柱算法
支持公元0年 - 9999年(1900-2100年精确节气)
"""

import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
from datetime import datetime, timedelta
import pytz
from itertools import cycle, repeat

try:
    from sxtwl import fromSolar
    import sxtwl
    SXTWL_AVAILABLE = True
except ImportError:
    SXTWL_AVAILABLE = False

# ==================== 常量(同上,省略)====================
tian_gan = '甲乙丙丁戊己庚辛壬癸'
di_zhi = '子丑寅卯辰巳午未申酉戌亥'
jqmc = ['小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨',
        '立夏', '小满', '芒种', '夏至', '小暑', '大暑', '立秋', '处暑',
        '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪', '冬至']
lunar_m = ['占位', '正月', '二月', '三月', '四月', '五月', '六月', 
           '七月', '八月', '九月', '十月', '冬月', '腊月']
jieqi_to_dizhi = {
    '立春': '寅', '雨水': '寅', '惊蛰': '卯', '春分': '卯', '清明': '辰', '谷雨': '辰',
    '立夏': '巳', '小满': '巳', '芒种': '午', '夏至': '午', '小暑': '未', '大暑': '未',
    '立秋': '申', '处暑': '申', '白露': '酉', '秋分': '酉', '寒露': '戌', '霜降': '戌',
    '立冬': '亥', '小雪': '亥', '大雪': '子', '冬至': '子', '小寒': '丑', '大寒': '丑'
}
fivetigers = {
    tuple(list('甲己')): '丙寅', tuple(list('乙庚')): '戊寅', tuple(list('丙辛')): '庚寅',
    tuple(list('丁壬')): '壬寅', tuple(list('戊癸')): '甲寅'
}
fiverats = {
    tuple(list('甲己')): '甲子', tuple(list('乙庚')): '丙子', tuple(list('丙辛')): '戊子',
    tuple(list('丁壬')): '庚子', tuple(list('戊癸')): '壬子'
}
fivehourses = {
    tuple(list('丙辛')): '甲午', tuple(list('丁壬')): '丙午', tuple(list('戊癸')): '戊午',
    tuple(list('甲己')): '庚午', tuple(list('乙庚')): '壬午'
}
nayin_dict = {
    '甲子': '海中金', '乙丑': '海中金', '丙寅': '炉中火', '丁卯': '炉中火', '戊辰': '大林木', '己巳': '大林木',
    '庚午': '路旁土', '辛未': '路旁土', '壬申': '剑锋金', '癸酉': '剑锋金', '甲戌': '山头火', '乙亥': '山头火',
    '丙子': '涧下水', '丁丑': '涧下水', '戊寅': '城头土', '己卯': '城头土', '庚辰': '白蜡金', '辛巳': '白蜡金',
    '壬午': '杨柳木', '癸未': '杨柳木', '甲申': '泉中水', '乙酉': '泉中水', '丙戌': '屋上土', '丁亥': '屋上土',
    '戊子': '霹雳火', '己丑': '霹雳火', '庚寅': '松柏木', '辛卯': '松柏木', '壬辰': '长流水', '癸巳': '长流水',
    '甲午': '沙中金', '乙未': '沙中金', '丙申': '山下火', '丁酉': '山下火', '戊戌': '平地木', '己亥': '平地木',
    '庚子': '壁上土', '辛丑': '壁上土', '壬寅': '金箔金', '癸卯': '金箔金', '甲辰': '佛灯火', '乙巳': '佛灯火',
    '丙午': '天河水', '丁未': '天河水', '戊申': '大驿土', '己酉': '大驿土', '庚戌': '钗钏金', '辛亥': '钗钏金',
    '壬子': '桑柘木', '癸丑': '桑柘木', '甲寅': '大溪水', '乙卯': '大溪水', '丙辰': '沙中土', '丁巳': '沙中土',
    '戊午': '天上火', '己未': '天上火', '庚申': '石榴木', '辛酉': '石榴木', '壬戌': '大海水', '癸亥': '大海水'
}
xunshou_dict = {
    '甲子': '甲子', '乙丑': '甲子', '丙寅': '甲子', '丁卯': '甲子', '戊辰': '甲子', '己巳': '甲子', '庚午': '甲子', '辛未': '甲子', '壬申': '甲子', '癸酉': '甲子',
    '甲戌': '甲戌', '乙亥': '甲戌', '丙子': '甲戌', '丁丑': '甲戌', '戊寅': '甲戌', '己卯': '甲戌', '庚辰': '甲戌', '辛巳': '甲戌', '壬午': '甲戌', '癸未': '甲戌',
    '甲申': '甲申', '乙酉': '甲申', '丙戌': '甲申', '丁亥': '甲申', '戊子': '甲申', '己丑': '甲申', '庚寅': '甲申', '辛卯': '甲申', '壬辰': '甲申', '癸巳': '甲申',
    '甲午': '甲午', '乙未': '甲午', '丙申': '甲午', '丁酉': '甲午', '戊戌': '甲午', '己亥': '甲午', '庚子': '甲午', '辛丑': '甲午', '壬寅': '甲午', '癸卯': '甲午',
    '甲辰': '甲辰', '乙巳': '甲辰', '丙午': '甲辰', '丁未': '甲辰', '戊申': '甲辰', '己酉': '甲辰', '庚戌': '甲辰', '辛亥': '甲辰', '壬子': '甲辰', '癸丑': '甲辰',
    '甲寅': '甲寅', '乙卯': '甲寅', '丙辰': '甲寅', '丁巳': '甲寅', '戊午': '甲寅', '己未': '甲寅', '庚申': '甲寅', '辛酉': '甲寅', '壬戌': '甲寅', '癸亥': '甲寅'
}

# ==================== 辅助函数 ====================

def jiazi():
    return list(map(lambda x: "{}{}".format(tian_gan[x % 10], di_zhi[x % 12]), list(range(60))))

def multi_key_dict_get(d, k):
    for keys, v in d.items():
        if k in keys:
            return v
    return None

def new_list(olist, o):
    a = olist.index(o)
    return olist[a:] + olist[:a]

def repeat_list(n, thelist):
    return [repetition for i in thelist for repetition in repeat(i, n)]

# ==================== 节气计算(同上,省略)====================
_JIEQI_CACHE = {}

def get_jieqi_start_date(year, month, day, hour, minute):
    current_datetime = datetime(year, month, day, hour, minute)
    cache_key = (year, month, day, hour // 4)
    if cache_key in _JIEQI_CACHE:
        cached = _JIEQI_CACHE[cache_key]
        if (current_datetime - cached["cache_time"]).seconds < 86400:
            return cached["result"].copy()
    if 1900 <= year <= 2100 and SXTWL_AVAILABLE:
        try:
            day_obj = fromSolar(year, month, day)
            if day_obj.hasJieQi():
                jq_index = day_obj.getJieQi()
                jd = day_obj.getJieQiJD()
                t = sxtwl.JD2DD(jd)
                result = {"年": t.Y, "月": t.M, "日": t.D, "时": int(t.h), "分": round(t.m),
                          "节气": jqmc[jq_index - 1], "时间": datetime(t.Y, t.M, t.D, int(t.h), round(t.m))}
                _JIEQI_CACHE[cache_key] = {"result": result, "cache_time": current_datetime}
                return result.copy()
            else:
                current_day = day_obj
                for _ in range(15):
                    current_day = current_day.before(1)
                    if current_day.hasJieQi():
                        jq_index = current_day.getJieQi()
                        jd = current_day.getJieQiJD()
                        t = sxtwl.JD2DD(jd)
                        result = {"年": t.Y, "月": t.M, "日": t.D, "时": int(t.h), "分": round(t.m),
                                  "节气": jqmc[jq_index - 1], "时间": datetime(t.Y, t.M, t.D, int(t.h), round(t.m))}
                        _JIEQI_CACHE[cache_key] = {"result": result, "cache_time": current_datetime}
                        return result.copy()
        except:
            pass
    jieqi_table = [(1, 5, '小寒'), (1, 20, '大寒'), (2, 4, '立春'), (2, 19, '雨水'),
        (3, 5, '惊蛰'), (3, 20, '春分'), (4, 4, '清明'), (4, 20, '谷雨'),
        (5, 5, '立夏'), (5, 21, '小满'), (6, 5, '芒种'), (6, 21, '夏至'),
        (7, 7, '小暑'), (7, 23, '大暑'), (8, 7, '立秋'), (8, 23, '处暑'),
        (9, 7, '白露'), (9, 23, '秋分'), (10, 8, '寒露'), (10, 23, '霜降'),
        (11, 7, '立冬'), (11, 22, '小雪'), (12, 7, '大雪'), (12, 21, '冬至')]
    jieqi = '冬至'
    jieqi_date = None
    for m, d, name in jieqi_table:
        if m < month or (m == month and d <= day):
            jieqi = name
            jieqi_date = datetime(year, m, d, 0, 0)
        else:
            break
    if jieqi_date is None:
        jieqi_date = current_datetime
    result = {"年": year, "月": jieqi_date.month, "日": jieqi_date.day, 
              "时": 0, "分": 0, "节气": jieqi, "时间": jieqi_date}
    _JIEQI_CACHE[cache_key] = {"result": result, "cache_time": current_datetime}
    return result.copy()

def get_next_jieqi_start_date(year, month, day, hour, minute):
    current_datetime = datetime(year, month, day, hour, minute)
    cache_key = (year, month, day, hour // 4, 'next')
    if cache_key in _JIEQI_CACHE:
        cached = _JIEQI_CACHE[cache_key]
        if (current_datetime - cached["cache_time"]).seconds < 86400:
            return cached["result"].copy()
    if 1900 <= year <= 2100 and SXTWL_AVAILABLE:
        try:
            day_obj = fromSolar(year, month, day)
            current_day = day_obj.after(1)
            while True:
                if current_day.hasJieQi():
                    jq_index = current_day.getJieQi()
                    jd = current_day.getJieQiJD()
                    t = sxtwl.JD2DD(jd)
                    result = {"年": t.Y, "月": t.M, "日": t.D, "时": int(t.h), "分": round(t.m),
                              "节气": jqmc[jq_index - 1], "时间": datetime(t.Y, t.M, t.D, int(t.h), round(t.m))}
                    _JIEQI_CACHE[cache_key] = {"result": result, "cache_time": current_datetime}
                    return result.copy()
                current_day = current_day.after(1)
        except:
            pass
    jieqi_table = [(1, 5, '小寒'), (1, 20, '大寒'), (2, 4, '立春'), (2, 19, '雨水'),
        (3, 5, '惊蛰'), (3, 20, '春分'), (4, 4, '清明'), (4, 20, '谷雨'),
        (5, 5, '立夏'), (5, 21, '小满'), (6, 5, '芒种'), (6, 21, '夏至'),
        (7, 7, '小暑'), (7, 23, '大暑'), (8, 7, '立秋'), (8, 23, '处暑'),
        (9, 7, '白露'), (9, 23, '秋分'), (10, 8, '寒露'), (10, 23, '霜降'),
        (11, 7, '立冬'), (11, 22, '小雪'), (12, 7, '大雪'), (12, 21, '冬至')]
    for m, d, name in jieqi_table:
        if m > month or (m == month and d > day):
            next_date = datetime(year, m, d, 0, 0)
            result = {"年": year, "月": m, "日": d, "时": 0, "分": 0, 
                      "节气": name, "时间": next_date}
            _JIEQI_CACHE[cache_key] = {"result": result, "cache_time": current_datetime}
            return result.copy()
    m, d, name = jieqi_table[0]
    next_date = datetime(year + 1, m, d, 0, 0)
    result = {"年": year + 1, "月": m, "日": d, "时": 0, "分": 0, 
              "节气": name, "时间": next_date}
    _JIEQI_CACHE[cache_key] = {"result": result, "cache_time": current_datetime}
    return result.copy()

def jq(year, month, day, hour, minute):
    try:
        current_datetime = datetime(year, month, day, hour, minute)
        jq_start_dict = get_jieqi_start_date(year, month, day, hour, minute)
        next_jq_start_dict = get_next_jieqi_start_date(year, month, day, hour, minute)
        if not jq_start_dict or not next_jq_start_dict:
            month_map = {1: '小寒', 2: '立春', 3: '惊蛰', 4: '清明',
                         5: '立夏', 6: '芒种', 7: '小暑', 8: '立秋',
                         9: '白露', 10: '寒露', 11: '立冬', 12: '大雪'}
            return month_map.get(month, '冬至')
        jq_start_datetime = jq_start_dict["时间"]
        next_jq_start_datetime = next_jq_start_dict["时间"]
        jq_name = jq_start_dict["节气"]
        if jq_start_datetime <= current_datetime < next_jq_start_datetime:
            return jq_name
        elif current_datetime < jq_start_datetime:
            return jq_name
        else:
            return jq_name
    except Exception:
        month_map = {1: '小寒', 2: '立春', 3: '惊蛰', 4: '清明',
                     5: '立夏', 6: '芒种', 7: '小暑', 8: '立秋',
                     9: '白露', 10: '寒露', 11: '立冬', 12: '大雪'}
        return month_map.get(month, '冬至')

def lunar_date_d(year, month, day):
    if SXTWL_AVAILABLE:
        try:
            day_obj = fromSolar(year, month, day)
            return {"年": day_obj.getLunarYear(), "農曆月": lunar_m[int(day_obj.getLunarMonth())],
                    "月": day_obj.getLunarMonth(), "日": day_obj.getLunarDay()}
        except:
            pass
    return {"年": year, "農曆月": "未知", "月": month, "日": day}

# ==================== 五柱核心计算 ====================

def find_lunar_month(year_gz):
    result = multi_key_dict_get(fivetigers, year_gz[0])
    if result is None:
        result = multi_key_dict_get(fivetigers, year_gz[1])
    return dict(zip(range(1, 13), new_list(jiazi(), result)[:12]))

def find_lunar_hour(day_gz):
    result = multi_key_dict_get(fiverats, day_gz[0])
    if result is None:
        result = multi_key_dict_get(fiverats, day_gz[1])
    return dict(zip(list(di_zhi), new_list(jiazi(), result)[:12]))

def find_lunar_ke(hour_gz):
    result = multi_key_dict_get(fivehourses, hour_gz[0])
    if result is None:
        result = multi_key_dict_get(fivehourses, hour_gz[1])
    return new_list(jiazi(), result)

def ke_jiazi_d(zi_hour_gz):
    t = [f"{h}:{m}0" for h in range(24) for m in range(6)]
    zi_ke = find_lunar_ke(zi_hour_gz)
    minutelist = dict(zip(t, cycle(repeat_list(1, zi_ke))))
    return minutelist

def get_month_ganzhi_by_jieqi(year, month, day, hour, minute, year_ganzhi):
    current_jq = jq(year, month, day, hour, minute)
    month_dizhi = jieqi_to_dizhi.get(current_jq, '寅')
    year_gan = year_ganzhi[0]
    start_gan = multi_key_dict_get(fivetigers, year_gan)
    if start_gan is None:
        start_gan = multi_key_dict_get(fivetigers, year_ganzhi[1])
    start_gan = start_gan[0] if start_gan else '丙'
    dizhi_order = ['寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', '子', '丑']
    gan_order = list(tian_gan)
    start_idx = dizhi_order.index('寅')
    current_idx = dizhi_order.index(month_dizhi)
    offset = current_idx - start_idx
    start_gan_idx = gan_order.index(start_gan)
    month_gan = gan_order[(start_gan_idx + offset) % 10]
    return f"{month_gan}{month_dizhi}"

def gangzhi(year, month, day, hour, minute):
    if not SXTWL_AVAILABLE:
        raise ImportError("sxtwl 库未安装")
    cdate = fromSolar(year, month, day)
    ygz = cdate.getYearGZ()
    yTG = "{}{}".format(tian_gan[ygz.tg], di_zhi[ygz.dz])
    dgz = cdate.getDayGZ()
    dTG = "{}{}".format(tian_gan[dgz.tg], di_zhi[dgz.dz])
    hTG_raw = cdate.getHourGZ(hour)
    hTG = "{}{}".format(tian_gan[hTG_raw.tg], di_zhi[hTG_raw.dz])
    mTG = get_month_ganzhi_by_jieqi(year, month, day, hour, minute, yTG)
    # 刻柱:用子时时柱为起点
    zi_hTG_raw = cdate.getHourGZ(0)
    zi_hTG = "{}{}".format(tian_gan[zi_hTG_raw.tg], di_zhi[zi_hTG_raw.dz])
    ke_dict = ke_jiazi_d(zi_hTG)
    m = minute // 10
    key = f"{hour}:{m}0"
    ke_gz = ke_dict.get(key, '未知')
    return [yTG, mTG, dTG, hTG, ke_gz]


# ==================== GUI - 移动端优化版 ====================

class WuzhuGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("五柱十字万年历 v3.2")
        self.root.geometry("900x800")  # 稍微加高,容纳更多按钮
        
        self.setup_styles()
        self.create_ui()
        self.show_current()
    
    def setup_styles(self):
        style = ttk.Style()
        style.theme_use('clam')
        style.configure('Title.TLabelframe', font=('微软雅黑', 10, 'bold'))
        style.configure('Title.TLabelframe.Label', font=('微软雅黑', 10, 'bold'))
        # 增大按钮字体,方便触屏点击
        style.configure('TButton', font=('微软雅黑', 12))
        style.configure('Big.TButton', font=('微软雅黑', 14, 'bold'))
    
    def create_ui(self):
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # ========== 输入面板 ==========
        input_frame = ttk.LabelFrame(main_frame, text="时间输入(点击框可弹出键盘)", 
                                      padding="10", style='Title.TLabelframe')
        input_frame.pack(fill=tk.X, pady=(0, 10))
        
        # === 年月日:用Entry代替Spinbox,并绑定焦点事件 ===
        date_frame = ttk.Frame(input_frame)
        date_frame.pack(pady=5)
        
        # 年
        ttk.Label(date_frame, text="年:", font=('微软雅黑', 12)).pack(side=tk.LEFT, padx=5)
        self.year_var = tk.StringVar(value=str(datetime.now().year))
        self.year_entry = tk.Entry(date_frame, textvariable=self.year_var, 
                                    width=6, font=('微软雅黑', 14), justify='center')
        self.year_entry.pack(side=tk.LEFT, padx=5)
        self.year_entry.bind('<FocusIn>', lambda e: self.on_entry_focus(e))
        
        # 快速年份按钮
        year_btn_frame = ttk.Frame(date_frame)
        year_btn_frame.pack(side=tk.LEFT, padx=5)
        ttk.Button(year_btn_frame, text="-", width=2, command=lambda: self.adjust_year(-1)).pack(side=tk.LEFT)
        ttk.Button(year_btn_frame, text="+", width=2, command=lambda: self.adjust_year(1)).pack(side=tk.LEFT)
        
        # 月
        ttk.Label(date_frame, text="月:", font=('微软雅黑', 12)).pack(side=tk.LEFT, padx=5)
        self.month_var = tk.StringVar(value=str(datetime.now().month))
        self.month_entry = tk.Entry(date_frame, textvariable=self.month_var, 
                                     width=4, font=('微软雅黑', 14), justify='center')
        self.month_entry.pack(side=tk.LEFT, padx=5)
        self.month_entry.bind('<FocusIn>', lambda e: self.on_entry_focus(e))
        
        month_btn_frame = ttk.Frame(date_frame)
        month_btn_frame.pack(side=tk.LEFT, padx=5)
        ttk.Button(month_btn_frame, text="-", width=2, command=lambda: self.adjust_month(-1)).pack(side=tk.LEFT)
        ttk.Button(month_btn_frame, text="+", width=2, command=lambda: self.adjust_month(1)).pack(side=tk.LEFT)
        
        # 日
        ttk.Label(date_frame, text="日:", font=('微软雅黑', 12)).pack(side=tk.LEFT, padx=5)
        self.day_var = tk.StringVar(value=str(datetime.now().day))
        self.day_entry = tk.Entry(date_frame, textvariable=self.day_var, 
                                   width=4, font=('微软雅黑', 14), justify='center')
        self.day_entry.pack(side=tk.LEFT, padx=5)
        self.day_entry.bind('<FocusIn>', lambda e: self.on_entry_focus(e))
        
        day_btn_frame = ttk.Frame(date_frame)
        day_btn_frame.pack(side=tk.LEFT, padx=5)
        ttk.Button(day_btn_frame, text="-", width=2, command=lambda: self.adjust_day(-1)).pack(side=tk.LEFT)
        ttk.Button(day_btn_frame, text="+", width=2, command=lambda: self.adjust_day(1)).pack(side=tk.LEFT)
        
        # === 时分:同样用Entry ===
        time_frame = ttk.Frame(input_frame)
        time_frame.pack(pady=5)
        
        ttk.Label(time_frame, text="时:", font=('微软雅黑', 12)).pack(side=tk.LEFT, padx=5)
        self.hour_var = tk.StringVar(value=f"{datetime.now().hour:02d}")
        self.hour_entry = tk.Entry(time_frame, textvariable=self.hour_var, 
                                    width=4, font=('微软雅黑', 14), justify='center')
        self.hour_entry.pack(side=tk.LEFT, padx=5)
        self.hour_entry.bind('<FocusIn>', lambda e: self.on_entry_focus(e))
        
        hour_btn_frame = ttk.Frame(time_frame)
        hour_btn_frame.pack(side=tk.LEFT, padx=5)
        ttk.Button(hour_btn_frame, text="-", width=2, command=lambda: self.adjust_hour(-1)).pack(side=tk.LEFT)
        ttk.Button(hour_btn_frame, text="+", width=2, command=lambda: self.adjust_hour(1)).pack(side=tk.LEFT)
        
        ttk.Label(time_frame, text="分:", font=('微软雅黑', 12)).pack(side=tk.LEFT, padx=5)
        self.minute_var = tk.StringVar(value=f"{datetime.now().minute:02d}")
        self.minute_entry = tk.Entry(time_frame, textvariable=self.minute_var, 
                                      width=4, font=('微软雅黑', 14), justify='center')
        self.minute_entry.pack(side=tk.LEFT, padx=5)
        self.minute_entry.bind('<FocusIn>', lambda e: self.on_entry_focus(e))
        
        minute_btn_frame = ttk.Frame(time_frame)
        minute_btn_frame.pack(side=tk.LEFT, padx=5)
        ttk.Button(minute_btn_frame, text="-", width=2, command=lambda: self.adjust_minute(-10)).pack(side=tk.LEFT)
        ttk.Button(minute_btn_frame, text="+", width=2, command=lambda: self.adjust_minute(10)).pack(side=tk.LEFT)
        
        # === 快速时间选择按钮(触屏友好)===
        quick_frame = ttk.Frame(input_frame)
        quick_frame.pack(pady=10)
        
        ttk.Button(quick_frame, text="🕐 子时(23-1)", command=lambda: self.set_hour(0), width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(quick_frame, text="🕕 午时(11-13)", command=lambda: self.set_hour(12), width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(quick_frame, text="🕛 当前时间", command=self.show_current, width=12).pack(side=tk.LEFT, padx=2)
        
        # === 主操作按钮 ===
        btn_frame = ttk.Frame(input_frame)
        btn_frame.pack(pady=10)
        
        self.calc_btn = ttk.Button(btn_frame, text="▶ 开始排盘", 
                                    command=self.calculate, width=15, style='Big.TButton')
        self.calc_btn.pack(side=tk.LEFT, padx=10)
        
        self.clear_btn = ttk.Button(btn_frame, text="🗑 清空", 
                                     command=self.clear_result, width=10)
        self.clear_btn.pack(side=tk.LEFT, padx=5)
        
        # ========== 结果显示面板 ==========
        result_frame = ttk.LabelFrame(main_frame, text="排盘结果", 
                                       padding="10", style='Title.TLabelframe')
        result_frame.pack(fill=tk.BOTH, expand=True)
        
        self.result_text = scrolledtext.ScrolledText(
            result_frame, wrap=tk.WORD, font=('微软雅黑', 12),
            width=80, height=25, bg='#f5f5f5'
        )
        self.result_text.pack(fill=tk.BOTH, expand=True)
        
        self.result_text.tag_config('title', font=('微软雅黑', 16, 'bold'), foreground='#2c3e50')
        self.result_text.tag_config('subtitle', font=('微软雅黑', 13, 'bold'), foreground='#34495e')
        self.result_text.tag_config('ganzhi', font=('微软雅黑', 15, 'bold'), foreground='#c0392b')
        self.result_text.tag_config('info', font=('微软雅黑', 11), foreground='#7f8c8d')
        self.result_text.tag_config('correct', font=('微软雅黑', 11), foreground='#27ae60')
        self.result_text.tag_config('big', font=('微软雅黑', 18, 'bold'), foreground='#8e44ad')
    
    # ========== 焦点处理:强制弹出软键盘 ==========
    def on_entry_focus(self, event):
        """Entry获得焦点时的处理"""
        widget = event.widget
        widget.selection_range(0, tk.END)  # 全选文本,方便替换
        # 在手机上,点击Entry通常会弹出键盘,但如果不行,可以尝试:
        # 某些Python IDE需要额外的处理
    
    # ========== 数值调整按钮 ==========
    def adjust_year(self, delta):
        try:
            v = int(self.year_var.get()) + delta
            self.year_var.set(str(v))
        except:
            pass
    
    def adjust_month(self, delta):
        try:
            v = int(self.month_var.get()) + delta
            if 1 <= v <= 12:
                self.month_var.set(str(v))
        except:
            pass
    
    def adjust_day(self, delta):
        try:
            v = int(self.day_var.get()) + delta
            if 1 <= v <= 31:
                self.day_var.set(str(v))
        except:
            pass
    
    def adjust_hour(self, delta):
        try:
            v = int(self.hour_var.get()) + delta
            v = v % 24
            self.hour_var.set(f"{v:02d}")
        except:
            pass
    
    def adjust_minute(self, delta):
        try:
            v = int(self.minute_var.get()) + delta
            v = max(0, min(59, v))
            self.minute_var.set(f"{v:02d}")
        except:
            pass
    
    def set_hour(self, h):
        """快速设置小时"""
        self.hour_var.set(f"{h:02d}")
        self.minute_var.set("00")
    
    # ========== 核心功能 ==========
    def show_current(self):
        now = datetime.now(pytz.timezone('Asia/Hong_Kong'))
        self.year_var.set(str(now.year))
        self.month_var.set(str(now.month))
        self.day_var.set(str(now.day))
        self.hour_var.set(f"{now.hour:02d}")
        self.minute_var.set(f"{now.minute:02d}")
        self.calculate()
    
    def calculate(self):
        try:
            year = int(self.year_var.get())
            month = int(self.month_var.get())
            day = int(self.day_var.get())
            hour = int(self.hour_var.get())
            minute = int(self.minute_var.get())
            
            if year < 0 or year > 9999:
                messagebox.showerror("错误", f"年份必须在0-9999之间")
                return
            
            try:
                datetime(year, month, day)
            except ValueError:
                messagebox.showerror("错误", f"日期无效:{year}-{month}-{day}")
                return
            
            gz = gangzhi(year, month, day, hour, minute)
            current_jq = jq(year, month, day, hour, minute)
            jq_info = get_jieqi_start_date(year, month, day, hour, minute)
            next_jq_info = get_next_jieqi_start_date(year, month, day, hour, minute)
            lunar = lunar_date_d(year, month, day)
            
            self.display_result(year, month, day, hour, minute, gz, current_jq, jq_info, next_jq_info, lunar)
            
        except ImportError as e:
            messagebox.showerror("错误", str(e) + "\n请安装sxtwl库:pip install sxtwl")
        except Exception as e:
            messagebox.showerror("错误", f"排盘失败:{str(e)}")
    
    def display_result(self, year, month, day, hour, minute, gz, current_jq, jq_info, next_jq_info, lunar):
        self.result_text.delete(1.0, tk.END)
        
        self.result_text.insert(tk.END, "=" * 50 + "\n", 'title')
        self.result_text.insert(tk.END, "      五柱十字干支万年历\n", 'title')
        self.result_text.insert(tk.END, "=" * 50 + "\n\n", 'title')
        
        self.result_text.insert(tk.END, "【公历时间】\n", 'subtitle')
        self.result_text.insert(tk.END, "-" * 35 + "\n")
        self.result_text.insert(tk.END, f"{year}{month}{day}{hour:02d}:{minute:02d}\n")
        weekday = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
        wd = datetime(year, month, day).weekday()
        self.result_text.insert(tk.END, f"{weekday[wd]}\n\n")
        
        self.result_text.insert(tk.END, "【农历】\n", 'subtitle')
        self.result_text.insert(tk.END, "-" * 35 + "\n")
        if lunar.get("農曆月") != "未知":
            self.result_text.insert(tk.END, f"{lunar['年']}{lunar['農曆月']} {lunar['日']}{hour:02d}:{minute:02d}\n")
            weekday = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
            wd = datetime(year, month, day).weekday()
            self.result_text.insert(tk.END, f"{weekday[wd]}\n\n")
        else:
            self.result_text.insert(tk.END, "(需安装sxtwl库)\n\n")
        
        self.result_text.insert(tk.END, "【节气】\n", 'subtitle')
        self.result_text.insert(tk.END, "-" * 35 + "\n")
        self.result_text.insert(tk.END, f"当前:{current_jq}\n")
        self.result_text.insert(tk.END, f"开始:{next_jq_info['年']}-{jq_info['月']}-{jq_info['日']} {jq_info['时']:02d}:{jq_info['分']:02d}\n")
        self.result_text.insert(tk.END, f"下一节气:{next_jq_info['节气']} {next_jq_info['年']}-{next_jq_info['月']}-{next_jq_info['日']} {next_jq_info['时']}:{next_jq_info['分']}\n\n")
        
        self.result_text.insert(tk.END, "【五柱十字】\n", 'subtitle')
        self.result_text.insert(tk.END, "-" * 35 + "\n")
        
        zhu_names = ["年柱", "月柱", "日柱", "时柱", "刻柱"]
        for i, name in enumerate(zhu_names):
            if i < len(gz) and gz[i]:
                self.result_text.insert(tk.END, f"{name}:", 'info')
                self.result_text.insert(tk.END, f"{gz[i]}\n", 'big')
        
        self.result_text.insert(tk.END, "\n【完整格式】\n", 'subtitle')
        self.result_text.insert(tk.END, "-" * 35 + "\n")
        full_str = "  ".join([g for g in gz if g])
        self.result_text.insert(tk.END, f"{full_str}\n\n", 'ganzhi')
        
        self.result_text.insert(tk.END, "【纳音五行】\n", 'subtitle')
        self.result_text.insert(tk.END, "-" * 35 + "\n")
        for i, name in enumerate(zhu_names):
            if i < len(gz) and gz[i]:
                nayin = nayin_dict.get(gz[i], '未知')
                self.result_text.insert(tk.END, f"{name}{gz[i]}{nayin}\n", 'info')
        
        self.result_text.insert(tk.END, "\n" + "=" * 50 + "\n", 'info')
        self.result_text.insert(tk.END, "【说明】\n", 'info')
        self.result_text.insert(tk.END, "刻柱以当日子时为五马遁起点\n", 'correct')
        self.result_text.insert(tk.END, "仅供国学文化研究参考\n", 'info')
        self.result_text.insert(tk.END, "=" * 50 + "\n")
    
    def clear_result(self):
        self.result_text.delete(1.0, tk.END)


def main():
    root = tk.Tk()
    app = WuzhuGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()



更多推荐