Python Tkinter |自定义小部件:无限(水平)滚动日历 上下文

Python Tkinter |自定义小部件:无限(水平)滚动日历 上下文,python,tkinter,calendar,infinite-scroll,tkinter-canvas,Python,Tkinter,Calendar,Infinite Scroll,Tkinter Canvas,我正在尝试创建具有以下属性/功能的自定义日历(Tkinter小部件): 每个列代表1天 每一行将代表一个人 它有无限水平滚动->所以它可以无限地回到过去和现在 日历中的单元格(框)将是交互式的,如果我按住鼠标左键,我可以选择特定的单元格进行进一步的操作/功能 它看起来像这样: (请注意:左侧的红色列将是一个单独的框架小部件。我只是将其包含在草图中,以显示日历中各行的用途) 我的计划 为了能够在构建日历后与单元格交互,我计划将每个小部件对象存储在一个名为self.cells的数组中 也因为

我正在尝试创建具有以下属性/功能的自定义日历(Tkinter小部件):

  • 每个代表1天
  • 每一行将代表一个人
  • 它有无限水平滚动->所以它可以无限地回到过去和现在
  • 日历中的单元格(框)将是交互式的,如果我按住鼠标左键,我可以选择特定的单元格进行进一步的操作/功能
它看起来像这样:

(请注意:左侧的红色列将是一个单独的框架小部件。我只是将其包含在草图中,以显示日历中各行的用途)


我的计划 为了能够在构建日历后与单元格交互,我计划将每个小部件对象存储在一个名为
self.cells
的数组中

也因为我希望它无限地过去和将来,在初始化时,日历滚动条将在中间。< /P>


我的进度(代码)


问题 如何实现无限滚动效果?我不知道如何使它工作


杂记
  • Python 3,64位
  • Windows 7,64位


编辑#1-创建
addFuture()
函数 这个
addFuture()
函数只是稍微修改了
set()
函数。可以多次调用
addFuture()
,每次都会将
天数添加到日历中。只需要把滚动条连接起来。但是,我应该如何
添加过去()


编辑#2-无限滚动到未来作品! 每当用户拖动滚动条时,就会调用
onFrameConfigure
命令,因此我添加了
if self.scrollbar.get()[1]>0.9:
语句,以检查滚动条的x轴是否越来越靠近最右端。如果是的话,它会执行一个增加天数的功能,滚动条会自动重新调整刻度(我不知道为什么,但它能工作)

因此,我的窗口有无限的滚动到未来。我现在的问题是如何使它无限滚动到过去(即左侧)?


当滚动条靠近左侧时,我可以使用以下语句检测滚动条:
if self.scrollbar.get()[1]<0.1:
。但是,我需要的是某种类型的
self.addpass()
命令,它与
self.addFuture()
命令的作用相同,但是(顾名思义)在左侧添加天数。

您要做的是确保画布始终有足够的列向右或向左滚动整个屏幕。首先要做的是从这么多列开始。如果希望每列为100像素,而画布本身为400像素,则总共需要1200像素的列:左侧4列,右侧4列,可见列

接下来,为scrollbar创建一个代理——一个在拖动scrollbar时调用的自定义命令。它应该做的第一件事是调用画布的
xview
方法来进行实际的滚动。然后,滚动画布后,您需要计算是否需要在右侧或左侧添加更多列以始终维护缓冲区


在右侧或左侧添加任何新列后,需要重新计算画布的
scrollregion
。当您这样做时,tkinter将自动调整滚动条拇指的位置和大小inf/2我们将得到
inf
的值。这也适用于inf/8754339。似乎无限有点大。我想知道有多大,所以我数到无穷大。等我讲完,我会发表评论,告诉你们它有多大。@EthanK:好吧,但我不会屏住呼吸的<代码>;请将您的问题限制为一个问题。请检查我的编辑#2*。我设法使它在不重新计算
scrollregion
的情况下工作(我认为它以某种方式重新计算了
scrollregion
,但我甚至不知道在哪里或如何计算)。至于滚动条的代理,我已经方便地在代码中的
onFrameConfigure(self,event)
下找到了它。现在,我有一个问题要向left@ProgramerBeginner:你说你不知道滚动条是如何重新配置的,但你显然是在重置
scrollregion
。好吧,代码的某些部分是从其他帖子复制粘贴的,我做了一些随机的事情使它工作,所以是的,代码可能正在重置
滚动区域
,但是不,我不知道代码中的方式或位置。
import tkinter as tk
import datetime

CELL_SIZE = (100, 50)
FIRST_ROW_HEIGHT = 20

class Cell(tk.Canvas):
    def __init__(self, root,
        width = CELL_SIZE[0],
        height = CELL_SIZE[1],
        highlightthickness = 1,
        background = 'white',
        highlightbackground = 'black',
        highlightcolor = 'red',
        *args, **kwargs):

        tk.Canvas.__init__(self, root,
            width = width,
            height = height,
            background = background,
            highlightthickness = highlightthickness,
            highlightbackground = highlightbackground,
            highlightcolor = highlightcolor,
            *args, **kwargs)

class Calendar(tk.Frame):
    def __init__(self, root, rows=0, *args, **kwargs):
        tk.Frame.__init__(self, root, *args, **kwargs)

        # create the canvas and frame
        self.calendar_canvas = tk.Canvas(self)
        self.calendar_frame = tk.Frame(self.calendar_canvas)
        self.calendar_canvas.create_window((4,4), window=self.calendar_frame, anchor="nw", tags="self.calendar_frame")
        self.calendar_canvas.pack(side="top", fill="both", expand=True)

        # building scrollbar
        self.scrollbar = tk.Scrollbar(self, orient='horizontal', command=self.calendar_canvas.xview)
        self.scrollbar.pack(side="bottom", fill="x")

        # hooking up scrollbar
        self.calendar_canvas.configure(xscrollcommand=self.scrollbar.set)
        self.calendar_frame.bind("<Configure>", self.onFrameConfigure)

        # variables
        self.rows = rows
        self.cells = []


    def onFrameConfigure(self, event):
        self.calendar_canvas.configure(scrollregion=self.calendar_canvas.bbox("all"))

    def set(self, day=0):
        today = datetime.date.today()

        for i in range(day):
            self.cells.append([])

            # create first row (indicating the date)
            cell = Cell(self.calendar_frame, height=FIRST_ROW_HEIGHT)
            cell.grid(row=0, column=i)

            # add the date label into the first row
            cell.create_text(
                CELL_SIZE[0]/2,
                FIRST_ROW_HEIGHT/2,
                text = (today + datetime.timedelta(days=i)).strftime('%d/%m/%y'))

            for c in range(self.rows):
                cell = Cell(self.calendar_frame)
                cell.grid(row=c+1, column=i)

                self.cells[i].append(cell)
root = tk.Tk()
calendar = Calendar(root, rows=3)
calendar.set(day=10)
calendar.pack(fill='both', expand=True)
root.mainloop()
# under class Calendar:
def addFuture(self, day=0):
    today = datetime.date.today()

    for i in range(day):
        index = i + self.lastColumn
        self.cells.append([])

        # create first row (indicating the date)
        cell = Cell(self.calendar_frame, height=FIRST_ROW_HEIGHT)
        cell.grid(row=0, column=index)

        # add the date label into the first row
        cell.create_text(
            CELL_SIZE[0]/2,
            FIRST_ROW_HEIGHT/2,
            text = (today + datetime.timedelta(days=index)).strftime('[%a] %d/%m/%y'))

        for c in range(self.rows):
            cell = Cell(self.calendar_frame)
            cell.grid(row=c+1, column=index)

            self.cells[i].append(cell)

    self.lastColumn = self.lastColumn + day
def onFrameConfigure(self, event):
    self.calendar_canvas.configure(scrollregion=self.calendar_canvas.bbox("all"))
    if self.scrollbar.get()[1] > 0.9:
        self.addFuture(day=10)