简体   繁体   English

tkinter 网格重叠

[英]tkinter grid overlapping

I am building a calendar that allows the user to cycle through the months and years by pressing the buttons created of the previous month and next month.我正在构建一个日历,允许用户通过按下上个月和下个月创建的按钮来循环浏览月份和年份。 Essentially what I want the main window to do is update with the new month upon clicking PREV or NEXT month with the correct days, which it does, only issue is the day buttons that display the specific days of the month overlap when cycling through.本质上,我希望主要的 window 做的是在单击 PREV 或 NEXT 月份并使用正确的日期更新新月份,它确实如此,唯一的问题是显示月份特定日期的日期按钮在循环时重叠。 Below is the part where I am having issues:以下是我遇到问题的部分:

def prevMonth(self):
        try:
            self.grid_forget()
            #SHOULD REFRESH THE WINDOW SO BUTTONS DONT OVERLAP
            print "forgeting" 

        except:
            print "passed the forgetting"
            pass
        lastMonth = self.month - 1 
        self.month = lastMonth
        self.curr_month()

    def nextMonth(self):
        try:
            self.grid_forget()
            #SHOULD REFRESH THE WINDOW SO BUTTONS DONT OVERLAP
            print "forgeting"

        except:
            print "passed the forgetting"
            pass
        nextMonth = self.month + 1
        self.month = nextMonth
        self.curr_month()

When the program iterates between the months the grid does not refresh it just overlaps the days and months.当程序在月份之间迭代时,网格不会刷新它只是与日期和月份重叠。 I have tried EVERYTHING I found in my hours of research.我已经尝试了我在研究中发现的一切。 "self.destroy()" merely creates a blank window. "self.grid.destroy()" returns and error that function has no attribute destroy. “self.destroy()”仅创建一个空白 window。“self.grid.destroy()”返回错误,function 没有属性 destroy。 I have tried making the children of grid all global variables within self and I cant iterate through the months correctly so the set up is permanent but I feel like I am missing something simple as far as working with refreshing the grid and reprinting the based upon the updated month.我已经尝试让网格的子项成为自我中的所有全局变量,但我无法正确地迭代几个月,因此设置是永久性的,但我觉得我缺少一些简单的东西,比如刷新网格并重新打印基于更新月份。

Can you please point me in the right direction or correct the error I am missing?你能指出我正确的方向或纠正我遗漏的错误吗?

below is the entire program下面是整个程序

from Tkinter import *
from calendar import *
import datetime

class Application(Frame):

def __init__(self, master=None):
    Frame.__init__(self, master)
    self.grid()
    DateNow = datetime.datetime.now()
    self.year = DateNow.year#declaring global variable year
    self.month = DateNow.month#declaring global variable month
    self.curr_month()



def curr_month(self):
    try:#iterating the month and year backward if index is out of range
        if self.month == 0:
            self.month = 12
            trueYear = int(self.year)
            self.year = trueYear - 1
    except:
        pass
    try:#iterating month and year forward if index is out of range
        if self.month == 13:
            self.month = 1
            trueYear = int(self.year)
            self.year = trueYear + 1
    except:
        pass


    days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
#create labels


    self.label = Label(self, text=months[self.month - 1])#displaying month
    self.label.grid(row=0, column = 1)
    self.label = Label(self, text=self.year)#displaying year
    self.label.grid(row=0, column = 6)


    try:#displaying previous month
        prevMonthBut = Button(self, text=months[self.month-2], command=self.prevMonth)
        prevMonthBut.grid(row=0,column=0)
    except:#USED ONLY IF PREVIOUS MONTH IS IN PREVIOUS YEAR
        prevMonthBut = Button(self, text=months[11], command=self.prevMonth)
        prevMonthBut.grid(row=0,column=0)
    try:#displaying next month 
        nextMonthBut = Button(self, text=months[self.month], command=self.nextMonth)
        nextMonthBut.grid(row=0,column=2)
    except:#USED ONLY IF NEXT MONTH IS IN NEXT YEAR
        nextMonthBut = Button(self, text=months[0], command=self.nextMonth)
        nextMonthBut.grid(row=0,column=2)
    for i in range(7):
        self.label = Label(self, text=days[i])
        self.label.grid(row = 1, column = i)

    weekday, numDays = monthrange(self.year, self.month)
    week = 2
    for i in range(1, numDays + 1):
        self.button = Button(self, text = str(i))
        self.button.grid(row = week, column = weekday)

        weekday += 1

        if weekday > 6:
            week += 1
            weekday = 0


def prevMonth(self):
    try:
        self.grid_forget()
        #SHOULD REFRESH THE WINDOW SO BUTTONS DONT OVERLAP
        print "forgeting" 

    except:
        print "passed the forgetting"
        pass
    lastMonth = self.month - 1 
    self.month = lastMonth
    self.curr_month()

def nextMonth(self):
    try:
        self.grid_forget()
        #SHOULD REFRESH THE WINDOW SO BUTTONS DONT OVERLAP
        print "forgeting"

    except:
        print "passed the forgetting"
        pass
    nextMonth = self.month + 1
    self.month = nextMonth
    self.curr_month()

mainWindow = Tk()
obj = Application()
mainWindow.mainloop()here

This is a modified version of the proposed answer that also includes the original desired intent of allowing the user to cycle through the months and will also increment the year. 这是建议答案的修改版本,其中还包括允许用户循环使用月份并增加年份的最初预期意图。

from calendar import *
import datetime
try:
    from tkinter import *   # Python 3.x
except:
    from Tkinter import *   # Python 2.x


class Application(Frame):

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid(row=0, column=0, sticky='news')
        DateNow = datetime.datetime.now()
        self.month = int(DateNow.month)
        self.year = int(DateNow.year)
        self.createDaysOfWeekLabels()

        # Create frames and button controls for previous, current and next month.
        self.frameList = []    # List that contains the frame objects.
        self.buttonList = []   # List that contains the button objects.
        self.split()

    def split(self):
        month_name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        leftArrow = Button(self, text="<", command=self.prevMonth)
        leftArrow.grid(row = 0, column = 0)
        rightArrow = Button(self, text=">", command=self.nextMonth)
        rightArrow.grid(row = 0, column = 1)
        for i in range(3):
            try:
                print i, "this is i"
                print self.month
                mFrame = Frame(self)
                self.createMonth(mFrame)
                self.frameList.append(mFrame)
                mButton = Button(self, text=month_name[self.month-1])
                mButton['command'] = lambda f=mFrame, b=mButton: self.showMonth(f, b)
                mButton.grid(row=1, column=i)
                # Grid each frame
                mFrame.grid(row=3, column=0, columnspan=7, sticky='news')
                if (i == 1):
                    mButton['relief'] = 'flat'
                else:
                    mButton.grid_remove()
                    # Remove all but the ith frame. More efficient to remove than forget and configuration is remembered.
                    mFrame.grid_remove()          
                self.buttonList.append(mButton)

            except:
                pass
        # Create year widget at top right of top frame
        label = Label(self, text=self.year)#displaying year
        label.grid(row=0, column=6)
        print "-------------------"

    def prevMonth(self):

        self.month -= 1
        print self.month, "this is month in PREV"
        if self.month <= 0:
            self.month = 12
            print self.month, "month inside forinif in PREVMONTH"
            self.year -= 1
        elif self.month >= 13:
            self.month = 0
            print self.month, "month inside forinelif in PREVMONTH"
            self.year += 1
        self.split()

    def nextMonth(self):

        self.month += 1
        print self.month, "this is month in NEXT"
        for frame in self.frameList:
            frame.grid_remove()

        if self.month <= -1:
            self.month = 11
            print self.month, "month inside forinif in NEXTMONTH"
            self.year -= 1
        elif self.month >= 13:
            self.month = 1
            print self.month, "month inside forinelif in NEXTMONTH"
            self.year += 1
        self.split()


    def createDaysOfWeekLabels(self):
        days = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
        for i in range(7):
            label = Label(self, text=days[i], width = 3)
            label.grid(row = 2, column = i)

    def showMonth(self, mFrame, mButton):
        # Display all buttons normally
        for button in self.buttonList:
            button['relief'] = 'raised'

        # Set this month's button relief to flat
        mButton['relief'] = 'flat'

        # Hide all frames
        for mframe in self.frameList:
            mframe.grid_remove()

        mFrame.grid()

    def createMonth(self, mFrame):

        weekday, numDays = monthrange(self.year, self.month)
        week = 0
        for i in range(1, numDays + 1):
            button = Button(mFrame, text = str(i), width=3)
            button.grid(row = week, column = weekday)

            weekday += 1

            if weekday > 6:
                week += 1
                weekday = 0

mainWindow = Tk()
obj = Application(mainWindow)
mainWindow.mainloop()

Tkinter is fairly efficient. Tkinter非常有效。 And for the number of widgets that you have, it won't impact performance much to create them all initially. 对于您拥有的小部件数量,最初创建它们不会对性能产生太大影响。 Here is a sample that works about like what you were trying to do. 这是一个与您尝试执行的操作类似的示例。

from calendar import *
import datetime
try:
    from tkinter import *   # Python 3.x
except:
    from Tkinter import *   # Python 2.x


class Application(Frame):

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid(row=0, column=0, sticky='news')

        DateNow = datetime.datetime.now()
        month = int(DateNow.month)
        year = int(DateNow.year)
        self.createDaysOfWeekLabels()
        month_name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        # Create frames and button controls for previous, current and next month.
        self.frameList = []    # List that contains the frame objects.
        self.buttonList = []   # List that contains the button objects.
        amonth = month - 1
        for i in range(3):
            if amonth < 0:
                amonth = 11
                year -= 1
            elif amonth == 12:
                amonth = 0
                year += 1

            mFrame = Frame(self)
            self.createMonth(mFrame, amonth, year)
            self.frameList.append(mFrame)
            mButton = Button(self, text=month_name[amonth-1])
            mButton['command'] = lambda f=mFrame, b=mButton: self.showMonth(f, b)
            mButton.grid(row=0, column=i)
            # Grid each frame
            mFrame.grid(row=2, column=0, columnspan=7, sticky='news')
            if (i == 1):
                mButton['relief'] = 'flat'
            else:
                # Remove all but the ith frame. More efficient to remove than forget and configuration is remembered.
                mFrame.grid_remove()
            self.buttonList.append(mButton)
            amonth += 1

        # Create year widget at top left of top frame
        label = Label(self, text=year)#displaying year
        label.grid(row=0, column=6)


    def createDaysOfWeekLabels(self):
        days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
        for i in range(7):
            label = Label(self, text=days[i])
            label.grid(row = 1, column = i)

    def showMonth(self, mFrame, mButton):
        # Display all buttons normally
        for button in self.buttonList:
            button['relief'] = 'raised'

        # Set this month's button relief to flat
        mButton['relief'] = 'flat'

        # Hide all frames
        for frame in self.frameList:
            frame.grid_remove()

        mFrame.grid()

    def createMonth(self, mFrame, month, year):
        weekday, numDays = monthrange(year, month)
        week = 0
        for i in range(1, numDays + 1):
            button = Button(mFrame, text = str(i), width=3)
            button.grid(row = week, column = weekday)

            weekday += 1

            if weekday > 6:
                week += 1
                weekday = 0

mainWindow = Tk()
obj = Application(mainWindow)
mainWindow.mainloop()

Use something like [yourWidget].grid(row=0, column=0, columnspan=4)使用类似 [yourWidget].grid(row=0, column=0, columnspan=4)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM