tkinter的时间选择器

时间:2019-07-15 06:17:21

标签: python tkinter

我正在寻找一种在tkinter应用程序中实现时间选择器的方法。

我可以使用Spinbox小部件并使用@PRMoureu's出色的答案进行验证来实现此功能(可能不是以最佳方式)。我现在所拥有的是这个-

import tkinter as tk

class App(tk.Frame):
    def __init__(self,parent):
        super().__init__(parent)
        self.reg=self.register(self.hour_valid)
        self.hourstr=tk.StringVar(self,'10')
        self.hour = tk.Spinbox(self,from_=0,to=23,wrap=True,validate='focusout',validatecommand=(self.reg,'%P'),invalidcommand=self.hour_invalid,textvariable=self.hourstr,width=2)
        self.reg2=self.register(self.min_valid)
        self.minstr=tk.StringVar(self,'30')
        self.min = tk.Spinbox(self,from_=0,to=59,wrap=True,validate='focusout',validatecommand=(self.reg2,'%P'),invalidcommand=self.min_invalid,textvariable=self.minstr,width=2)
        self.hour.grid()
        self.min.grid(row=0,column=1)
    def hour_invalid(self):
        self.hourstr.set('10')
    def hour_valid(self,input):
        if (input.isdigit() and int(input) in range(24) and len(input) in range(1,3)):
            valid = True
        else:
            valid = False
        if not valid:
            self.hour.after_idle(lambda: self.hour.config(validate='focusout'))
        return valid
    def min_invalid(self):
        self.minstr.set('30')
    def min_valid(self,input):
        if (input.isdigit() and int(input) in range(60) and len(input) in range(1,3)):
            valid = True
        else:
            valid = False
        if not valid:
            self.min.after_idle(lambda: self.min.config(validate='focusout'))
        return valid
root = tk.Tk()
App(root).pack()
root.mainloop()

这似乎是GUI应用程序中非常普遍的要求,因此我认为必须有更标准的方法来实现这一目标。如何以更简洁的方式实现用户选择的时间小部件? 我之所以这样问,是因为我要实现的微小功能是在增加/减少分钟微调框时,如果它循环了,则小时微调框应相应地增大/减小。 我曾想通过设置一个回调函数来实现这一点,但我不知道精确地触发了旋转框的哪个按钮(向上或向下)。

2 个答案:

答案 0 :(得分:1)

您可以根据自己的时间trace进行更改,并采取相应的措施。下面的示例显示了如何在分钟数增加59时自动增加小时;您可以调整并找出减少部分的方法。

import tkinter as tk

class App(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.hourstr=tk.StringVar(self,'10')
        self.hour = tk.Spinbox(self,from_=0,to=23,wrap=True,textvariable=self.hourstr,width=2,state="readonly")
        self.minstr=tk.StringVar(self,'30')
        self.minstr.trace("w",self.trace_var)
        self.last_value = ""
        self.min = tk.Spinbox(self,from_=0,to=59,wrap=True,textvariable=self.minstr,width=2,state="readonly")
        self.hour.grid()
        self.min.grid(row=0,column=1)

    def trace_var(self,*args):
        if self.last_value == "59" and self.minstr.get() == "0":
            self.hourstr.set(int(self.hourstr.get())+1 if self.hourstr.get() !="23" else 0)
        self.last_value = self.minstr.get()

root = tk.Tk()
App(root).pack()
root.mainloop()

答案 1 :(得分:0)

谢谢亨利的代码,它很棒。这是我的扩展秒数:

# You can trace the changes on your minutes and act accordingly. Below sample shows how to automatically increase hour when minutes increases pass 59 and similarly Seconds increase pass 59; you can adapt and figure out how to do the decrease part.

import tkinter as tk

class App(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.hourstr=tk.StringVar(self,'10')
        self.hour = tk.Spinbox(self,from_=0,to=23,wrap=True,textvariable=self.hourstr,width=2,state="readonly")
        self.minstr=tk.StringVar(self,'30')

        self.min = tk.Spinbox(self,from_=0,to=59,wrap=True,textvariable=self.minstr,width=2)    # ,state="readonly"
        self.secstr=tk.StringVar(self,'00')
        self.sec = tk.Spinbox(self,from_=0,to=59,wrap=True,textvariable=self.secstr,width=2) 

        self.last_valueSec = ""
        self.last_value = ""        
        self.minstr.trace("w",self.trace_var)
        self.secstr.trace("w",self.trace_varsec)

        self.hour.grid()
        self.min.grid(row=0,column=1)
        self.sec.grid(row=0,column=2)

    def trace_var(self,*args):
        if self.last_value == "59" and self.minstr.get() == "0":
            self.hourstr.set(int(self.hourstr.get())+1 if self.hourstr.get() !="23" else 0)   
        self.last_value = self.minstr.get()

    def trace_varsec(self,*args):
        if self.last_valueSec == "59" and self.secstr.get() == "0":
            self.minstr.set(int(self.minstr.get())+1 if self.minstr.get() !="59" else 0)
            if self.last_value == "59":
                self.hourstr.set(int(self.hourstr.get())+1 if self.hourstr.get() !="23" else 0)            
        self.last_valueSec = self.secstr.get()

root = tk.Tk()
App(root).pack()
root.mainloop()