使用Python和wxPython创建动态HTML日历生成器

news2024/12/23 23:02:49

在这个数字化时代,日历仍然是我们日常生活中不可或缺的工具。今天,我们将探讨如何使用Python创建一个动态HTML日历生成器。这个项目不仅实用,还能帮助我们深入理解Python编程、GUI开发和网页生成的相关知识。

项目概述

我们的目标是创建一个应用程序,允许用户选择特定的年份和月份,然后生成并显示一个美观的HTML日历。这个日历不仅显示日期,还会包含中国的主要节假日信息。
C:\pythoncode\new\calendarHTML.py
C:\pythoncode\new\calendar_template.html

主要特性包括:

  1. 使用wxPython创建图形用户界面
  2. 动态生成HTML日历
  3. 从XML文件加载节假日信息
  4. 使用内嵌浏览器组件显示生成的HTML

技术栈

  • Python 3.x
  • wxPython: 用于创建图形用户界面
  • Jinja2: 用于HTML模板渲染
  • xml.etree.ElementTree: 用于解析XML文件
  • calendar和datetime模块: 用于日期处理

实现步骤

全部代码:

import wx
import wx.html2
import calendar
import datetime
import xml.etree.ElementTree as ET
from jinja2 import Template

class CalendarFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title='Calendar Generator')
        panel = wx.Panel(self)

        self.year_ctrl = wx.SpinCtrl(panel, min=1900, max=2100, initial=datetime.datetime.now().year)
        self.month_ctrl = wx.Choice(panel, choices=[calendar.month_name[i] for i in range(1, 13)])
        self.month_ctrl.SetSelection(datetime.datetime.now().month - 1)

        generate_btn = wx.Button(panel, label='Generate Calendar')
        generate_btn.Bind(wx.EVT_BUTTON, self.on_generate)

        self.browser = wx.html2.WebView.New(panel)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(wx.StaticText(panel, label="Select Year and Month:"))
        sizer.Add(self.year_ctrl, 0, wx.ALL | wx.EXPAND, 5)
        sizer.Add(self.month_ctrl, 0, wx.ALL | wx.EXPAND, 5)
        sizer.Add(generate_btn, 0, wx.ALL | wx.EXPAND, 5)
        sizer.Add(self.browser, 1, wx.ALL | wx.EXPAND, 5)

        panel.SetSizer(sizer)
        self.SetSize((800, 600))

    def on_generate(self, event):
        year = self.year_ctrl.GetValue()
        month = self.month_ctrl.GetSelection() + 1
        html_content = self.generate_calendar_html(year, month)
        self.browser.SetPage(html_content, "")

    def generate_calendar_html(self, year, month):
        # Load holidays from XML
        holidays = self.load_holidays_from_xml()

        # Generate calendar data
        cal = calendar.monthcalendar(year, month)
        month_name = calendar.month_name[month]

        # Prepare holiday data for the template
        holiday_data = {}
        for date, holiday in holidays.items():
            holiday_date = datetime.datetime.strptime(date, "%Y-%m-%d")
            if holiday_date.year == year and holiday_date.month == month:
                holiday_data[holiday_date.day] = holiday

        # Load and render the HTML template
        with open('calendar_template.html', 'r', encoding='utf-8') as file:
            template = Template(file.read())

        return template.render(
            year=year,
            month=month_name,
            calendar_data=cal,
            holidays=holiday_data
        )

    def load_holidays_from_xml(self):
        holidays = {}
        tree = ET.parse('holidays.xml')
        root = tree.getroot()
        for holiday in root.findall('holiday'):
            date = holiday.find('date').text
            name = holiday.find('name').text
            description = holiday.find('description').text
            holidays[date] = {'name': name, 'description': description}
        return holidays

if __name__ == '__main__':
    app = wx.App()
    frame = CalendarFrame()
    frame.Show()
    app.MainLoop()

1. 创建图形用户界面

首先,我们使用wxPython创建了一个简单的GUI,包含年份选择器、月份下拉列表、生成按钮和一个用于显示HTML的内嵌浏览器组件。

class CalendarFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title='Calendar Generator')
        panel = wx.Panel(self)

        self.year_ctrl = wx.SpinCtrl(panel, min=1900, max=2100, initial=datetime.datetime.now().year)
        self.month_ctrl = wx.Choice(panel, choices=[calendar.month_name[i] for i in range(1, 13)])
        self.month_ctrl.SetSelection(datetime.datetime.now().month - 1)

        generate_btn = wx.Button(panel, label='Generate Calendar')
        generate_btn.Bind(wx.EVT_BUTTON, self.on_generate)

        self.browser = wx.html2.WebView.New(panel)

        # 设置布局...

2. 生成HTML日历

核心功能是根据用户选择的年份和月份生成HTML日历。我们使用Python的calendar模块来获取日历数据,然后使用Jinja2模板引擎渲染HTML。

def generate_calendar_html(self, year, month):
    # 加载节假日信息
    holidays = self.load_holidays_from_xml()

    # 生成日历数据
    cal = calendar.monthcalendar(year, month)
    month_name = calendar.month_name[month]

    # 准备节假日数据
    holiday_data = {}
    for date, holiday in holidays.items():
        holiday_date = datetime.datetime.strptime(date, "%Y-%m-%d")
        if holiday_date.year == year and holiday_date.month == month:
            holiday_data[holiday_date.day] = holiday

    # 加载并渲染HTML模板
    with open('calendar_template.html', 'r', encoding='utf-8') as file:
        template = Template(file.read())

    return template.render(
        year=year,
        month=month_name,
        calendar_data=cal,
        holidays=holiday_data
    )

3. HTML模板设计

我们设计了一个美观的HTML模板,使用CSS来样式化日历。模板包含一个标题区域显示年份和月份,以及一个表格来显示日期和节假日信息。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ month }} {{ year }} 日历</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
        }
        .calendar {
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
            overflow: hidden;
            width: 90%;
            max-width: 800px;
        }
        .header {
            background-color: #4CAF50;
            color: white;
            text-align: center;
            padding: 20px;
        }
        .month-year {
            font-size: 24px;
            font-weight: bold;
        }
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd;
            text-align: center;
            padding: 10px;
        }
        th {
            background-color: #f2f2f2;
        }
        .holiday {
            background-color: #ffebee;
            cursor: pointer;
        }
        .holiday-name {
            font-weight: bold;
            color: #d32f2f;
        }
        .holiday-description {
            font-size: 12px;
            color: #757575;
        }
    </style>
</head>
<body>
    <div class="calendar">
        <div class="header">
            <div class="month-year">{{ month }} {{ year }}</div>
            <img src="https://via.placeholder.com/800x200" alt="月份图片" style="width: 100%; margin-top: 10px;">
        </div>
        <table>
            <tr>
                <th>周日</th>
                <th>周一</th>
                <th>周二</th>
                <th>周三</th>
                <th>周四</th>
                <th>周五</th>
                <th>周六</th>
            </tr>
            {% for week in calendar_data %}
                <tr>
                    {% for day in week %}
                        {% if day != 0 %}
                            {% set date_string = '%d-%02d-%02d'|format(year, loop.index, day) %}
                            {% if date_string in holidays %}
                                <td class="holiday" title="{{ holidays[date_string]['description'] }}">
                                    {{ day }}
                                    <div class="holiday-name">{{ holidays[date_string]['name'] }}</div>
                                    <div class="holiday-description">{{ holidays[date_string]['description'] }}</div>
                                </td>
                            {% else %}
                                <td>{{ day }}</td>
                            {% endif %}
                        {% else %}
                            <td></td>
                        {% endif %}
                    {% endfor %}
                </tr>
            {% endfor %}
        </table>
    </div>
</body>
</html>

4. 加载节假日信息

我们使用XML文件来存储节假日信息,并使用Python的xml.etree.ElementTree模块来解析它。
C:\pythoncode\new\holidays.xml

<?xml version="1.0" encoding="UTF-8"?>
<holidays>
    <holiday>
        <date>2024-01-01</date>
        <name>元旦</name>
        <description>新年的第一天,象征着新的开始</description>
    </holiday>
    <holiday>
        <date>2024-02-10</date>
        <name>春节</name>
        <description>中国最重要的传统节日,家人团聚的日子</description>
    </holiday>
    <holiday>
        <date>2024-04-04</date>
        <name>清明节</name>
        <description>缅怀先人,踏青郊游的节日</description>
    </holiday>
    <holiday>
        <date>2024-05-01</date>
        <name>劳动节</name>
        <description>庆祝劳动者的节日</description>
    </holiday>
    <holiday>
        <date>2024-06-10</date>
        <name>端午节</name>
        <description>赛龙舟,吃粽子的传统节日</description>
    </holiday>
    <holiday>
        <date>2024-09-17</date>
        <name>中秋节</name>
        <description>家人团聚,赏月吃月饼的节日</description>
    </holiday>
    <holiday>
        <date>2024-10-01</date>
        <name>国庆节</name>
        <description>庆祝中华人民共和国成立</description>
    </holiday>
</holidays>

def load_holidays_from_xml(self):
    holidays = {}
    tree = ET.parse('holidays.xml')
    root = tree.getroot()
    for holiday in root.findall('holiday'):
        date = holiday.find('date').text
        name = holiday.find('name').text
        description = holiday.find('description').text
        holidays[date] = {'name': name, 'description': description}
    return holidays

遇到的挑战和解决方案

在开发过程中,我们遇到了一个与Jinja2模板渲染相关的错误。错误信息表明在模板中使用了loop.parent,但在某些情况下它可能不存在。

解决方案是修改HTML模板中的日期处理逻辑:

{% set date_string = '%d-%02d-%02d'|format(year, loop.index, day) %}

我们移除了loop.parent.loop.index,改为直接使用loop.index。这是因为在这个上下文中,loop.index已经给出了正确的月份数字。

同时,我们也优化了Python脚本中的generate_calendar_html方法,预处理节假日数据,只传递当前月份的节假日信息给模板,简化了模板中的日期处理逻辑。

结果:

在这里插入图片描述

结论

通过这个项目,我们不仅创建了一个实用的日历生成器,还学习了如何结合使用多个Python库来创建复杂的应用程序。我们探索了GUI编程、HTML生成、模板渲染和XML解析等多个方面的知识。

这个项目还有很多可以扩展的地方。例如,我们可以添加更多的自定义选项,允许用户选择不同的主题或颜色方案。我们也可以增加导出功能,让用户可以将生成的日历保存为PDF或图片文件。

编程是一个不断学习和改进的过程。通过解决实际问题和克服挑战,我们不仅提高了编程技能,还培养了解决问题的能力。希望这个项目能够激发你的创意,鼓励你尝试开发自己的有趣应用程序!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1931229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二证券:电影暑期档持续升温 农机自动驾驶驶入快车道

农机自动驾驶打开驶入快车道 得益于农机补贴、土地流通、高标准农田制造等方针引导&#xff0c;叠加技术突围和用户降本增效的内生需求&#xff0c;我国正处于农业2.0向农业3.0的过渡阶段。其间农机自动驾驶系统是结束农业3.0&#xff08;即自动化&#xff09;的要害并迎来快速…

【中项第三版】系统集成项目管理工程师 | 第 5 章 软件工程② | 5.4 - 5.8

前言 第 5 章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于技术的内容&#xff0c;学习要以教材为准。 目录 5.4 软件实现 5.4.1 软件配置管理 5.4.2 软件编码 5.4.3 软件测试 5.5 部署交付 5.5.1 软件部署 5.5.2 软件交付 5.5.3 持续交付 5.5.4…

我日常是如何使用LLM工具的:你的LLM工具没用起来,可能是因为方法不对。

引言 我对 Prompt 认知经历了 2 个阶段&#xff1a; 第一阶段&#xff1a;去年 3 月-11 月&#xff0c;我认为 Prompt 最终会灭亡。 第二阶段&#xff1a;去年 12 月至今&#xff0c;我有两个理解&#xff1a; 在主流 LLM 工具(比如 ChatGPT&#xff0c;文心一言等大模型厂商…

dom4j 操作 xml 之按照顺序插入标签

最近学了一下 dom4j 操作 xml 文件&#xff0c;特此记录一下。 public class Dom4jNullTagFiller {public static void main(String[] args) throws DocumentException {SAXReader reader new SAXReader();//加载 xml 文件Document document reader.read("C:\\Users\\24…

leetcode刷题总结——字符串匹配

KMP&#xff08;字符串匹配算法&#xff09; 主串或目标串&#xff1a;比较长的&#xff0c;我们就是在它里面寻找子串是否存在&#xff1b; 子串或模式串&#xff1a;比较短的。 前缀&#xff1a;字符串A和B&#xff0c;A BS&#xff0c;S非空&#xff0c;则B为A的前缀。 …

C++从入门到精通(第2版) 中文电子版

前言 C&#xff08;c plus plus&#xff09;是一种计算机高级程序设计语言&#xff0c;由C语言扩展升级而产生&#xff0c;最早于1979年由本贾尼斯特劳斯特卢普在AT&T贝尔工作室研发。C既可以进行C语言的过程化程序设计&#xff0c;又可以进行以抽象数据类型为特点的基于对…

四、GD32 MCU 常见外设介绍

系统架构 1.RCU 时钟介绍 众所周知&#xff0c;时钟是MCU能正常运行的基本条件&#xff0c;就好比心跳或脉搏&#xff0c;为所有的工作单元提供时间 基数。时钟控制单元提供了一系列频率的时钟功能&#xff0c;包括多个内部RC振荡器时钟(IRC)、一个外部 高速晶体振荡器时钟(H…

Python os模块的强大功能与应用详解

概要 在Python中,os模块提供了与操作系统进行交互的功能,允许我们执行各种操作系统任务,如文件和目录操作、环境变量访问、进程管理等。os模块是标准库的一部分,无需额外安装。本文将详细介绍os模块的功能,并提供相应的示例代码,帮助全面掌握这一强大工具。 os 模块概述…

支付宝低代码搭建电商小程序,无需编程,可视化操作

大家好&#xff0c;我是小悟 在数字化浪潮的推动下&#xff0c;为了更快速、高效地搭建电商小程序&#xff0c;支付宝低代码平台凭借其独特优势&#xff0c;为商家提供了便捷的解决方案。 支付宝低代码平台犹如一座精心打造的智慧工坊&#xff0c;让电商小程序的搭建变得轻而易…

【 香橙派 AIpro评测】烧系统运行部署LLMS大模型跑开源yolov5物体检测并体验Jupyter Lab AI 应用样例(新手入门)

文章目录 一、引言⭐1.1下载镜像烧系统⭐1.2开发板初始化系统配置远程登陆&#x1f496; 远程ssh&#x1f496;查看ubuntu桌面&#x1f496; 远程向日葵 二、部署LLMS大模型&yolov5物体检测⭐2.1 快速启动LLMS大模型&#x1f496;拉取代码&#x1f496;下载mode数据&#x…

【Outlook】从Outlook新版回归经典版全攻略

引言 在微软宣布计划于2024年底淘汰邮件应用&#xff08;Mail app&#xff09;之后&#xff0c;许多用户发现新版Outlook应用&#xff08;Outlook (new)&#xff09;在他们的Windows 11/10系统上自动启动。如果您更倾向于使用经典版Outlook&#xff08;Outlook (classic)&…

大气热力学(11)——热力学图的应用之二(焚风)

本篇文章源自我在 2021 年暑假自学大气物理相关知识时手写的笔记&#xff0c;现转化为电子版本以作存档。相较于手写笔记&#xff0c;电子版的部分内容有补充和修改。笔记内容大部分为公式的推导过程。 文章目录 11.1 焚风的概念11.2 焚风形成的原理11.3 焚风的示意图 11.1 焚风…

Caido——Burpsuite强有力的竞品工具

0x00 最近发现一个burpsuite的竞品&#xff1a;Caido&#xff0c;尝试使用了一下&#xff0c;发现它的功能还是挺强大的&#xff0c;而且在用户体验上&#xff0c;比Burpsuite要好不少&#xff01;和大家分享一下。 Caido是一款用RUST语言编写的代理工具&#xff0c;目前处于…

nftables(7)集合(SETS)

简介 在nftables中&#xff0c;集合&#xff08;sets&#xff09;是一个非常有用的特性&#xff0c;它允许你以集合的形式管理IP地址、端口号等网络元素&#xff0c;从而简化规则的配置和管理。 nftables提供了两种类型的集合&#xff1a;匿名集合和命名集合。 匿名集合&…

捷配总结的SMT工厂安全防静电规则

SMT工厂须熟记的安全防静电规则&#xff01; 安全对于我们非常重要&#xff0c;特别是我们这种SMT加工厂&#xff0c;通常我们所讲的安全是指人身安全。 但这里我们须树立一个较为全面的安全常识就是在强调人身安全的同时亦必须注意设备、产品的安全。 电气&#xff1a; 怎样预…

【顺序表】算法题 --- 力扣

一、移除元素 移除元素 这个题让我们移除数组nums中值为val的元素&#xff0c;最后返回k&#xff08;不是val的元素个数&#xff09; 这样显然我们就不能再创建一个数组来解决这个问题了&#xff0c;只能另辟蹊径 思路&#xff1a;双指针 这里定义两个指针&#xff08;l1&…

【Python】连接MySQL数据库:详细教程与示例代码

文章目录 1. 安装必要的库2. 建立与MySQL的连接3. 执行SQL查询4. 插入数据5. 更新数据6. 删除数据7. 错误处理8. 小结 在数据驱动的开发中&#xff0c;连接数据库是一个至关重要的技能。Python作为一门强大的编程语言&#xff0c;提供了多种方式连接并操作MySQL数据库。本文将详…

nuitka 打包python程序成windows exe可执行文件

参考&#xff1a; https://www.zhihu.com/question/281858271/answer/2466245521 https://www.zhihu.com/question/281858271 https://zhuanlan.zhihu.com/p/689115995 https://blog.csdn.net/Pan_peter/article/details/136411229 下载&#xff1a; pydantic-2.6.1 pydantic-…

通讯的概念

通讯的概念 文章目录 通讯的概念1.通讯的基本概念2. 串行通讯与并行通讯2. 全双工、半双工及单工通讯3. 同步通讯与异步通讯4. 通讯速率 1.通讯的基本概念 通讯是指在嵌入式系统中实现数据交换的技术手段&#xff0c;它涉及到硬件与硬件、硬件与软件之间的信息传输。基本概念包…

OneForAll工具:安装指南、使用方法及常见问题解决(超全)

引言 在网络安全领域&#xff0c;子域名收集是信息收集过程中非常重要的一步。OneForAll 是一款功能强大的子域名收集工具&#xff0c;能够帮助我们高效地进行子域名收集。本文将详细介绍 OneForAll 的安装和使用方法&#xff0c;并解决在使用过程中可能遇到的问题。 1. OneFo…