百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Python Tkinter日期选择(日历)‘控件’(原创)

toyiye 2024-06-27 00:43 11 浏览 0 评论

前言

Tkinter模块("Tk 接口")是Python的标准Tk GUI工具包的接口

作为一个业余的为方便自己工作的自学者来说,我写的程序都是用TK模块创建GUI。但TK并没有提供日期选择控件。

之前我一直使用网上大神写的日期选择器,如下图


使用起来无法双击选择日期,有一点不方便。

所以我自己用tksheet写了一个日期选择器。


不一定很完美,至少我自己用着还不错,今天分享给大家

# -*- coding:utf-8 -*-

import tkinter as tk
import calendar
import datetime
import tksheet
datetime = calendar.datetime.datetime
timedelta = calendar.datetime.timedelta
class tkcalendar(tk.Toplevel):

    def __init__(self,x,y):
        super().__init__()
        self.setup_UI(x,y)

    def setup_UI(self,x,y):

        self.title('日期选择窗  作者:包家三少')
        ww = 300  # 设置窗口 宽度
        wh = 250  # 设置窗口 高度
        self.geometry("%dx%d+%d+%d" % (ww, wh, x, y))

        calendar.setfirstweekday(firstweekday=6)  # 将星期天设置为一周第一天
        list_date1 = calendar.monthcalendar(datetime.now().year, datetime.now().month)
        list_date = []
        for i in list_date1:  # 替换list_date1列表中 0
            list_date2 = []
            for j in i:
                if j == 0:
                    j = ''
                elif j == 1:
                    j = '01'
                elif j == 2:
                    j = '02'
                elif j == 3:
                    j = '03'
                elif j == 4:
                    j = '04'
                elif j == 5:
                    j = '05'
                elif j == 6:
                    j = '06'
                elif j == 7:
                    j = '07'
                elif j == 8:
                    j = '08'
                elif j == 9:
                    j = '09'

                if len(list_date) <= 7:
                    list_date2.append(j)
            list_date.append(list_date2)

        self.frame1 = tk.Frame(self)
        self.frame1.pack()

        var_year = tk.StringVar()
        self.Spinbox_year = tk.Spinbox(self.frame1, from_=1, to=9999, textvariable=var_year, width=4, font="宋体, 16",
                                       command=self.update_calendar)
        self.Spinbox_year.grid(row=0, column=0, padx=5, pady=5)
        var_year.set(datetime.now().year)
        self.Label_year = tk.Label(self.frame1, text='年', font="宋体, 16")
        self.Label_year.grid(row=0, column=1, padx=5, pady=5)

        var_month = tk.StringVar()
        self.Spinbox_month = tk.Spinbox(self.frame1, from_=1, to=12, textvariable=var_month, width=4, font="宋体, 16",
                                        command=self.update_calendar)
        self.Spinbox_month.grid(row=0, column=2, padx=5, pady=5)
        var_month.set(datetime.now().month)
        self.Label_month = tk.Label(self.frame1, text='月', font="宋体, 16")
        self.Label_month.grid(row=0, column=3, padx=5, pady=5)
        self.var_date_choose = tk.StringVar()
        self.Entry_date_choose = tk.Entry(self.frame1, textvariable=self.var_date_choose)
        self.Entry_date_choose.grid(row=0, column=5, padx=5, pady=5)
        self.Entry_date_choose.grid_forget()

        self.frame2 = tk.Frame(self)
        self.frame2.pack()

        self.sheet = tksheet.Sheet(self.frame2,
                                   page_up_down_select_row=True,
                                   expand_sheet_if_paste_too_big=True,
                                   column_width=35,
                                   startup_select=(0, 1, "rows"),
                                   row_height="1",
                                   headers=['日', '一', "二", '三', '四', '五', '六'],
                                   height=165,  # height and width arguments are optional
                                   width=290,
                                   total_rows=6,  # if you want to set empty sheet dimensions at startup
                                   total_columns=7,
                                   data=list_date
                                   )

        self.sheet.enable_bindings()

        self.sheet.change_theme("light blue")
        self.sheet.highlight_columns([0, 6], bg="light blue", fg="purple")
        self.sheet.readonly_columns(columns=[0], readonly=True, redraw=True)
        self.sheet.font(newfont=("宋体", 12, "normal"), reset_row_positions=True)
        self.sheet.readonly_columns(columns=[0, 1, 2, 3, 4, 5, 6], readonly=True, redraw=True)
        self.sheet.pack(anchor=tk.W)

        def sheet_double_clicked(event):
            self.sure()

        self.sheet.bind('<Double-Button-1>', sheet_double_clicked)

        self.frame3 = tk.Frame(self)
        self.frame3.pack()

        self.Button_sure = tk.Button(self.frame3, text='确定', font="宋体, 12", borderwidth= 2,relief = tk.GROOVE ,command=self.sure)
        self.Button_sure.grid(row=0, column=0, padx=5, pady=5)

        self.Button_today = tk.Button(self.frame3, text='今天', font="宋体, 12", borderwidth= 2,relief = tk.GROOVE , command=self.today)
        self.Button_today.grid(row=0, column=1, padx=5, pady=5)

        self.Button_exit = tk.Button(self.frame3, text='取消', font="宋体, 12",  borderwidth= 2,relief = tk.GROOVE ,command=self.cancel)
        self.Button_exit.grid(row=0, column=2, padx=5, pady=5)
        #--------------------------------------------

    def update_calendar(self):   #更新日历
        row_num1 = self.sheet.get_total_rows()
        if row_num1 > 0:
            for t in range(row_num1):
                self.sheet.delete_row(idx=0, deselect_all=False, redraw=True)
        list_date1 = calendar.monthcalendar(int(self.Spinbox_year.get()), int(self.Spinbox_month.get()))
        print(list_date1, 'ppp')
        list_date = []
        for i in list_date1:  # 替换list_date1列表中 0
            list_date2 = []
            for j in i:
                if j == 0:
                    j = ''
                elif j == 1:
                    j = '01'
                elif j == 2:
                    j = '02'
                elif j == 3:
                    j = '03'
                elif j == 4:
                    j = '04'
                elif j == 5:
                    j = '05'
                elif j == 6:
                    j = '06'
                elif j == 7:
                    j = '07'
                elif j == 8:
                    j = '08'
                elif j == 9:
                    j = '09'
                if len(list_date) <= 7:
                    list_date2.append(j)
            list_date.append(list_date2)
        self.sheet.set_sheet_data(list_date, verify=False)

    def sure(self):
        sure_year = self.Spinbox_year.get()
        sure_month = self.Spinbox_month.get()
	      if len(sure_month) ==1:
        	  sure_month = '0' + sure_month
        sure_day = self.sheet.get_cell_data(self.sheet.get_currently_selected()[0],
                                            self.sheet.get_currently_selected()[1])
        if sure_day =='':return

        else:
            sure_date = sure_year + '-' + sure_month + '-' + sure_day
            self.var_date_choose.set(sure_date)

        self.date_get = [self.Entry_date_choose.get()]  # 设置数据

        self.destroy()  # 销毁窗口


    def today(self):
        to_day =str(datetime.now().strftime("%Y-%m-%d"))
        self.var_date_choose.set(to_day)
        self.date_get = [self.Entry_date_choose.get()]

        self.destroy()  # 销毁窗口today

    def cancel(self):
        self.date_get = None  # 空!
        self.destroy()





if __name__ == '__main__':
    root1 = tkcalendar(300,300)
    root1.wait_window()

测试代码:

# -*- coding: utf-8 -*-
import tkinter as tk
import  tkcalendar

class tkcalendar_test():
    def __init__(self):

        self.setupUI()

    def setupUI(self):
        self.root = tk.Tk()

        # 设置tk窗口在屏幕中心显示
        sw = self.root.winfo_screenwidth()  # 得到屏幕宽度
        sh = self.root.winfo_screenheight()  # 得到屏幕高度
        ww = 200  # 设置窗口 宽度
        wh = 60  # 设置窗口 高度

        x = (sw - ww) / 2
        y = (sh - wh) / 2
        self.root.geometry("%dx%d+%d+%d" % (ww, wh, x, y))

        # --------------------------------------------------------------------------------------------
        self.Frame_row1 = tk.Frame(self.root)
        self.Frame_row1.pack()

        self.var_test = tk.StringVar()
        self.Entry_test = tk.Entry(self.Frame_row1, width=10, textvariable=self.var_test, font="宋体, 12",
                                         justify='center',)
        self.Entry_test.grid(row=0, column=0, padx=5, pady=5)
        # 调用日历控件---------------------------------------------------
        date_choose = lambda: [
            self.var_test.set(date)
            for date in [self.tkcalendar_get_date(self.Entry_test.winfo_rootx(),
                                                  self.Entry_test.winfo_rooty() + 20)]]
        
        self.Button_test = tk.Button(self.Frame_row1, width=2, text='*', font="宋体, 12",
                                         justify='center',
                                     command = date_choose)
        self.Button_test.grid(row=0, column=1, padx=5, pady=5)

        # 调用日历控件---------------------------------------------------



        self.root.mainloop()
#-------------------------------------------------------------
    #这一部分需要复制到 tk窗体代码中
    def tkcalendar_get_date(self,x,y):#x,y位Entry的坐标位置
            # 接收弹窗的数据
            res = self.tkcalendar_ask_date(x,y)
            if res is None: return
            return(res[0])
            #self.var_test.set(res[0])

    def tkcalendar_ask_date(self,x,y):
        inputDialog = tkcalendar.tkcalendar(x,y)
        self.root.wait_window(inputDialog)  # 这一句很重要!!!
        return inputDialog.date_get
#--------------------------------------------------------------
if __name__ == '__main__':
    app = tkcalendar_test()

不足之处,可能调用有点麻烦 需要复制两段代码到tk窗体主程序中,如果有大神能帮我改的更方便调用,万分感谢

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码